From ff19b81296638488719e0e1a48ff5f4602dac571 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 30 Dec 2020 16:41:26 +0100 Subject: [PATCH] Tests improved. --- .../Apps/Indexes/AppsIndex.cs | 8 +- .../Schemas/Indexes/SchemasIndex.cs | 8 +- .../Apps/Indexes/AppsIndexIntegrationTests.cs | 123 +++++++++++++++--- .../Indexes/SchemasIndexIntegrationTests.cs | 20 ++- 4 files changed, 125 insertions(+), 34 deletions(-) diff --git a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs b/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs index 3056ef65d..9c2235935 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsIndex.cs @@ -117,9 +117,9 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes { if (canCache) { - if (replicatedCache.TryGetValue(GetCacheKey(name), out var cached)) + if (replicatedCache.TryGetValue(GetCacheKey(name), out var v) && v is IAppEntity cacheApp) { - return cached as IAppEntity; + return cacheApp; } } @@ -140,9 +140,9 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes { if (canCache) { - if (replicatedCache.TryGetValue(GetCacheKey(appId), out var cached)) + if (replicatedCache.TryGetValue(GetCacheKey(appId), out var v) && v is IAppEntity cachedApp) { - return cached as IAppEntity; + return cachedApp; } } diff --git a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs b/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs index c8c4f95d0..7ac5e503d 100644 --- a/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs +++ b/backend/src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasIndex.cs @@ -65,9 +65,9 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes if (canCache) { - if (replicatedCache.TryGetValue(cacheKey, out var cachedSchema)) + if (replicatedCache.TryGetValue(cacheKey, out var v) && v is ISchemaEntity cachedSchema) { - return cachedSchema as ISchemaEntity; + return cachedSchema; } } @@ -90,9 +90,9 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes if (canCache) { - if (replicatedCache.TryGetValue(cacheKey, out var cachedSchema)) + if (replicatedCache.TryGetValue(cacheKey, out var v) && v is ISchemaEntity cachedSchema) { - return cachedSchema as ISchemaEntity; + return cachedSchema; } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexIntegrationTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexIntegrationTests.cs index 777775e3a..8aa59d9dd 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexIntegrationTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsIndexIntegrationTests.cs @@ -32,6 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes public class GrainEnvironment { private AppContributors contributors = AppContributors.Empty; + private long version = EtagVersion.Empty; public IGrainFactory GrainFactory { get; } = A.Fake(); @@ -56,9 +57,18 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes .Returns(indexGrain); } - public void HandleCommand(AssignContributor contributor) + public void HandleCommand(CreateApp command) { - contributors = contributors.Assign(contributor.ContributorId, Role.Developer); + version++; + + contributors = contributors.Assign(command.Actor.Identifier, Role.Developer); + } + + public void HandleCommand(AssignContributor command) + { + version++; + + contributors = contributors.Assign(command.ContributorId, Role.Developer); } public void VerifyGrainAccess(int count) @@ -77,6 +87,9 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes A.CallTo(() => appEntity.Name) .Returns(AppId.Name); + A.CallTo(() => appEntity.Version) + .Returns(version); + A.CallTo(() => appEntity.Contributors) .Returns(new AppContributors(contributors.ToDictionary())); @@ -108,23 +121,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes try { - var indexes = - cluster.Silos.OfType() - .Select(x => - { - var pubSub = - shouldBreak ? - A.Fake() : - x.SiloHost.Services.GetRequiredService(); - - var cache = - new ReplicatedCache( - new MemoryCache(Options.Create(new MemoryCacheOptions())), - pubSub, - Options.Create(new ReplicatedCacheOptions { Enable = true })); - - return new AppsIndex(env.GrainFactory, cache); - }).ToArray(); + var indexes = GetIndexes(shouldBreak, env, cluster); var appId = env.AppId; @@ -176,5 +173,93 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes await Task.WhenAny(Task.Delay(2000), cluster.StopAllSilosAsync()); } } + + [Theory] + [InlineData(3, false)] + public async Task Should_retrieve_new_app(short numSilos, bool shouldBreak) + { + var env = new GrainEnvironment(); + + var cluster = + new TestClusterBuilder(numSilos) + .AddSiloBuilderConfigurator() + .Build(); + + await cluster.DeployAsync(); + + try + { + var indexes = GetIndexes(shouldBreak, env, cluster); + + var appId = env.AppId; + + foreach (var index in indexes) + { + Assert.Null(await index.GetAppAsync(appId.Id, true)); + Assert.Null(await index.GetAppByNameAsync(appId.Name, true)); + } + + var creatorId = Guid.NewGuid().ToString(); + var creatorToken = new RefToken(RefTokenType.Subject, creatorId); + var createCommand = new CreateApp { Actor = creatorToken, AppId = appId.Id }; + + var commandContext = new CommandContext(createCommand, A.Fake()); + + var randomIndex = indexes[new Random().Next(3)]; + + await indexes[0].HandleAsync(commandContext, x => + { + if (x.Command is CreateApp command) + { + env.HandleCommand(command); + } + + x.Complete(true); + + return Task.CompletedTask; + }); + + foreach (var index in indexes) + { + var appById = await index.GetAppAsync(appId.Id, true); + var appByName = await index.GetAppByNameAsync(appId.Name, true); + + if (index == randomIndex || !shouldBreak) + { + Assert.True(appById?.Contributors.ContainsKey(creatorId)); + Assert.True(appByName?.Contributors.ContainsKey(creatorId)); + } + else + { + Assert.False(appById?.Contributors.ContainsKey(creatorId)); + Assert.False(appByName?.Contributors.ContainsKey(creatorId)); + } + } + } + finally + { + await Task.WhenAny(Task.Delay(2000), cluster.StopAllSilosAsync()); + } + } + + private static AppsIndex[] GetIndexes(bool shouldBreak, GrainEnvironment env, TestCluster cluster) + { + return cluster.Silos.OfType() + .Select(x => + { + var pubSub = + shouldBreak ? + A.Fake() : + x.SiloHost.Services.GetRequiredService(); + + var cache = + new ReplicatedCache( + new MemoryCache(Options.Create(new MemoryCacheOptions())), + pubSub, + Options.Create(new ReplicatedCacheOptions { Enable = true })); + + return new AppsIndex(env.GrainFactory, cache); + }).ToArray(); + } } } diff --git a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs index 855ee88c7..57c03e653 100644 --- a/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs +++ b/backend/tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasIndexIntegrationTests.cs @@ -37,6 +37,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes public class GrainEnvironment { private Schema schema = new Schema("my-schema"); + private long version = EtagVersion.Empty; public IGrainFactory GrainFactory { get; } = A.Fake(); @@ -63,9 +64,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes .Returns(indexGrain); } - public void HandleCommand(AddField addField) + public void HandleCommand(AddField command) { - schema = schema.AddString(schema.Fields.Count + 1, addField.Name, Partitioning.Invariant); + version++; + + schema = schema.AddString(schema.Fields.Count + 1, command.Name, Partitioning.Invariant); } public void VerifyGrainAccess(int count) @@ -76,18 +79,21 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes private ISchemaEntity CreateEntity() { - var appEntity = A.Fake(); + var schemaEntity = A.Fake(); - A.CallTo(() => appEntity.Id) + A.CallTo(() => schemaEntity.Id) .Returns(SchemaId.Id); - A.CallTo(() => appEntity.AppId) + A.CallTo(() => schemaEntity.AppId) .Returns(AppId); - A.CallTo(() => appEntity.SchemaDef) + A.CallTo(() => schemaEntity.Version) + .Returns(version); + + A.CallTo(() => schemaEntity.SchemaDef) .Returns(schema); - return appEntity; + return schemaEntity; } }