Browse Source

More tests

pull/194/head
Sebastian Stehle 9 years ago
parent
commit
d56d148c6d
  1. 3
      src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
  2. 6
      src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
  3. 3
      src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs
  4. 4
      src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
  5. 5
      src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs
  6. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs
  7. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs
  8. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs
  9. 2
      src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
  10. 84
      src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs
  11. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs
  12. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs
  13. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs
  14. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs
  15. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs
  16. 5
      src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs
  17. 2
      src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs
  18. 4
      src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs
  19. 11
      src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs
  20. 4
      src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonSerializer.cs
  21. 13
      src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs
  22. 20
      tests/Benchmarks/Benchmark.cs
  23. 8
      tests/Benchmarks/Program.cs
  24. 8
      tests/Benchmarks/Tests/AppendToEventStore.cs
  25. 8
      tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs
  26. 8
      tests/Benchmarks/Tests/HandleEvents.cs
  27. 8
      tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs
  28. 8
      tests/Benchmarks/Tests/ReadSchemaState.cs
  29. 78
      tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs

3
src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs

@ -6,6 +6,7 @@
// All rights reserved. // All rights reserved.
// ========================================================================== // ==========================================================================
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
@ -42,6 +43,7 @@ namespace Squidex.Domain.Apps.Core.Apps
this.permission = permission; this.permission = permission;
} }
[Pure]
public AppClient Update(AppClientPermission newPermission) public AppClient Update(AppClientPermission newPermission)
{ {
Guard.Enum(newPermission, nameof(newPermission)); Guard.Enum(newPermission, nameof(newPermission));
@ -49,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppClient(name, secret, newPermission); return new AppClient(name, secret, newPermission);
} }
[Pure]
public AppClient Rename(string newName) public AppClient Rename(string newName)
{ {
Guard.NotNullOrEmpty(newName, nameof(newName)); Guard.NotNullOrEmpty(newName, nameof(newName));

6
src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
@ -25,6 +26,7 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
} }
[Pure]
public AppClients Add(string id, AppClient client) public AppClients Add(string id, AppClient client)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));
@ -33,6 +35,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppClients(Inner.Add(id, client)); return new AppClients(Inner.Add(id, client));
} }
[Pure]
public AppClients Add(string id, string secret) public AppClients Add(string id, string secret)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));
@ -40,6 +43,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppClients(Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor))); return new AppClients(Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor)));
} }
[Pure]
public AppClients Revoke(string id) public AppClients Revoke(string id)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));
@ -47,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppClients(Inner.Remove(id)); return new AppClients(Inner.Remove(id));
} }
[Pure]
public AppClients Rename(string id, string newName) public AppClients Rename(string id, string newName)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));
@ -59,6 +64,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppClients(Inner.SetItem(id, client.Rename(newName))); return new AppClients(Inner.SetItem(id, client.Rename(newName)));
} }
[Pure]
public AppClients Update(string id, AppClientPermission permission) public AppClients Update(string id, AppClientPermission permission)
{ {
Guard.NotNullOrEmpty(id, nameof(id)); Guard.NotNullOrEmpty(id, nameof(id));

3
src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps namespace Squidex.Domain.Apps.Core.Apps
@ -25,6 +26,7 @@ namespace Squidex.Domain.Apps.Core.Apps
{ {
} }
[Pure]
public AppContributors Assign(string contributorId, AppContributorPermission permission) public AppContributors Assign(string contributorId, AppContributorPermission permission)
{ {
Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); Guard.NotNullOrEmpty(contributorId, nameof(contributorId));
@ -33,6 +35,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new AppContributors(Inner.SetItem(contributorId, permission)); return new AppContributors(Inner.SetItem(contributorId, permission));
} }
[Pure]
public AppContributors Remove(string contributorId) public AppContributors Remove(string contributorId)
{ {
Guard.NotNullOrEmpty(contributorId, nameof(contributorId)); Guard.NotNullOrEmpty(contributorId, nameof(contributorId));

4
src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs

@ -10,6 +10,7 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics.Contracts;
using System.Linq; using System.Linq;
using Squidex.Infrastructure; using Squidex.Infrastructure;
@ -88,6 +89,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return Build(languages?.Select(x => new LanguageConfig(x)).ToList()); return Build(languages?.Select(x => new LanguageConfig(x)).ToList());
} }
[Pure]
public LanguagesConfig MakeMaster(Language language) public LanguagesConfig MakeMaster(Language language)
{ {
Guard.NotNull(language, nameof(language)); Guard.NotNull(language, nameof(language));
@ -95,6 +97,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new LanguagesConfig(languages, languages[language]); return new LanguagesConfig(languages, languages[language]);
} }
[Pure]
public LanguagesConfig Set(LanguageConfig config) public LanguagesConfig Set(LanguageConfig config)
{ {
Guard.NotNull(config, nameof(config)); Guard.NotNull(config, nameof(config));
@ -102,6 +105,7 @@ namespace Squidex.Domain.Apps.Core.Apps
return new LanguagesConfig(languages.SetItem(config.Language, config), Master?.Language == config.Language ? config : Master); return new LanguagesConfig(languages.SetItem(config.Language, config), Master?.Language == config.Language ? config : Master);
} }
[Pure]
public LanguagesConfig Remove(Language language) public LanguagesConfig Remove(Language language)
{ {
Guard.NotNull(language, nameof(language)); Guard.NotNull(language, nameof(language));

5
src/Squidex.Domain.Apps.Core.Model/Rules/Rule.cs

@ -7,6 +7,7 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.Diagnostics.Contracts;
using Squidex.Infrastructure; using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Rules namespace Squidex.Domain.Apps.Core.Rules
@ -41,6 +42,7 @@ namespace Squidex.Domain.Apps.Core.Rules
this.action = action; this.action = action;
} }
[Pure]
public Rule Enable() public Rule Enable()
{ {
return Clone(clone => return Clone(clone =>
@ -49,6 +51,7 @@ namespace Squidex.Domain.Apps.Core.Rules
}); });
} }
[Pure]
public Rule Disable() public Rule Disable()
{ {
return Clone(clone => return Clone(clone =>
@ -57,6 +60,7 @@ namespace Squidex.Domain.Apps.Core.Rules
}); });
} }
[Pure]
public Rule Update(RuleTrigger newTrigger) public Rule Update(RuleTrigger newTrigger)
{ {
Guard.NotNull(newTrigger, nameof(newTrigger)); Guard.NotNull(newTrigger, nameof(newTrigger));
@ -72,6 +76,7 @@ namespace Squidex.Domain.Apps.Core.Rules
}); });
} }
[Pure]
public Rule Update(RuleAction newAction) public Rule Update(RuleAction newAction)
{ {
Guard.NotNull(newAction, nameof(newAction)); Guard.NotNull(newAction, nameof(newAction));

5
src/Squidex.Domain.Apps.Core.Model/Schemas/AssetsFieldProperties.cs

@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new AssetsField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/BooleanFieldProperties.cs

@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new BooleanField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/DateTimeFieldProperties.cs

@ -94,5 +94,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new DateTimeField(id, name, partitioning, this);
}
} }
} }

2
src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs

@ -57,5 +57,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
} }
public abstract T Accept<T>(IFieldPropertiesVisitor<T> visitor); public abstract T Accept<T>(IFieldPropertiesVisitor<T> visitor);
public abstract Field CreateField(long id, string name, Partitioning partitioning);
} }
} }

84
src/Squidex.Domain.Apps.Core.Model/Schemas/FieldRegistry.cs

@ -17,29 +17,7 @@ namespace Squidex.Domain.Apps.Core.Schemas
private delegate Field FactoryFunction(long id, string name, Partitioning partitioning, FieldProperties properties); private delegate Field FactoryFunction(long id, string name, Partitioning partitioning, FieldProperties properties);
private readonly TypeNameRegistry typeNameRegistry; private readonly TypeNameRegistry typeNameRegistry;
private readonly Dictionary<Type, Registered> fieldsByPropertyType = new Dictionary<Type, Registered>(); private readonly Dictionary<Type, FactoryFunction> fieldsByPropertyType = new Dictionary<Type, FactoryFunction>();
private sealed class Registered
{
private readonly FactoryFunction fieldFactory;
private readonly Type propertiesType;
public Type PropertiesType
{
get { return propertiesType; }
}
public Registered(FactoryFunction fieldFactory, Type propertiesType)
{
this.fieldFactory = fieldFactory;
this.propertiesType = propertiesType;
}
public Field CreateField(long id, string name, Partitioning partitioning, FieldProperties properties)
{
return fieldFactory(id, name, partitioning, properties);
}
}
public FieldRegistry(TypeNameRegistry typeNameRegistry) public FieldRegistry(TypeNameRegistry typeNameRegistry)
{ {
@ -47,69 +25,39 @@ namespace Squidex.Domain.Apps.Core.Schemas
this.typeNameRegistry = typeNameRegistry; this.typeNameRegistry = typeNameRegistry;
Add<BooleanFieldProperties>( RegisterField<AssetsFieldProperties>();
(id, name, partitioning, properties) => RegisterField<BooleanFieldProperties>();
new BooleanField(id, name, partitioning, (BooleanFieldProperties)properties)); RegisterField<DateTimeFieldProperties>();
RegisterField<GeolocationFieldProperties>();
Add<NumberFieldProperties>( RegisterField<JsonFieldProperties>();
(id, name, partitioning, properties) => RegisterField<NumberFieldProperties>();
new NumberField(id, name, partitioning, (NumberFieldProperties)properties)); RegisterField<ReferencesFieldProperties>();
RegisterField<StringFieldProperties>();
Add<StringFieldProperties>( RegisterField<TagsFieldProperties>();
(id, name, partitioning, properties) =>
new StringField(id, name, partitioning, (StringFieldProperties)properties));
Add<JsonFieldProperties>(
(id, name, partitioning, properties) =>
new JsonField(id, name, partitioning, (JsonFieldProperties)properties));
Add<AssetsFieldProperties>(
(id, name, partitioning, properties) =>
new AssetsField(id, name, partitioning, (AssetsFieldProperties)properties));
Add<GeolocationFieldProperties>(
(id, name, partitioning, properties) =>
new GeolocationField(id, name, partitioning, (GeolocationFieldProperties)properties));
Add<ReferencesFieldProperties>(
(id, name, partitioning, properties) =>
new ReferencesField(id, name, partitioning, (ReferencesFieldProperties)properties));
Add<DateTimeFieldProperties>(
(id, name, partitioning, properties) =>
new DateTimeField(id, name, partitioning, (DateTimeFieldProperties)properties));
Add<TagsFieldProperties>(
(id, name, partitioning, properties) =>
new TagsField(id, name, partitioning, (TagsFieldProperties)properties));
typeNameRegistry.MapObsolete(typeof(ReferencesFieldProperties), "DateTime"); typeNameRegistry.MapObsolete(typeof(ReferencesFieldProperties), "DateTime");
typeNameRegistry.MapObsolete(typeof(DateTimeFieldProperties), "References"); typeNameRegistry.MapObsolete(typeof(DateTimeFieldProperties), "References");
} }
private void Add<TFieldProperties>(FactoryFunction fieldFactory) private void RegisterField<T>()
{ {
Guard.NotNull(fieldFactory, nameof(fieldFactory)); typeNameRegistry.Map(typeof(T));
typeNameRegistry.Map(typeof(TFieldProperties));
var registered = new Registered(fieldFactory, typeof(TFieldProperties));
fieldsByPropertyType[registered.PropertiesType] = registered; fieldsByPropertyType[typeof(T)] = (id, name, partitioning, properties) => properties.CreateField(id, name, partitioning);
} }
public Field CreateField(long id, string name, Partitioning partitioning, FieldProperties properties) public Field CreateField(long id, string name, Partitioning partitioning, FieldProperties properties)
{ {
Guard.NotNull(properties, nameof(properties)); Guard.NotNull(properties, nameof(properties));
var registered = fieldsByPropertyType.GetOrDefault(properties.GetType()); var factory = fieldsByPropertyType.GetOrDefault(properties.GetType());
if (registered == null) if (factory == null)
{ {
throw new InvalidOperationException($"The field property '{properties.GetType()}' is not supported."); throw new InvalidOperationException($"The field property '{properties.GetType()}' is not supported.");
} }
return registered.CreateField(id, name, partitioning, properties); return factory(id, name, partitioning, properties);
} }
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/GeolocationFieldProperties.cs

@ -33,5 +33,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new GeolocationField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/JsonFieldProperties.cs

@ -17,5 +17,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new JsonField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/NumberFieldProperties.cs

@ -94,5 +94,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new NumberField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/ReferencesFieldProperties.cs

@ -64,5 +64,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new ReferencesField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/StringFieldProperties.cs

@ -124,5 +124,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new StringField(id, name, partitioning, this);
}
} }
} }

5
src/Squidex.Domain.Apps.Core.Model/Schemas/TagsFieldProperties.cs

@ -48,5 +48,10 @@ namespace Squidex.Domain.Apps.Core.Schemas
{ {
return visitor.Visit(this); return visitor.Visit(this);
} }
public override Field CreateField(long id, string name, Partitioning partitioning)
{
return new TagsField(id, name, partitioning, this);
}
} }
} }

2
src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs

@ -27,7 +27,7 @@ namespace Squidex.Infrastructure.MongoDb
if (attributes.OfType<BsonJsonAttribute>().Any()) if (attributes.OfType<BsonJsonAttribute>().Any())
{ {
var bsonSerializerType = typeof(JsonBsonSerializer<>).MakeGenericType(memberMap.MemberType); var bsonSerializerType = typeof(BsonJsonSerializer<>).MakeGenericType(memberMap.MemberType);
var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer); var bsonSerializer = Activator.CreateInstance(bsonSerializerType, serializer);
memberMap.SetSerializer((IBsonSerializer)bsonSerializer); memberMap.SetSerializer((IBsonSerializer)bsonSerializer);

4
src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonConverter.cs → src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConverter.cs

@ -1,5 +1,5 @@
// ========================================================================== // ==========================================================================
// JsonBsonConverter.cs // BsonJsonConverter.cs
// Squidex Headless CMS // Squidex Headless CMS
// ========================================================================== // ==========================================================================
// Copyright (c) Squidex Group // Copyright (c) Squidex Group
@ -12,7 +12,7 @@ using Newtonsoft.Json.Linq;
namespace Squidex.Infrastructure.MongoDb namespace Squidex.Infrastructure.MongoDb
{ {
public static class JsonBsonConverter public static class BsonJsonConverter
{ {
public static BsonDocument ToBson(this JObject source) public static BsonDocument ToBson(this JObject source)
{ {

11
src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonReader.cs

@ -27,7 +27,9 @@ namespace Squidex.Infrastructure.MongoDb
public override bool Read() public override bool Read()
{ {
if (bsonReader.State == BsonReaderState.Type) if (bsonReader.State == BsonReaderState.Initial ||
bsonReader.State == BsonReaderState.ScopeDocument ||
bsonReader.State == BsonReaderState.Type)
{ {
bsonReader.ReadBsonType(); bsonReader.ReadBsonType();
} }
@ -60,9 +62,11 @@ namespace Squidex.Infrastructure.MongoDb
break; break;
case BsonType.Undefined: case BsonType.Undefined:
SetToken(NewtonsoftJsonToken.Undefined); SetToken(NewtonsoftJsonToken.Undefined);
bsonReader.ReadUndefined();
break; break;
case BsonType.Null: case BsonType.Null:
SetToken(NewtonsoftJsonToken.Null); SetToken(NewtonsoftJsonToken.Null);
bsonReader.ReadNull();
break; break;
case BsonType.String: case BsonType.String:
SetToken(NewtonsoftJsonToken.String, bsonReader.ReadString()); SetToken(NewtonsoftJsonToken.String, bsonReader.ReadString());
@ -93,6 +97,11 @@ namespace Squidex.Infrastructure.MongoDb
} }
} }
if (bsonReader.State == BsonReaderState.Initial)
{
return true;
}
return !bsonReader.IsAtEndOfFile(); return !bsonReader.IsAtEndOfFile();
} }
} }

4
src/Squidex.Infrastructure.MongoDb/MongoDb/JsonBsonSerializer.cs → src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonSerializer.cs

@ -14,11 +14,11 @@ using Newtonsoft.Json.Linq;
namespace Squidex.Infrastructure.MongoDb namespace Squidex.Infrastructure.MongoDb
{ {
public class JsonBsonSerializer<T> : ClassSerializerBase<T> where T : class public class BsonJsonSerializer<T> : ClassSerializerBase<T> where T : class
{ {
private readonly JsonSerializer serializer; private readonly JsonSerializer serializer;
public JsonBsonSerializer(JsonSerializer serializer) public BsonJsonSerializer(JsonSerializer serializer)
{ {
Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(serializer, nameof(serializer));

13
src/Squidex.Infrastructure.MongoDb/States/MongoStateStore.cs

@ -62,12 +62,13 @@ namespace Squidex.Infrastructure.States
try try
{ {
await collection.InsertOneAsync( await collection.UpdateOneAsync(
/*Builders<MongoState<T>>.Filter.And( Builders<MongoState<T>>.Filter.And(
Builders<MongoState<T>>.Filter.Eq(nameof(MongoState<T>.Id), key), Builders<MongoState<T>>.Filter.Eq(x => x.Id, key),
Builders<MongoState<T>>.Filter.Eq(nameof(MongoState<T>.Etag), oldEtag) Builders<MongoState<T>>.Filter.Eq(x => x.Etag, oldEtag)
),*/ ),
new MongoState<T> { Id = key, Etag = newEtag, Doc = value }); Builders<MongoState<T>>.Update.Set(x => x.Doc, value),
Upsert);
} }
catch (MongoWriteException ex) catch (MongoWriteException ex)
{ {

20
tests/Benchmarks/IBenchmark.cs → tests/Benchmarks/Benchmark.cs

@ -8,12 +8,24 @@
namespace Benchmarks namespace Benchmarks
{ {
public interface IBenchmark public abstract class Benchmark
{ {
void RunInitialize(); public virtual void Initialize()
{
}
long Run(); public virtual void RunInitialize()
{
}
void RunCleanup(); public virtual void RunCleanup()
{
}
public virtual void Cleanup()
{
}
public abstract long Run();
} }
} }

8
tests/Benchmarks/Program.cs

@ -16,7 +16,7 @@ namespace Benchmarks
{ {
public static class Program public static class Program
{ {
private static readonly List<(string Name, IBenchmark Benchmark)> Benchmarks = new IBenchmark[] private static readonly List<(string Name, Benchmark Benchmark)> Benchmarks = new Benchmark[]
{ {
new AppendToEventStore(), new AppendToEventStore(),
new AppendToEventStoreWithManyWriters(), new AppendToEventStoreWithManyWriters(),
@ -51,6 +51,8 @@ namespace Benchmarks
Console.WriteLine($"{selected.Name}: Initialized"); Console.WriteLine($"{selected.Name}: Initialized");
selected.Benchmark.Initialize();
for (var run = 0; run < numRuns; run++) for (var run = 0; run < numRuns; run++)
{ {
try try
@ -82,6 +84,10 @@ namespace Benchmarks
{ {
Console.WriteLine($"Benchmark failed with '{e.Message}'"); Console.WriteLine($"Benchmark failed with '{e.Message}'");
} }
finally
{
selected.Benchmark.Cleanup();
}
} }
Console.ReadLine(); Console.ReadLine();

8
tests/Benchmarks/Tests/AppendToEventStore.cs

@ -13,19 +13,19 @@ using Squidex.Infrastructure.CQRS.Events;
namespace Benchmarks.Tests namespace Benchmarks.Tests
{ {
public sealed class AppendToEventStore : IBenchmark public sealed class AppendToEventStore : Benchmark
{ {
private IServiceProvider services; private IServiceProvider services;
private IEventStore eventStore; private IEventStore eventStore;
public void RunInitialize() public override void RunInitialize()
{ {
services = Services.Create(); services = Services.Create();
eventStore = services.GetRequiredService<IEventStore>(); eventStore = services.GetRequiredService<IEventStore>();
} }
public long Run() public override long Run()
{ {
const long numCommits = 100; const long numCommits = 100;
const long numStreams = 20; const long numStreams = 20;
@ -45,7 +45,7 @@ namespace Benchmarks.Tests
return numCommits * numStreams; return numCommits * numStreams;
} }
public void RunCleanup() public override void RunCleanup()
{ {
services.Cleanup(); services.Cleanup();
} }

8
tests/Benchmarks/Tests/AppendToEventStoreWithManyWriters.cs

@ -14,19 +14,19 @@ using Squidex.Infrastructure.CQRS.Events;
namespace Benchmarks.Tests namespace Benchmarks.Tests
{ {
public sealed class AppendToEventStoreWithManyWriters : IBenchmark public sealed class AppendToEventStoreWithManyWriters : Benchmark
{ {
private IServiceProvider services; private IServiceProvider services;
private IEventStore eventStore; private IEventStore eventStore;
public void RunInitialize() public override void RunInitialize()
{ {
services = Services.Create(); services = Services.Create();
eventStore = services.GetRequiredService<IEventStore>(); eventStore = services.GetRequiredService<IEventStore>();
} }
public long Run() public override long Run()
{ {
const long numCommits = 200; const long numCommits = 200;
const long numStreams = 100; const long numStreams = 100;
@ -44,7 +44,7 @@ namespace Benchmarks.Tests
return numCommits * numStreams; return numCommits * numStreams;
} }
public void RunCleanup() public override void RunCleanup()
{ {
services.Cleanup(); services.Cleanup();
} }

8
tests/Benchmarks/Tests/HandleEvents.cs

@ -15,7 +15,7 @@ using Squidex.Infrastructure.States;
namespace Benchmarks.Tests namespace Benchmarks.Tests
{ {
public sealed class HandleEvents : IBenchmark public sealed class HandleEvents : Benchmark
{ {
private const int NumEvents = 5000; private const int NumEvents = 5000;
private IServiceProvider services; private IServiceProvider services;
@ -24,7 +24,7 @@ namespace Benchmarks.Tests
private EventDataFormatter eventDataFormatter; private EventDataFormatter eventDataFormatter;
private MyEventConsumer eventConsumer; private MyEventConsumer eventConsumer;
public void RunInitialize() public override void RunInitialize()
{ {
services = Services.Create(); services = Services.Create();
@ -39,7 +39,7 @@ namespace Benchmarks.Tests
eventConsumerActor.Activate(eventConsumer); eventConsumerActor.Activate(eventConsumer);
} }
public long Run() public override long Run()
{ {
var streamName = Guid.NewGuid().ToString(); var streamName = Guid.NewGuid().ToString();
@ -55,7 +55,7 @@ namespace Benchmarks.Tests
return NumEvents; return NumEvents;
} }
public void RunCleanup() public override void RunCleanup()
{ {
services.Cleanup(); services.Cleanup();
} }

8
tests/Benchmarks/Tests/HandleEventsWithManyWriters.cs

@ -16,7 +16,7 @@ using Squidex.Infrastructure.States;
namespace Benchmarks.Tests namespace Benchmarks.Tests
{ {
public sealed class HandleEventsWithManyWriters : IBenchmark public sealed class HandleEventsWithManyWriters : Benchmark
{ {
private const int NumCommits = 200; private const int NumCommits = 200;
private const int NumStreams = 10; private const int NumStreams = 10;
@ -26,7 +26,7 @@ namespace Benchmarks.Tests
private EventDataFormatter eventDataFormatter; private EventDataFormatter eventDataFormatter;
private MyEventConsumer eventConsumer; private MyEventConsumer eventConsumer;
public void RunInitialize() public override void RunInitialize()
{ {
services = Services.Create(); services = Services.Create();
@ -41,7 +41,7 @@ namespace Benchmarks.Tests
eventConsumerActor.Activate(eventConsumer); eventConsumerActor.Activate(eventConsumer);
} }
public long Run() public override long Run()
{ {
Parallel.For(0, NumStreams, streamId => Parallel.For(0, NumStreams, streamId =>
{ {
@ -62,7 +62,7 @@ namespace Benchmarks.Tests
return NumStreams * NumCommits; return NumStreams * NumCommits;
} }
public void RunCleanup() public override void RunCleanup()
{ {
services.Cleanup(); services.Cleanup();
} }

8
tests/Benchmarks/Tests/ReadSchemaState.cs

@ -22,12 +22,12 @@ using Squidex.Infrastructure.States;
namespace Benchmarks.Tests namespace Benchmarks.Tests
{ {
public class ReadSchemaState : IBenchmark public class ReadSchemaState : Benchmark
{ {
private IServiceProvider services; private IServiceProvider services;
private MyAppState grain; private MyAppState grain;
public void RunInitialize() public override void Initialize()
{ {
services = Services.Create(); services = Services.Create();
@ -84,7 +84,7 @@ namespace Benchmarks.Tests
grain.WriteStateAsync().Wait(); grain.WriteStateAsync().Wait();
} }
public long Run() public override long Run()
{ {
for (var i = 0; i < 10; i++) for (var i = 0; i < 10; i++)
{ {
@ -94,7 +94,7 @@ namespace Benchmarks.Tests
return 10; return 10;
} }
public void RunCleanup() public override void Cleanup()
{ {
services.Cleanup(); services.Cleanup();
} }

78
tests/Squidex.Infrastructure.Tests/MongoDb/BsonConverterTests.cs

@ -7,7 +7,11 @@
// ========================================================================== // ==========================================================================
using System; using System;
using System.IO;
using System.Linq;
using FluentAssertions; using FluentAssertions;
using MongoDB.Bson.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Xunit; using Xunit;
@ -19,14 +23,30 @@ namespace Squidex.Infrastructure.MongoDb
{ {
public class TestObject public class TestObject
{ {
public TimeSpan TimeSpan { get; set; } public bool Bool { get; set; }
public byte Byte { get; set; }
public byte[] Bytes { get; set; }
public string String { get; set; }
public string[] Strings { get; set; }
public float Float32 { get; set; }
public double Float64 { get; set; }
public Uri Uri { get; set; }
public Guid Guid { get; set; } public Guid Guid { get; set; }
public DateTimeOffset DateTimeOffset { get; set; } public TimeSpan TimeSpan { get; set; }
public DateTime DateTime { get; set; } public DateTime DateTime { get; set; }
public DateTimeOffset DateTimeOffset { get; set; }
public Int64 Int64 { get; set; } public Int64 Int64 { get; set; }
public Int32 Int32 { get; set; } public Int32 Int32 { get; set; }
@ -39,25 +59,13 @@ namespace Squidex.Infrastructure.MongoDb
public UInt16 UInt16 { get; set; } public UInt16 UInt16 { get; set; }
public double Float64 { get; set; } public TestObject Nested { get; set; }
public float Float32 { get; set; }
public bool Bool { get; set; } public TestObject[] NestedArray { get; set; }
public byte Byte { get; set; }
public byte[] Bytes { get; set; } public static TestObject CreateWithValues(bool nested = true)
public string String { get; set; }
public string[] Strings { get; set; }
public Uri Uri { get; set; }
public static TestObject CreateWithValues()
{ {
return new TestObject var result = new TestObject
{ {
Bool = true, Bool = true,
Byte = 0x2, Byte = 0x2,
@ -78,16 +86,48 @@ namespace Squidex.Infrastructure.MongoDb
UInt16 = 116, UInt16 = 116,
Uri = new Uri("http://squidex.io") Uri = new Uri("http://squidex.io")
}; };
if (nested)
{
result.Nested = CreateWithValues(false);
result.NestedArray = Enumerable.Repeat(0, 4).Select(x => CreateWithValues(false)).ToArray();
}
return result;
} }
} }
private readonly TestObject source = TestObject.CreateWithValues();
private readonly JsonSerializer serializer = JsonSerializer.CreateDefault();
[Fact] [Fact]
public void Should_serialize_and_deserialize_to_bson_with_json() public void Should_serialize_and_deserialize_to_bson_with_json()
{ {
var source = TestObject.CreateWithValues();
var target = JObject.FromObject(source).ToBson().ToJson().ToObject<TestObject>(); var target = JObject.FromObject(source).ToBson().ToJson().ToObject<TestObject>();
target.ShouldBeEquivalentTo(source); target.ShouldBeEquivalentTo(source);
} }
[Fact]
public void Should_serialize_with_reader_and_writer()
{
var stream = new MemoryStream();
using (var writer = new BsonJsonWriter(new BsonBinaryWriter(stream)))
{
serializer.Serialize(writer, source);
writer.Flush();
}
stream.Position = 0;
using (var reader = new BsonJsonReader(new BsonBinaryReader(stream)))
{
var target = serializer.Deserialize<TestObject>(reader);
target.ShouldBeEquivalentTo(source);
}
}
} }
} }

Loading…
Cancel
Save