From 408f2b2939e2c759dcc404a8ef78872f44dcccd5 Mon Sep 17 00:00:00 2001 From: Damien Daspit Date: Thu, 31 Aug 2023 18:24:51 -0500 Subject: [PATCH] Cleanup data access - remove unnecessary Mongo attributes - fix various coding convention inconsistencies - reimplement upsert support - cleanup integration tests --- Serval.sln | 2 +- src/SIL.DataAccess/DataAccessExtensions.cs | 6 +- src/SIL.DataAccess/IEntity.cs | 2 - src/SIL.DataAccess/IRepository.cs | 1 + src/SIL.DataAccess/MemoryRepository.cs | 43 +- src/SIL.DataAccess/MongoRepository.cs | 12 +- src/SIL.DataAccess/Usings.cs | 1 - src/Serval.Client/Client.g.cs | 6 +- src/Serval.DataFiles/Models/DataFile.cs | 2 - src/Serval.DataFiles/Models/DeletedFile.cs | 2 - src/Serval.DataFiles/Usings.cs | 2 - src/Serval.Shared/Utils/AutoToString.cs | 73 --- .../TranslationEnginesController.cs | 86 ++-- src/Serval.Translation/Models/Build.cs | 2 - src/Serval.Translation/Models/Engine.cs | 2 - .../Models/Pretranslation.cs | 2 - .../Services/EngineService.cs | 14 +- src/Serval.Translation/Usings.cs | 2 - src/Serval.Webhooks/Models/Webhook.cs | 2 - src/Serval.Webhooks/Usings.cs | 3 - .../DataFilesTests.cs | 102 ++-- .../TranslationEngineTests.cs | 443 +++++++----------- .../WebhooksTests.cs | 68 +-- ...rvicesTests.cs => MissingServicesTests.cs} | 2 +- tests/Serval.E2ETests/Serval.E2ETests.csproj | 33 +- .../{E2ETests.cs => ServalApiTests.cs} | 12 +- tests/Serval.E2ETests/Usings.cs | 3 +- tests/Serval.Translation.Tests/Usings.cs | 2 - tests/Serval.Webhooks.Tests/Usings.cs | 2 - 29 files changed, 362 insertions(+), 570 deletions(-) delete mode 100644 src/Serval.Shared/Utils/AutoToString.cs rename tests/Serval.E2ETests/{E2EMissingServicesTests.cs => MissingServicesTests.cs} (99%) rename tests/Serval.E2ETests/{E2ETests.cs => ServalApiTests.cs} (98%) diff --git a/Serval.sln b/Serval.sln index 28d7e7d5..6ef54544 100644 --- a/Serval.sln +++ b/Serval.sln @@ -50,7 +50,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serval.ApiServer.Integratio EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serval.E2ETests", "tests\Serval.E2ETests\Serval.E2ETests.csproj", "{1F020042-D7B8-4541-9691-26ECFD1FFC73}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serval.DataFiles.Tests", "tests\Serval.DataFiles.Tests\Serval.DataFiles.Tests.csproj", "{63E4D71B-11BE-4D68-A876-5B1B5F0A4C88}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serval.DataFiles.Tests", "tests\Serval.DataFiles.Tests\Serval.DataFiles.Tests.csproj", "{63E4D71B-11BE-4D68-A876-5B1B5F0A4C88}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/SIL.DataAccess/DataAccessExtensions.cs b/src/SIL.DataAccess/DataAccessExtensions.cs index 24cc8e9a..d84f9d73 100644 --- a/src/SIL.DataAccess/DataAccessExtensions.cs +++ b/src/SIL.DataAccess/DataAccessExtensions.cs @@ -49,24 +49,26 @@ public static async Task ExistsAsync( this IRepository repo, string id, Action> update, + bool upsert = false, bool returnOriginal = false, CancellationToken cancellationToken = default ) where T : IEntity { - return repo.UpdateAsync(e => e.Id == id, update, returnOriginal, cancellationToken); + return repo.UpdateAsync(e => e.Id == id, update, upsert, returnOriginal, cancellationToken); } public static Task UpdateAsync( this IRepository repo, T entity, Action> update, + bool upsert = false, bool returnOriginal = false, CancellationToken cancellationToken = default ) where T : IEntity { - return repo.UpdateAsync(e => e.Id == entity.Id, update, returnOriginal, cancellationToken); + return repo.UpdateAsync(e => e.Id == entity.Id, update, upsert, returnOriginal, cancellationToken); } public static Task DeleteAsync( diff --git a/src/SIL.DataAccess/IEntity.cs b/src/SIL.DataAccess/IEntity.cs index 64aaeea0..568d4212 100644 --- a/src/SIL.DataAccess/IEntity.cs +++ b/src/SIL.DataAccess/IEntity.cs @@ -2,8 +2,6 @@ namespace SIL.DataAccess; public interface IEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] string Id { get; set; } int Revision { get; set; } } diff --git a/src/SIL.DataAccess/IRepository.cs b/src/SIL.DataAccess/IRepository.cs index 94a14b5e..95539b96 100644 --- a/src/SIL.DataAccess/IRepository.cs +++ b/src/SIL.DataAccess/IRepository.cs @@ -12,6 +12,7 @@ public interface IRepository Task UpdateAsync( Expression> filter, Action> update, + bool upsert = false, bool returnOriginal = false, CancellationToken cancellationToken = default ); diff --git a/src/SIL.DataAccess/MemoryRepository.cs b/src/SIL.DataAccess/MemoryRepository.cs index 866db6af..240f90ed 100644 --- a/src/SIL.DataAccess/MemoryRepository.cs +++ b/src/SIL.DataAccess/MemoryRepository.cs @@ -116,6 +116,8 @@ public async Task ExistsAsync(Expression> filter, Cancellati public async Task InsertAsync(T entity, CancellationToken cancellationToken = default) { entity.Revision = 1; + if (string.IsNullOrEmpty(entity.Id)) + entity.Id = ObjectId.GenerateNewId().ToString(); var allSubscriptions = new List>(); string serializedEntity; using (await _lock.LockAsync(cancellationToken)) @@ -134,6 +136,8 @@ public async Task InsertAllAsync(IReadOnlyCollection entities, CancellationTo foreach (T entity in entities) { entity.Revision = 1; + if (string.IsNullOrEmpty(entity.Id)) + entity.Id = ObjectId.GenerateNewId().ToString(); } var serializedEntities = new List<(string, string, List>)>(); using (await _lock.LockAsync(cancellationToken)) @@ -156,6 +160,7 @@ public async Task InsertAllAsync(IReadOnlyCollection entities, CancellationTo public async Task UpdateAsync( Expression> filter, Action> update, + bool upsert = false, bool returnOriginal = false, CancellationToken cancellationToken = default ) @@ -178,17 +183,34 @@ public async Task InsertAllAsync(IReadOnlyCollection entities, CancellationTo return false; } }); - if (entity == null) - return entity; // file not found + if (entity != null || upsert) + { + bool isInsert = entity == null; + if (isInsert) + { + entity = (T)Activator.CreateInstance(typeof(T))!; + string? id = ExpressionHelper.FindEqualsConstantValue(e => e.Id, filter.Body); + entity.Id = id ?? ObjectId.GenerateNewId().ToString(); + entity.Revision = 0; + } + else + { + original = Entities.AsQueryable().FirstOrDefault(filter); + } + Debug.Assert(entity != null); + var builder = new MemoryUpdateBuilder(filter, entity, isInsert); + update(builder); + entity.Revision++; - original = Entities.AsQueryable().FirstOrDefault(filter); - Debug.Assert(entity != null); - var builder = new MemoryUpdateBuilder(filter, entity, isInsert: false); - update(builder); - entity.Revision++; + if (isInsert && Contains(entity.Id)) + throw new DuplicateKeyException(); - serializedEntity = Replace(entity); - GetSubscriptions(entity, allSubscriptions); + if (CheckDuplicateKeys(entity, original)) + throw new DuplicateKeyException(); + + serializedEntity = Replace(entity); + GetSubscriptions(entity, allSubscriptions); + } } if (entity != null && serializedEntity != null) SendToSubscribers(allSubscriptions, EntityChangeType.Update, entity.Id, serializedEntity); @@ -212,6 +234,9 @@ public async Task UpdateAllAsync( update(builder); entity.Revision++; + if (CheckDuplicateKeys(entity, original)) + throw new DuplicateKeyException(); + Replace(entity); } diff --git a/src/SIL.DataAccess/MongoRepository.cs b/src/SIL.DataAccess/MongoRepository.cs index 5b225349..b9aa79f9 100644 --- a/src/SIL.DataAccess/MongoRepository.cs +++ b/src/SIL.DataAccess/MongoRepository.cs @@ -55,7 +55,7 @@ public async Task ExistsAsync(Expression> filter, Cancellati public async Task InsertAsync(T entity, CancellationToken cancellationToken = default) { entity.Revision = 1; - await TryCatchDuplicate(async () => + await TryCatchDuplicate(async () => { if (_context.Session is not null) { @@ -67,7 +67,6 @@ await _collection { await _collection.InsertOneAsync(entity, cancellationToken: cancellationToken).ConfigureAwait(false); } - return null; }); } @@ -76,7 +75,7 @@ public async Task InsertAllAsync(IReadOnlyCollection entities, CancellationTo foreach (T entity in entities) entity.Revision = 1; - await TryCatchDuplicate(async () => + await TryCatchDuplicate(async () => { if (_context.Session is not null) { @@ -88,13 +87,13 @@ await _collection { await _collection.InsertManyAsync(entities, cancellationToken: cancellationToken).ConfigureAwait(false); } - return null; }); } public async Task UpdateAsync( Expression> filter, Action> update, + bool upsert = false, bool returnOriginal = false, CancellationToken cancellationToken = default ) @@ -105,6 +104,7 @@ await _collection UpdateDefinition updateDef = updateBuilder.Build(); var options = new FindOneAndUpdateOptions { + IsUpsert = upsert, ReturnDocument = returnOriginal ? ReturnDocument.Before : ReturnDocument.After }; T? entity; @@ -221,11 +221,11 @@ public async Task> SubscribeAsync( return subscription; } - private async Task TryCatchDuplicate(Func> func) + private async Task TryCatchDuplicate(Func action) { try { - return await func(); + await action(); } catch (MongoCommandException e) { diff --git a/src/SIL.DataAccess/Usings.cs b/src/SIL.DataAccess/Usings.cs index 32eef1a7..fb4848bb 100644 --- a/src/SIL.DataAccess/Usings.cs +++ b/src/SIL.DataAccess/Usings.cs @@ -11,7 +11,6 @@ global using Microsoft.Extensions.Options; global using MongoDB.Bson; global using MongoDB.Bson.Serialization; -global using MongoDB.Bson.Serialization.Attributes; global using MongoDB.Bson.Serialization.Conventions; global using MongoDB.Bson.Serialization.Serializers; global using MongoDB.Driver; diff --git a/src/Serval.Client/Client.g.cs b/src/Serval.Client/Client.g.cs index 024f1f4d..e44dbf1b 100644 --- a/src/Serval.Client/Client.g.cs +++ b/src/Serval.Client/Client.g.cs @@ -2998,7 +2998,7 @@ public string BaseUrl if (status_ == 400) { string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ServalApiException("Bad request", status_, responseText_, headers_, null); + throw new ServalApiException("A corpus id is invalid", status_, responseText_, headers_, null); } else if (status_ == 401) @@ -3016,7 +3016,7 @@ public string BaseUrl if (status_ == 404) { string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ServalApiException("The engine or corpora specified in the config do not exist", status_, responseText_, headers_, null); + throw new ServalApiException("The engine does not exist", status_, responseText_, headers_, null); } else if (status_ == 409) @@ -3028,7 +3028,7 @@ public string BaseUrl if (status_ == 503) { string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ServalApiException("A necessary service is currently unavailable. Check `/health` for more details. ", status_, responseText_, headers_, null); + throw new ServalApiException("A necessary service is currently unavailable. Check `/health` for more details.", status_, responseText_, headers_, null); } else { diff --git a/src/Serval.DataFiles/Models/DataFile.cs b/src/Serval.DataFiles/Models/DataFile.cs index fc8b48e8..4f4e2e42 100644 --- a/src/Serval.DataFiles/Models/DataFile.cs +++ b/src/Serval.DataFiles/Models/DataFile.cs @@ -2,8 +2,6 @@ public class DataFile : IOwnedEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string Owner { get; set; } = default!; diff --git a/src/Serval.DataFiles/Models/DeletedFile.cs b/src/Serval.DataFiles/Models/DeletedFile.cs index 7b45837c..bba442d4 100644 --- a/src/Serval.DataFiles/Models/DeletedFile.cs +++ b/src/Serval.DataFiles/Models/DeletedFile.cs @@ -2,8 +2,6 @@ public class DeletedFile : IEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string Filename { get; set; } = default!; diff --git a/src/Serval.DataFiles/Usings.cs b/src/Serval.DataFiles/Usings.cs index d485deef..a10d6a20 100644 --- a/src/Serval.DataFiles/Usings.cs +++ b/src/Serval.DataFiles/Usings.cs @@ -13,8 +13,6 @@ global using Microsoft.Extensions.Hosting; global using Microsoft.Extensions.Logging; global using Microsoft.Extensions.Options; -global using MongoDB.Bson; -global using MongoDB.Bson.Serialization.Attributes; global using NSwag.Annotations; global using Serval.DataFiles.Consumers; global using Serval.DataFiles.Contracts; diff --git a/src/Serval.Shared/Utils/AutoToString.cs b/src/Serval.Shared/Utils/AutoToString.cs deleted file mode 100644 index dd8dc1de..00000000 --- a/src/Serval.Shared/Utils/AutoToString.cs +++ /dev/null @@ -1,73 +0,0 @@ -namespace Serval.Shared.Utils; - -public static class AutoToString -{ - //Helper functions for debugging and error printing data classes - - /// - /// Renders the object and its properties as a string using introspection. - /// - /// Object to be printed - /// A recursively generated string representation of the object - public static string Stringify(object? o) - { - if (o is null) - return "null"; - if (!o!.GetType().IsValueType && o.GetType() != typeof(string)) - { - string soFar = "(" + o!.GetType().Name + ")"; - return Stringify(o, soFar, 1); - } - return o is null ? "" : o.ToString()!; - } - - private static string Stringify(object? o, string soFar = "", int tabDepth = 0, int itemIndex = 0) - { - if (o is null) - return soFar + (itemIndex > 0 ? "\n" + new string('\t', tabDepth) : " ") + "null"; - if (o!.GetType().IsValueType || o.GetType() == typeof(string)) - { - var value = o; - return soFar + (itemIndex > 0 ? "\n" + new string('\t', tabDepth) : " ") + value; - } - if (itemIndex > 0) - soFar += "\n" + new string('\t', tabDepth - 1) + "(" + o.GetType().Name + "@Index" + itemIndex + ")"; - foreach (var property in o.GetType().GetProperties()) - { - if (property.Name == "Count") - continue; - if (property.GetIndexParameters().Count() > 0) - { - foreach (var ele in property.GetIndexParameters()) - { - int index = 0; - try - { - while (true) - { - var next_obj = property.GetValue(o, new object[] { index }); - soFar = Stringify( - next_obj, - soFar: soFar + "\n" + new string('\t', tabDepth) + (index == 0 ? "[" : ""), - tabDepth: tabDepth + 1, - itemIndex: index + 1 - ); - index++; //separately increment in case exception is thrown in inner GetAuto... - } - } - catch - { - soFar += "\n" + new string('\t', tabDepth) + (index == 0 ? "" : "]"); - // + (soFar.Count(c => c == '[') > soFar.Count(c => c == ']') ? "]" : ""); - } - } - } - else - { - soFar += "\n" + new string('\t', tabDepth) + property.Name + ":"; - soFar = Stringify(property.GetValue(o), soFar: soFar, tabDepth: tabDepth + 1); - } - } - return soFar; - } -} diff --git a/src/Serval.Translation/Controllers/TranslationEnginesController.cs b/src/Serval.Translation/Controllers/TranslationEnginesController.cs index 338c8d38..fd66331d 100644 --- a/src/Serval.Translation/Controllers/TranslationEnginesController.cs +++ b/src/Serval.Translation/Controllers/TranslationEnginesController.cs @@ -1,4 +1,7 @@ -namespace Serval.Translation.Controllers; +using Serval.Translation.Models; +using System.Threading; + +namespace Serval.Translation.Controllers; [ApiVersion(1.0)] [Route("api/v{version:apiVersion}/translation/engines")] @@ -137,8 +140,7 @@ public async Task> CreateAsync( CancellationToken cancellationToken ) { - Engine engine; - engine = Map(engineConfig); + Engine engine = Map(engineConfig); engine.Id = idGenerator.GenerateId(); try { @@ -150,7 +152,7 @@ CancellationToken cancellationToken { if (rpcEx.StatusCode == Grpc.Core.StatusCode.InvalidArgument) return UnprocessableEntity(rpcEx.Message); - return BadRequest(); + throw; } TranslationEngineDto dto = Map(engine); @@ -216,7 +218,7 @@ CancellationToken cancellationToken { if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) return errorResult; - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); TranslationResult? result = await _engineService.TranslateAsync(id, segment, cancellationToken); @@ -259,7 +261,7 @@ CancellationToken cancellationToken { if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) return errorResult; - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); IEnumerable? results = await _engineService.TranslateAsync( @@ -305,7 +307,7 @@ CancellationToken cancellationToken { if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) return errorResult; - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); WordGraph? wordGraph = await _engineService.GetWordGraphAsync(id, segment, cancellationToken); @@ -349,7 +351,7 @@ CancellationToken cancellationToken { if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) return errorResult; - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); if ( @@ -416,12 +418,11 @@ public async Task> AddCorpusAsync( CancellationToken cancellationToken ) { - if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) - return errorResult; - Engine? engine = await _engineService.GetAsync(id, cancellationToken); if (engine is null) return NotFound(); + if (!await AuthorizeIsOwnerAsync(engine)) + return Forbid(); Corpus corpus = await MapAsync(getDataFileClient, idGenerator.GenerateId(), corpusConfig, cancellationToken); if (engine.SourceLanguage != corpus.SourceLanguage || engine.TargetLanguage != corpus.TargetLanguage) return UnprocessableEntity( @@ -546,8 +547,6 @@ CancellationToken cancellationToken return NotFound(); if (!await AuthorizeIsOwnerAsync(engine)) return Forbid(); - if (engine.Corpora is null) - return NotFound(); Corpus? corpus = engine.Corpora.FirstOrDefault(f => f.Id == corpusId); if (corpus == null) return NotFound(); @@ -640,7 +639,7 @@ CancellationToken cancellationToken ); if (pretranslations is null || pretranslations.Count() == 0) return NotFound(); - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); return Ok((pretranslations).Select(Map)); } @@ -692,7 +691,7 @@ CancellationToken cancellationToken ); if (pretranslations is null || pretranslations.Count() == 0) return NotFound(); - if (!await isBuilt(id)) + if (!await IsBuilt(id)) return Conflict(); return Ok((pretranslations).Select(Map)); } @@ -805,12 +804,12 @@ CancellationToken cancellationToken /// The build config (see remarks) /// /// The build job was started successfully - /// Bad request + /// A corpus id is invalid /// The client is not authenticated /// The authenticated client does not own the translation engine - /// The engine or corpora specified in the config do not exist + /// The engine does not exist /// There is already an active/pending build - /// A necessary service is currently unavailable. Check `/health` for more details. + /// A necessary service is currently unavailable. Check `/health` for more details. [Authorize(Scopes.UpdateTranslationEngines)] [HttpPost("{id}/builds")] [ProducesResponseType(StatusCodes.Status201Created)] @@ -826,19 +825,25 @@ public async Task> StartBuildAsync( CancellationToken cancellationToken ) { - if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult)) - return errorResult; + Engine? engine = await _engineService.GetAsync(id, cancellationToken); + if (engine is null) + return NotFound(); + if (!await AuthorizeIsOwnerAsync(engine)) + return Forbid(); + if (await _buildService.GetActiveAsync(id) is not null) return Conflict(); - Build build = Map(id, buildConfig); - bool startedBuild = false; + + Build build; try { - startedBuild = await _engineService.StartBuildAsync(build, cancellationToken); + build = Map(engine, buildConfig); } - catch { } - - if (!startedBuild) + catch (InvalidOperationException ioe) + { + return BadRequest(ioe.Message); + } + if (!await _engineService.StartBuildAsync(build, cancellationToken)) return NotFound(); var dto = Map(build); @@ -1007,19 +1012,30 @@ private Engine Map(TranslationEngineConfigDto source) SourceLanguage = source.SourceLanguage, TargetLanguage = source.TargetLanguage, Type = source.Type, - Owner = Owner + Owner = Owner, + Corpora = new List() }; } - private static Build Map(string engineId, TranslationBuildConfigDto source) + private static Build Map(Engine engine, TranslationBuildConfigDto source) { - return new Build + var build = new Build { EngineRef = engine.Id }; + if (source.Pretranslate != null) { - EngineRef = engineId, - Pretranslate = source.Pretranslate - ?.Select(c => new PretranslateCorpus { CorpusRef = c.CorpusId, TextIds = c.TextIds?.ToList() }) - .ToList() - }; + var pretranslateCorpora = new List(); + var corpusIds = new HashSet(engine.Corpora.Select(c => c.Id)); + foreach (PretranslateCorpusConfigDto ptcc in source.Pretranslate) + { + if (!corpusIds.Contains(ptcc.CorpusId)) + throw new InvalidOperationException($"The corpus {ptcc.CorpusId} is not valid."); + + pretranslateCorpora.Add( + new PretranslateCorpus { CorpusRef = ptcc.CorpusId, TextIds = ptcc.TextIds?.ToList() } + ); + } + build.Pretranslate = pretranslateCorpora; + } + return build; } private TranslationEngineDto Map(Engine source) @@ -1171,7 +1187,7 @@ private TranslationCorpusFileDto Map(CorpusFile source) }; } - private async Task isBuilt(string id) + private async Task IsBuilt(string id) { IEnumerable builds = await _buildService.GetAllAsync(id); return builds != null && builds.Any(b => b.State == JobState.Completed); diff --git a/src/Serval.Translation/Models/Build.cs b/src/Serval.Translation/Models/Build.cs index f8dd5dcc..ac6cb7fa 100644 --- a/src/Serval.Translation/Models/Build.cs +++ b/src/Serval.Translation/Models/Build.cs @@ -2,8 +2,6 @@ public class Build : IEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string EngineRef { get; set; } = default!; diff --git a/src/Serval.Translation/Models/Engine.cs b/src/Serval.Translation/Models/Engine.cs index ed670410..f9d0dbbd 100644 --- a/src/Serval.Translation/Models/Engine.cs +++ b/src/Serval.Translation/Models/Engine.cs @@ -2,8 +2,6 @@ public class Engine : IOwnedEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string? Name { get; set; } diff --git a/src/Serval.Translation/Models/Pretranslation.cs b/src/Serval.Translation/Models/Pretranslation.cs index a81151a5..447e0628 100644 --- a/src/Serval.Translation/Models/Pretranslation.cs +++ b/src/Serval.Translation/Models/Pretranslation.cs @@ -2,8 +2,6 @@ public class Pretranslation : IEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string EngineRef { get; set; } = default!; diff --git a/src/Serval.Translation/Services/EngineService.cs b/src/Serval.Translation/Services/EngineService.cs index 12bd69f3..8c55dfab 100644 --- a/src/Serval.Translation/Services/EngineService.cs +++ b/src/Serval.Translation/Services/EngineService.cs @@ -136,7 +136,8 @@ public override async Task CreateAsync(Engine engine, CancellationToken ca await Entities.InsertAsync(engine, cancellationToken); try { - var client = _grpcClientFactory.CreateClient(engine.Type); + TranslationEngineApi.TranslationEngineApiClient? client = + _grpcClientFactory.CreateClient(engine.Type); if (client is null) return false; var request = new CreateRequest @@ -271,7 +272,7 @@ public async Task DeleteCorpusAsync( ) { await _dataAccessContext.BeginTransactionAsync(cancellationToken); - Engine? original_engine = await Entities.UpdateAsync( + Engine? originalEngine = await Entities.UpdateAsync( engineId, u => u.RemoveAll(e => e.Corpora, c => c.Id == corpusId), returnOriginal: true, @@ -279,14 +280,7 @@ public async Task DeleteCorpusAsync( ); await _pretranslations.DeleteAllAsync(pt => pt.CorpusRef == corpusId, cancellationToken); await _dataAccessContext.CommitTransactionAsync(cancellationToken); - return original_engine is not null - && original_engine.Corpora is not null - && original_engine.Corpora - .FindAll(c => - { - return c.Id == corpusId; - }) - .Count() > 0; + return originalEngine is not null && originalEngine.Corpora.Any(c => c.Id == corpusId); } public Task DeleteAllCorpusFilesAsync(string dataFileId, CancellationToken cancellationToken = default) diff --git a/src/Serval.Translation/Usings.cs b/src/Serval.Translation/Usings.cs index 3bdcd861..41550d03 100644 --- a/src/Serval.Translation/Usings.cs +++ b/src/Serval.Translation/Usings.cs @@ -10,8 +10,6 @@ global using Microsoft.AspNetCore.Routing; global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.Options; -global using MongoDB.Bson; -global using MongoDB.Bson.Serialization.Attributes; global using NSwag.Annotations; global using Serval.Shared.Configuration; global using Serval.Shared.Contracts; diff --git a/src/Serval.Webhooks/Models/Webhook.cs b/src/Serval.Webhooks/Models/Webhook.cs index 4751542c..29f8ec68 100644 --- a/src/Serval.Webhooks/Models/Webhook.cs +++ b/src/Serval.Webhooks/Models/Webhook.cs @@ -2,8 +2,6 @@ public class Webhook : IOwnedEntity { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } = default!; public int Revision { get; set; } = 1; public string Owner { get; set; } = default!; diff --git a/src/Serval.Webhooks/Usings.cs b/src/Serval.Webhooks/Usings.cs index 1eb866f4..c7f870d3 100644 --- a/src/Serval.Webhooks/Usings.cs +++ b/src/Serval.Webhooks/Usings.cs @@ -1,5 +1,4 @@ global using System.Diagnostics.CodeAnalysis; -global using System.Reflection; global using System.Security.Cryptography; global using System.Text; global using System.Text.Json; @@ -13,8 +12,6 @@ global using Microsoft.AspNetCore.Mvc; global using Microsoft.AspNetCore.Routing; global using Microsoft.Extensions.Options; -global using MongoDB.Bson; -global using MongoDB.Bson.Serialization.Attributes; global using Polly; global using Serval.Shared.Contracts; global using Serval.Shared.Controllers; diff --git a/tests/Serval.ApiServer.IntegrationTests/DataFilesTests.cs b/tests/Serval.ApiServer.IntegrationTests/DataFilesTests.cs index 694ac241..90eaeb50 100644 --- a/tests/Serval.ApiServer.IntegrationTests/DataFilesTests.cs +++ b/tests/Serval.ApiServer.IntegrationTests/DataFilesTests.cs @@ -1,7 +1,6 @@ +using Nito.AsyncEx; + namespace Serval.ApiServer; -using Serval.DataFiles.Models; -using Shared.Contracts; -using Microsoft.AspNetCore.Mvc; [TestFixture] [Category("Integration")] @@ -23,33 +22,29 @@ public class DataFilesTests public async Task SetUp() { _env = new TestEnvironment(); - DataFile file1, - file2, - file3; - - file1 = new DataFile + var file1 = new DataFiles.Models.DataFile { Id = ID1, Owner = "client1", Name = NAME1, Filename = NAME1, - Format = FileFormat.Text + Format = Shared.Contracts.FileFormat.Text }; - file2 = new DataFile + var file2 = new DataFiles.Models.DataFile { Id = ID2, Owner = "client1", Name = NAME2, Filename = NAME2, - Format = FileFormat.Text + Format = Shared.Contracts.FileFormat.Text }; - file3 = new DataFile + var file3 = new DataFiles.Models.DataFile { Id = ID3, Owner = "client2", Name = NAME3, Filename = NAME3, - Format = FileFormat.Text + Format = Shared.Contracts.FileFormat.Text }; await _env.DataFiles.InsertAllAsync(new[] { file1, file2, file3 }); } @@ -61,11 +56,10 @@ public async Task SetUp() public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) { DataFilesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: - ICollection results = await client.GetAllAsync(); + ICollection results = await client.GetAllAsync(); Assert.That(results, Has.Count.EqualTo(2)); Assert.That(results.All(dataFile => dataFile.Revision == 1)); @@ -75,11 +69,11 @@ public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) expectedStatusCode = 403; goto case 403; case 403: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAllAsync(); }); - Assert.NotNull(ex); + Assert.That(ex, Is.Not.Null); Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); break; @@ -98,11 +92,10 @@ public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) public async Task GetByIDAsync(IEnumerable scope, int expectedStatusCode, string fileId) { DataFilesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: - Serval.Client.DataFile result = await client.GetAsync(fileId); + DataFile result = await client.GetAsync(fileId); Assert.That(result.Name, Is.EqualTo(NAME1)); break; case 401: @@ -110,7 +103,7 @@ public async Task GetByIDAsync(IEnumerable scope, int expectedStatusCode goto case 403; case 403: case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAsync(fileId); }); @@ -127,47 +120,45 @@ public async Task GetByIDAsync(IEnumerable scope, int expectedStatusCode // [TestCase(new[] { Scopes.CreateFiles, Scopes.ReadFiles }, 401)] [TestCase(new[] { Scopes.CreateFiles, Scopes.ReadFiles }, 400)] [TestCase(new[] { Scopes.ReadFiles }, 403)] - public void CreateAsync(IEnumerable scope, int expectedStatusCode) + public async Task CreateAsync(IEnumerable scope, int expectedStatusCode) { DataFilesClient client = _env!.CreateClient(scope); - ServalApiException? ex; - FileParameter fp; - Stream fs; + ServalApiException ex; switch (expectedStatusCode) { case 201: - Assert.DoesNotThrowAsync(async () => + using (var fs = new MemoryStream()) { - fs = new MemoryStream(); - fp = new FileParameter(fs); - await client.CreateAsync(fp, Client.FileFormat.Text); - ICollection results = await client.GetAllAsync(); + var fp = new FileParameter(fs); + await client.CreateAsync(fp, FileFormat.Text); + ICollection results = await client.GetAllAsync(); Assert.That(results, Has.Count.EqualTo(3)); //2 from set-up + 1 added above = 3 Assert.That(results.All(dataFile => dataFile.Revision == 1)); - fs.Dispose(); - }); + } break; case 400: byte[] bytes = new byte[2_000_000_000]; - fs = new MemoryStream(bytes); - fp = new FileParameter(fs); - fp = new FileParameter(fs); - ex = Assert.ThrowsAsync(async () => + using (var fs = new MemoryStream(bytes)) { - await client.CreateAsync(fp, Client.FileFormat.Text); - }); - fs.Dispose(); + var fp = new FileParameter(fs); + fp = new FileParameter(fs); + ex = Assert.ThrowsAsync(async () => + { + await client.CreateAsync(fp, FileFormat.Text); + }); + } Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); break; case 403: - fs = new MemoryStream(); - fp = new FileParameter(fs); - ex = Assert.ThrowsAsync(async () => + using (var fs = new MemoryStream()) { - await client.CreateAsync(fp, Client.FileFormat.Text); - }); - fs.Dispose(); + var fp = new FileParameter(fs); + ex = Assert.ThrowsAsync(async () => + { + await client.CreateAsync(fp, FileFormat.Text); + }); + } Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); break; default: @@ -185,17 +176,17 @@ public void CreateAsync(IEnumerable scope, int expectedStatusCode) public async Task UpdateAsync(IEnumerable scope, int expectedStatusCode, string fileId) { DataFilesClient client = _env!.CreateClient(scope); - ServalApiException? ex; + ServalApiException ex; switch (expectedStatusCode) { case 200: - Serval.Client.DataFile result = await client.GetAsync(fileId); + DataFile result = await client.GetAsync(fileId); Assert.That(result.Name, Is.EqualTo(NAME1)); Assert.DoesNotThrowAsync(async () => { await client.UpdateAsync(fileId, new FileParameter(new MemoryStream())); }); - Serval.Client.DataFile resultAfterUpdate = await client.GetAsync(fileId); + DataFile resultAfterUpdate = await client.GetAsync(fileId); Assert.That(resultAfterUpdate.Id, Is.EqualTo(ID1)); break; case 400: @@ -228,17 +219,13 @@ public async Task UpdateAsync(IEnumerable scope, int expectedStatusCode, public async Task DeleteAsync(IEnumerable scope, int expectedStatusCode, string fileId) { DataFilesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: - Serval.Client.DataFile result = await client.GetAsync(fileId); + DataFile result = await client.GetAsync(fileId); Assert.That(result.Name, Is.EqualTo(NAME1)); - Assert.DoesNotThrowAsync(async () => - { - await client.DeleteAsync(fileId); - }); - ICollection results = await client.GetAllAsync(); + await client.DeleteAsync(fileId); + ICollection results = await client.GetAllAsync(); Assert.That(results, Has.Count.EqualTo(1)); Assert.That(results.First().Id, Is.EqualTo(ID2)); break; @@ -247,12 +234,12 @@ public async Task DeleteAsync(IEnumerable scope, int expectedStatusCode, goto case 403; case 403: case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.DeleteAsync(fileId); }); Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); - ICollection resultsAfterDelete = await client.GetAllAsync(); + ICollection resultsAfterDelete = await client.GetAllAsync(); Assert.That(resultsAfterDelete, Has.Count.EqualTo(2)); break; default: @@ -274,8 +261,7 @@ private class TestEnvironment : DisposableBase public TestEnvironment() { - var clientSettings = new MongoClientSettings(); - clientSettings.LinqProvider = LinqProvider.V2; + var clientSettings = new MongoClientSettings { LinqProvider = LinqProvider.V2 }; _mongoClient = new MongoClient(clientSettings); ResetDatabases(); diff --git a/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs b/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs index ccd7b95c..bb2a2129 100644 --- a/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs +++ b/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs @@ -1,8 +1,7 @@ -namespace Serval.ApiServer; -using Serval.Translation.V1; using Google.Protobuf.WellKnownTypes; -using Serval.DataFiles.Models; -using static Serval.Shared.Utils.AutoToString; +using Serval.Translation.V1; + +namespace Serval.ApiServer; [TestFixture] [Category("Integration")] @@ -28,62 +27,60 @@ public class TranslationEngineTests public async Task SetUp() { _env = new TestEnvironment(); - Engine e0, - e1, - e2, - be0, - ce0; - e0 = new Engine + var e0 = new Engine { Id = ECHO_ENGINE1_ID, Name = "e0", SourceLanguage = "en", TargetLanguage = "en", Type = "Echo", - Owner = "client1" + Owner = "client1", + Corpora = new List() }; - e1 = new Engine + var e1 = new Engine { Id = ECHO_ENGINE2_ID, Name = "e1", SourceLanguage = "en", TargetLanguage = "en", Type = "Echo", - Owner = "client1" + Owner = "client1", + Corpora = new List() }; - e2 = new Engine + var e2 = new Engine { Id = ECHO_ENGINE3_ID, Name = "e2", SourceLanguage = "en", TargetLanguage = "en", Type = "Echo", - Owner = "client2" + Owner = "client2", + Corpora = new List() }; - be0 = new Engine + var be0 = new Engine { Id = SMT_ENGINE1_ID, Name = "be0", SourceLanguage = "en", TargetLanguage = "es", Type = "SMTTransfer", - Owner = "client1" + Owner = "client1", + Corpora = new List() }; - ce0 = new Engine + var ce0 = new Engine { Id = NMT_ENGINE1_ID, Name = "ce0", SourceLanguage = "en", TargetLanguage = "es", Type = "Nmt", - Owner = "client1" + Owner = "client1", + Corpora = new List() }; await _env.Engines.InsertAllAsync(new[] { e0, e1, e2, be0, ce0 }); - DataFile srcFile, - trgFile; - srcFile = new DataFile + var srcFile = new DataFiles.Models.DataFile { Id = FILE1_ID, Owner = "client1", @@ -91,7 +88,7 @@ public async Task SetUp() Filename = FILE1_FILENAME, Format = Shared.Contracts.FileFormat.Text }; - trgFile = new DataFile + var trgFile = new DataFiles.Models.DataFile { Id = FILE2_ID, Owner = "client1", @@ -137,7 +134,6 @@ public async Task SetUp() public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: @@ -146,7 +142,7 @@ public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) Assert.That(results.All(eng => eng.SourceLanguage.Equals("en"))); break; case 403: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAllAsync(); }); @@ -166,7 +162,6 @@ public async Task GetAllAsync(IEnumerable scope, int expectedStatusCode) public async Task GetByIdAsync(IEnumerable scope, int expectedStatusCode, string engineId) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: @@ -175,7 +170,7 @@ public async Task GetByIdAsync(IEnumerable scope, int expectedStatusCode break; case 403: case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAsync(engineId); }); @@ -209,7 +204,7 @@ public async Task CreateEngineAsync(IEnumerable scope, int expectedStatu ); Assert.That(result.Name, Is.EqualTo("test")); TranslationEngine? engine = await client.GetAsync(result.Id); - Assert.NotNull(engine); + Assert.That(engine, Is.Not.Null); Assert.That(engine.Name, Is.EqualTo("test")); break; case 400: @@ -255,21 +250,17 @@ await client.CreateAsync( public async Task DeleteEngineByIdAsync(IEnumerable scope, int expectedStatusCode, string engineId) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: - Assert.DoesNotThrowAsync(async () => - { - await client.DeleteAsync(engineId); - }); + await client.DeleteAsync(engineId); ICollection results = await client.GetAllAsync(); Assert.That(results, Has.Count.EqualTo(3)); Assert.That(results.All(eng => eng.SourceLanguage.Equals("en"))); break; case 403: case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.DeleteAsync(engineId); }); @@ -292,51 +283,23 @@ string engineId ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; - Serval.Client.TranslationResult? result = null; switch (expectedStatusCode) { case 200: await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - Assert.DoesNotThrowAsync(async () => - { - result = await client.TranslateAsync(engineId, "This is a test ."); - }); - Assert.NotNull(result); - Assert.That(result!.Translation, Is.EqualTo("This is a test .")); + Client.TranslationResult result = await client.TranslateAsync(engineId, "This is a test ."); + Assert.That(result.Translation, Is.EqualTo("This is a test .")); Assert.That(result.Sources, Has.Count.EqualTo(5)); Assert.That( result.Sources, Has.All.EquivalentTo(new[] { Client.TranslationSource.Primary, Client.TranslationSource.Secondary }) ); break; - // case 405: //NOTE: Cannot test 405s because they are handled in middleware that does not run in test environment - // TranslationCorpus added_corpus405 = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - // var ptcc405 = new PretranslateCorpusConfig - // { - // CorpusId = added_corpus405.Id, - // TextIds = new List { "all" } - // }; - // var tbc405 = new TranslationBuildConfig - // { - // Pretranslate = new List { ptcc405 } - // }; - // Assert.DoesNotThrowAsync(async () => - // { - // await client.StartBuildAsync(engineId, tbc405); - // }); - // ex = Assert.ThrowsAsync(async () => - // { - // await client.TranslateAsync(engineId, "This is a test ."); - // }); - // Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); - - // break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.TranslateAsync(engineId, "This is a test ."); }); @@ -360,30 +323,28 @@ string engineId ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; - ICollection? results = null; switch (expectedStatusCode) { case 200: await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - Assert.DoesNotThrowAsync(async () => - { - results = await client.TranslateNAsync(engineId, 1, "This is a test ."); - }); - Assert.NotNull(results); + ICollection results = await client.TranslateNAsync( + engineId, + 1, + "This is a test ." + ); Assert.That(results, Has.Count.EqualTo(1)); - Assert.That(results!.First().Translation, Is.EqualTo("This is a test .")); - Assert.That(results!.First().Sources, Has.Count.EqualTo(5)); + Assert.That(results.First().Translation, Is.EqualTo("This is a test .")); + Assert.That(results.First().Sources, Has.Count.EqualTo(5)); Assert.That( - results!.First().Sources, + results.First().Sources, Has.All.EquivalentTo(new[] { Client.TranslationSource.Primary, Client.TranslationSource.Secondary }) ); break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.TranslateNAsync(engineId, 1, "This is a test ."); }); @@ -407,29 +368,23 @@ string engineId ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; - Serval.Client.WordGraph? wg = null; switch (expectedStatusCode) { case 200: - TranslationCorpus added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); + TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - Assert.DoesNotThrowAsync(async () => - { - wg = await client.GetWordGraphAsync(engineId, "This is a test ."); - }); - Assert.NotNull(wg); + Client.WordGraph wg = await client.GetWordGraphAsync(engineId, "This is a test ."); Assert.Multiple(() => { - Assert.That(wg!.FinalStates.First(), Is.EqualTo(4)); - Assert.That(wg!.Arcs.Count(), Is.EqualTo(4)); + Assert.That(wg.FinalStates[0], Is.EqualTo(4)); + Assert.That(wg.Arcs, Has.Count.EqualTo(4)); }); break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetWordGraphAsync(engineId, "This is a test ."); }); @@ -452,26 +407,24 @@ string engineId ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; - SegmentPair sp = new SegmentPair(); - sp.SourceSegment = "This is a test ."; - sp.TargetSegment = "This is a test ."; - sp.SentenceStart = true; + var sp = new SegmentPair + { + SourceSegment = "This is a test .", + TargetSegment = "This is a test .", + SentenceStart = true + }; switch (expectedStatusCode) { case 200: - TranslationCorpus added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); + TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - Assert.DoesNotThrowAsync(async () => - { - await client.TrainSegmentAsync(engineId, sp); - }); + await client.TrainSegmentAsync(engineId, sp); break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.TrainSegmentAsync(engineId, sp); }); @@ -489,16 +442,10 @@ await _env.Builds.InsertAsync( public async Task AddCorpusToEngineByIdAsync(IEnumerable scope, int expectedStatusCode, string engineId) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 201: - TranslationCorpus result = new TranslationCorpus(); - - Assert.DoesNotThrowAsync(async () => - { - result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - }); + TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); Assert.Multiple(() => { Assert.That(result.Name, Is.EqualTo("TestCorpus")); @@ -514,7 +461,7 @@ public async Task AddCorpusToEngineByIdAsync(IEnumerable scope, int expe }); break; case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); }); @@ -549,25 +496,20 @@ string engineId ) { TranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex; switch (expectedStatusCode) { case 200: TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - - Assert.DoesNotThrowAsync(async () => + var src = new[] { - var src = new[] - { - new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" } - }; - var trg = new[] - { - new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" } - }; - var updateConfig = new TranslationCorpusUpdateConfig { SourceFiles = src, TargetFiles = trg }; - await client.UpdateCorpusAsync(engineId, result.Id, updateConfig); - }); + new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" } + }; + var trg = new[] + { + new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" } + }; + var updateConfig = new TranslationCorpusUpdateConfig { SourceFiles = src, TargetFiles = trg }; + await client.UpdateCorpusAsync(engineId, result.Id, updateConfig); Engine? engine = await _env.Engines.GetAsync(engineId); Assert.That(engine, Is.Not.Null); Assert.Multiple(() => @@ -578,7 +520,7 @@ string engineId break; case 400: case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { var src = new[] { @@ -622,12 +564,12 @@ string engineId { case 200: TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - TranslationCorpus result_afterAdd = (await client.GetAllCorporaAsync(engineId)).First(); + TranslationCorpus resultAfterAdd = (await client.GetAllCorporaAsync(engineId)).First(); Assert.Multiple(() => { - Assert.That(result_afterAdd.Name, Is.EqualTo(result.Name)); - Assert.That(result_afterAdd.SourceLanguage, Is.EqualTo(result.SourceLanguage)); - Assert.That(result_afterAdd.TargetLanguage, Is.EqualTo(result.TargetLanguage)); + Assert.That(resultAfterAdd.Name, Is.EqualTo(result.Name)); + Assert.That(resultAfterAdd.SourceLanguage, Is.EqualTo(result.SourceLanguage)); + Assert.That(resultAfterAdd.TargetLanguage, Is.EqualTo(result.TargetLanguage)); }); break; case 404: @@ -668,12 +610,12 @@ public async Task GetCorpusByIdForEngineByIdAsync( case 200: if (result is null) Assert.Fail(); - TranslationCorpus result_afterAdd = await client.GetCorpusAsync(engineId, result!.Id); + TranslationCorpus resultAfterAdd = await client.GetCorpusAsync(engineId, result!.Id); Assert.Multiple(() => { - Assert.That(result_afterAdd.Name, Is.EqualTo(result.Name)); - Assert.That(result_afterAdd.SourceLanguage, Is.EqualTo(result.SourceLanguage)); - Assert.That(result_afterAdd.TargetLanguage, Is.EqualTo(result.TargetLanguage)); + Assert.That(resultAfterAdd.Name, Is.EqualTo(result.Name)); + Assert.That(resultAfterAdd.SourceLanguage, Is.EqualTo(result.SourceLanguage)); + Assert.That(resultAfterAdd.TargetLanguage, Is.EqualTo(result.TargetLanguage)); }); break; case 404: @@ -706,12 +648,9 @@ string engineId { case 200: TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - Assert.DoesNotThrowAsync(async () => - { - await client.DeleteCorpusAsync(engineId, result.Id); - }); - ICollection results_afterDelete = await client.GetAllCorporaAsync(engineId); - Assert.That(results_afterDelete, Has.Count.EqualTo(0)); + await client.DeleteCorpusAsync(engineId, result.Id); + ICollection resultsAfterDelete = await client.GetAllCorporaAsync(engineId); + Assert.That(resultsAfterDelete, Has.Count.EqualTo(0)); break; case 404: ex = Assert.ThrowsAsync(async () => @@ -758,14 +697,13 @@ public async Task GetAllPretranslationsForCorpusByIdForEngineByIdAsync( ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; - TranslationCorpus? added_corpus = null; + TranslationCorpus? addedCorpus = null; if (addCorpus) { - added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - Serval.Translation.Models.Pretranslation pret = new Serval.Translation.Models.Pretranslation + addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); + var pret = new Translation.Models.Pretranslation { - CorpusRef = added_corpus.Id, + CorpusRef = addedCorpus.Id, TextId = "all", EngineRef = engineId, Refs = new List { "ref1", "ref2" }, @@ -777,25 +715,23 @@ public async Task GetAllPretranslationsForCorpusByIdForEngineByIdAsync( switch (expectedStatusCode) { case 200: - Assert.True(addCorpus, "Check that addCorpus is true - cannot build without added corpus"); + Assert.That(addCorpus, Is.True, "Check that addCorpus is true - cannot build without added corpus"); await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - ICollection? results = null; - Assert.DoesNotThrowAsync(async () => - { - results = await client.GetAllPretranslationsAsync(engineId, added_corpus!.Id); - }); - Assert.NotNull(results); - Assert.That(results!.First().TextId, Is.EqualTo("all")); + ICollection results = await client.GetAllPretranslationsAsync( + engineId, + addedCorpus!.Id + ); + Assert.That(results.First().TextId, Is.EqualTo("all")); break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { results = await client.GetAllPretranslationsAsync( engineId, - addCorpus ? added_corpus!.Id : "cccccccccccccccccccccccc" + addCorpus ? addedCorpus!.Id : "cccccccccccccccccccccccc" ); }); Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); @@ -851,14 +787,13 @@ string textId ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; - TranslationCorpus? added_corpus = null; + TranslationCorpus? addedCorpus = null; if (addCorpus) { - added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - Serval.Translation.Models.Pretranslation pret = new Serval.Translation.Models.Pretranslation + addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); + var pret = new Translation.Models.Pretranslation { - CorpusRef = added_corpus.Id, + CorpusRef = addedCorpus.Id, TextId = "all", //Note that this is not equal to textId necessarily EngineRef = engineId, Refs = new List { "ref1", "ref2" }, @@ -870,25 +805,24 @@ string textId switch (expectedStatusCode) { case 200: - Assert.True(addCorpus, "Check that addCorpus is true - cannot build without added corpus"); + Assert.That(addCorpus, Is.True, "Check that addCorpus is true - cannot build without added corpus"); await _env.Builds.InsertAsync( new Build { EngineRef = engineId, State = Shared.Contracts.JobState.Completed } ); - ICollection? results = null; - Assert.DoesNotThrowAsync(async () => - { - results = await client.GetAllPretranslations2Async(engineId, added_corpus!.Id, textId); - }); - Assert.NotNull(results); - Assert.That(results!.First().TextId, Is.EqualTo("all")); + ICollection results = await client.GetAllPretranslations2Async( + engineId, + addedCorpus!.Id, + textId + ); + Assert.That(results.First().TextId, Is.EqualTo("all")); break; case 404: case 409: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { results = await client.GetAllPretranslations2Async( engineId, - addCorpus ? added_corpus!.Id : "cccccccccccccccccccccccc", + addCorpus ? addedCorpus!.Id : "cccccccccccccccccccccccc", textId ); }); @@ -911,7 +845,6 @@ public async Task GetAllBuildsForEngineByIdAsync( ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; Build? build = null; if (addBuild) { @@ -921,22 +854,17 @@ public async Task GetAllBuildsForEngineByIdAsync( switch (expectedStatusCode) { case 200: - ICollection? results = null; - Assert.DoesNotThrowAsync(async () => - { - results = await client.GetAllBuildsAsync(engineId); - }); - Assert.NotNull(results); - Assert.That(results!.Count(), Is.GreaterThan(0)); + ICollection results = await client.GetAllBuildsAsync(engineId); + Assert.That(results, Is.Not.Empty); Assert.Multiple(() => { - Assert.That(results!.First().Revision, Is.EqualTo(1)); - Assert.That(results!.First().Id, Is.EqualTo(build!.Id)); - Assert.That(results!.First().State, Is.EqualTo(JobState.Pending)); + Assert.That(results.First().Revision, Is.EqualTo(1)); + Assert.That(results.First().Id, Is.EqualTo(build!.Id)); + Assert.That(results.First().State, Is.EqualTo(JobState.Pending)); }); break; case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAllBuildsAsync(engineId); }); @@ -960,26 +888,22 @@ public async Task GetBuildByIdForEngineByIdAsync( ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; Build? build = null; if (addBuild) { build = new Build { EngineRef = engineId }; await _env.Builds.InsertAsync(build); } + ServalApiException ex; switch (expectedStatusCode) { case 200: - Serval.Client.TranslationBuild? result = null; - Assert.NotNull(build); - Assert.DoesNotThrowAsync(async () => - { - result = await client.GetBuildAsync(engineId, build!.Id); - }); + Assert.That(build, Is.Not.Null); + TranslationBuild result = await client.GetBuildAsync(engineId, build!.Id); Assert.Multiple(() => { - Assert.That(result!.Revision, Is.EqualTo(1)); - Assert.That(result.Id, Is.EqualTo(build!.Id)); + Assert.That(result.Revision, Is.EqualTo(1)); + Assert.That(result.Id, Is.EqualTo(build.Id)); Assert.That(result.State, Is.EqualTo(JobState.Pending)); }); break; @@ -991,7 +915,7 @@ public async Task GetBuildByIdForEngineByIdAsync( Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); break; case 408: - Assert.NotNull(build); + Assert.That(build, Is.Not.Null); ex = Assert.ThrowsAsync(async () => { await client.GetBuildAsync(engineId, build!.Id, 3); @@ -1017,42 +941,37 @@ public async Task GetBuildByIdForEngineByIdAsync( )] [TestCase( new[] { Scopes.UpdateTranslationEngines, Scopes.CreateTranslationEngines, Scopes.ReadTranslationEngines }, - 404, + 400, ECHO_ENGINE1_ID )] public async Task StartBuildForEngineByIdAsync(IEnumerable scope, int expectedStatusCode, string engineId) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; - PretranslateCorpusConfig? ptcc = null; - TranslationBuildConfig? tbc = null; + PretranslateCorpusConfig ptcc; + TranslationBuildConfig tbc; switch (expectedStatusCode) { case 201: - TranslationBuild? build; - TranslationCorpus added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); - Serval.Client.TranslationBuild? result_afterStart = null; + TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!); ptcc = new PretranslateCorpusConfig { - CorpusId = added_corpus.Id, + CorpusId = addedCorpus.Id, TextIds = new List { "all" } }; tbc = new TranslationBuildConfig { Pretranslate = new List { ptcc } }; + TranslationBuild resultAfterStart; Assert.ThrowsAsync(async () => { - result_afterStart = await client.GetCurrentBuildAsync(engineId); - }); - Assert.DoesNotThrowAsync(async () => - { - build = await client.StartBuildAsync(engineId, tbc); - Assert.NotNull(build); - }); - Assert.DoesNotThrowAsync(async () => - { - build = await client.GetCurrentBuildAsync(engineId); - Assert.NotNull(build); + resultAfterStart = await client.GetCurrentBuildAsync(engineId); }); + + TranslationBuild build = await client.StartBuildAsync(engineId, tbc); + Assert.That(build, Is.Not.Null); + + build = await client.GetCurrentBuildAsync(engineId); + Assert.That(build, Is.Not.Null); break; + case 400: case 404: ptcc = new PretranslateCorpusConfig { @@ -1060,7 +979,7 @@ public async Task StartBuildForEngineByIdAsync(IEnumerable scope, int ex TextIds = new List { "all" } }; tbc = new TranslationBuildConfig { Pretranslate = new List { ptcc } }; - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.StartBuildAsync(engineId, tbc); }); @@ -1085,25 +1004,20 @@ public async Task GetCurrentBuildForEngineByIdAsync( ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; Build? build = null; - TranslationBuild? result = null; if (addBuild) { build = new Build { EngineRef = engineId }; await _env.Builds.InsertAsync(build); } + ServalApiException ex; switch (expectedStatusCode) { case 200: - Assert.DoesNotThrowAsync(async () => - { - result = await client.GetCurrentBuildAsync(engineId); - }); - Assert.NotNull(result); - Assert.NotNull(build); - Assert.That(result!.Id, Is.EqualTo(build!.Id)); + Assert.That(build, Is.Not.Null); + TranslationBuild result = await client.GetCurrentBuildAsync(engineId); + Assert.That(result.Id, Is.EqualTo(build!.Id)); break; case 204: case 404: @@ -1139,7 +1053,6 @@ public async Task CancelCurrentBuildForEngineByIdAsync( ) { ITranslationEnginesClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; Build? build = null; if (addBuild) { @@ -1150,13 +1063,10 @@ public async Task CancelCurrentBuildForEngineByIdAsync( switch (expectedStatusCode) { case 200: - Assert.DoesNotThrowAsync(async () => - { - await client.CancelBuildAsync(engineId); - }); + await client.CancelBuildAsync(engineId); break; case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.CancelBuildAsync(engineId); }); @@ -1174,36 +1084,32 @@ public async Task TryToQueueMultipleBuildsPerSingleUser() ITranslationEnginesClient client = _env!.CreateClient(); var engineId = NMT_ENGINE1_ID; var expectedStatusCode = 409; - TranslationBuild? build = null; - TranslationCorpus added_corpus = await client.AddCorpusAsync(engineId, _testCorpusConfigNonEcho!); + TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfigNonEcho!); var ptcc = new PretranslateCorpusConfig { - CorpusId = added_corpus.Id, + CorpusId = addedCorpus.Id, TextIds = new List { "all" } }; var tbc = new TranslationBuildConfig { Pretranslate = new List { ptcc } }; - Assert.DoesNotThrowAsync(async () => - { - build = await client.StartBuildAsync(engineId, tbc); - }); - ServalApiException? ex = Assert.ThrowsAsync(async () => + TranslationBuild build = await client.StartBuildAsync(engineId, tbc); + var ex = Assert.ThrowsAsync(async () => { build = await client.StartBuildAsync(engineId, tbc); }); - Assert.NotNull(ex); - Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode)); + Assert.That(ex, Is.Not.Null); + Assert.That(ex.StatusCode, Is.EqualTo(expectedStatusCode)); } [Test] public void AddCorpusWithSameSourceAndTargetLangs() { ITranslationEnginesClient client = _env!.CreateClient(); - ServalApiException? ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.AddCorpusAsync(NMT_ENGINE1_ID, _testCorpusConfig!); }); - Assert.NotNull(ex); - Assert.That(ex!.StatusCode, Is.EqualTo(422)); + Assert.That(ex, Is.Not.Null); + Assert.That(ex.StatusCode, Is.EqualTo(422)); } [TearDown] @@ -1219,8 +1125,7 @@ private class TestEnvironment : DisposableBase public TestEnvironment() { - var clientSettings = new MongoClientSettings(); - clientSettings.LinqProvider = LinqProvider.V2; + var clientSettings = new MongoClientSettings { LinqProvider = LinqProvider.V2 }; _mongoClient = new MongoClient(clientSettings); ResetDatabases(); @@ -1229,48 +1134,42 @@ public TestEnvironment() Engines = _scope.ServiceProvider.GetRequiredService>(); DataFiles = _scope.ServiceProvider.GetRequiredService>(); Pretranslations = _scope.ServiceProvider.GetRequiredService< - IRepository + IRepository >(); - Builds = _scope.ServiceProvider.GetRequiredService>(); + Builds = _scope.ServiceProvider.GetRequiredService>(); } ServalWebApplicationFactory Factory { get; } public IRepository Engines { get; } public IRepository DataFiles { get; } - public IRepository Pretranslations { get; } - public IRepository Builds { get; } + public IRepository Pretranslations { get; } + public IRepository Builds { get; } - public TranslationEnginesClient CreateClient( - IEnumerable? scope = null, - bool delayedBuildService = false - ) + public TranslationEnginesClient CreateClient(IEnumerable? scope = null) { - if (scope is null) + scope ??= new[] { - scope = new[] - { - Scopes.CreateTranslationEngines, - Scopes.ReadTranslationEngines, - Scopes.UpdateTranslationEngines, - Scopes.DeleteTranslationEngines - }; - } - var httpClient = Factory + Scopes.CreateTranslationEngines, + Scopes.ReadTranslationEngines, + Scopes.UpdateTranslationEngines, + Scopes.DeleteTranslationEngines + }; + HttpClient httpClient = Factory .WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { - var echo_client = Substitute.For(); - echo_client + var echoClient = Substitute.For(); + echoClient .CreateAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - echo_client + echoClient .DeleteAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - echo_client + echoClient .StartBuildAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - echo_client + echoClient .CancelBuildAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); var wg = new Translation.V1.WordGraph @@ -1306,7 +1205,7 @@ public TranslationEnginesClient CreateClient( } }; var wgr = new GetWordGraphResponse { WordGraph = wg }; - echo_client + echoClient .TrainSegmentPairAsync( Arg.Any(), null, @@ -1314,7 +1213,7 @@ public TranslationEnginesClient CreateClient( Arg.Any() ) .Returns(CreateAsyncUnaryCall(new Empty())); - echo_client + echoClient .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(wgr)); @@ -1386,37 +1285,37 @@ public TranslationEnginesClient CreateClient( } }; var translateResponse = new TranslateResponse { Results = { translationResult } }; - echo_client + echoClient .TranslateAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(translateResponse)); - var nmt_client = Substitute.For(); - nmt_client + var nmtClient = Substitute.For(); + nmtClient .CreateAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - nmt_client + nmtClient .DeleteAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - nmt_client + nmtClient .StartBuildAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - nmt_client + nmtClient .CancelBuildAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new Empty())); - nmt_client + nmtClient .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new GetWordGraphResponse(), true)); - nmt_client + nmtClient .TranslateAsync(Arg.Any(), null, null, Arg.Any()) .Returns(CreateAsyncUnaryCall(new TranslateResponse(), true)); var grpcClientFactory = Substitute.For(); grpcClientFactory .CreateClient("Echo") - .Returns(echo_client); + .Returns(echoClient); grpcClientFactory .CreateClient("Nmt") - .Returns(nmt_client); + .Returns(nmtClient); services.AddSingleton(grpcClientFactory); }); }) diff --git a/tests/Serval.ApiServer.IntegrationTests/WebhooksTests.cs b/tests/Serval.ApiServer.IntegrationTests/WebhooksTests.cs index ba852c06..c29a6a18 100644 --- a/tests/Serval.ApiServer.IntegrationTests/WebhooksTests.cs +++ b/tests/Serval.ApiServer.IntegrationTests/WebhooksTests.cs @@ -29,19 +29,14 @@ public async Task Setup() [Test] [TestCase(null, 200)] //null gives all scope privileges - public void GetAllWebhooksAsync(IEnumerable? scope, int expectedStatusCode) + public async Task GetAllWebhooksAsync(IEnumerable? scope, int expectedStatusCode) { WebhooksClient client = _env!.CreateClient(scope); switch (expectedStatusCode) { case 200: - Serval.Client.Webhook? result = null; - Assert.DoesNotThrowAsync(async () => - { - result = (await client.GetAllAsync()).First(); - }); - Assert.NotNull(result); - Assert.That(result!.Id, Is.EqualTo(ID)); + Webhook result = (await client.GetAllAsync()).First(); + Assert.That(result.Id, Is.EqualTo(ID)); break; default: Assert.Fail("Unanticipated expectedStatusCode. Check test case for typo."); @@ -52,23 +47,17 @@ public void GetAllWebhooksAsync(IEnumerable? scope, int expectedStatusCo [Test] [TestCase(null, 200, ID)] //null gives all scope privileges [TestCase(null, 404, DOES_NOT_EXIST_ID)] - public void GetWebhookByIdAsync(IEnumerable? scope, int expectedStatusCode, string webhookId) + public async Task GetWebhookByIdAsync(IEnumerable? scope, int expectedStatusCode, string webhookId) { WebhooksClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; switch (expectedStatusCode) { case 200: - Serval.Client.Webhook? result = null; - Assert.DoesNotThrowAsync(async () => - { - result = await client.GetAsync(webhookId); - }); - Assert.NotNull(result); - Assert.That(result!.Id, Is.EqualTo(ID)); + Webhook result = await client.GetAsync(webhookId); + Assert.That(result.Id, Is.EqualTo(ID)); break; case 404: - ex = Assert.ThrowsAsync(async () => + var ex = Assert.ThrowsAsync(async () => { await client.GetAsync(webhookId); }); @@ -83,17 +72,14 @@ public void GetWebhookByIdAsync(IEnumerable? scope, int expectedStatusCo [Test] [TestCase(null, 200, ID)] //null gives all scope privileges [TestCase(null, 404, DOES_NOT_EXIST_ID)] - public void DeleteWebhookByIdAsync(IEnumerable? scope, int expectedStatusCode, string webhookId) + public async Task DeleteWebhookByIdAsync(IEnumerable? scope, int expectedStatusCode, string webhookId) { WebhooksClient client = _env!.CreateClient(scope); - ServalApiException? ex = null; + ServalApiException ex; switch (expectedStatusCode) { case 200: - Assert.DoesNotThrowAsync(async () => - { - await client.DeleteAsync(webhookId); - }); + await client.DeleteAsync(webhookId); ex = Assert.ThrowsAsync(async () => { await client.GetAsync(webhookId); @@ -115,34 +101,22 @@ public void DeleteWebhookByIdAsync(IEnumerable? scope, int expectedStatu [Test] [TestCase(null, 201)] - public void CreateWebhookAsync(IEnumerable scope, int expectedStatusCode) + public async Task CreateWebhookAsync(IEnumerable scope, int expectedStatusCode) { WebhooksClient client = _env!.CreateClient(scope); switch (expectedStatusCode) { case 201: - Serval.Client.Webhook? result = null; - Assert.DoesNotThrowAsync(async () => - { - result = await client.CreateAsync( - new WebhookConfig - { - PayloadUrl = "/a/different/url", - Secret = "M0rEs3CreTz#", - Events = new List - { - Serval.Client.WebhookEvent.TranslationBuildStarted - } - } - ); - }); - Serval.Client.Webhook? result_afterCreate = null; - Assert.DoesNotThrowAsync(async () => - { - result_afterCreate = await client.GetAsync(result!.Id); - }); - Assert.NotNull(result_afterCreate); - Assert.That(result_afterCreate!.PayloadUrl, Is.EqualTo(result!.PayloadUrl)); + Webhook result = await client.CreateAsync( + new WebhookConfig + { + PayloadUrl = "/a/different/url", + Secret = "M0rEs3CreTz#", + Events = { WebhookEvent.TranslationBuildStarted } + } + ); + Webhook resultAfterCreate = await client.GetAsync(result.Id); + Assert.That(resultAfterCreate.PayloadUrl, Is.EqualTo(result.PayloadUrl)); break; default: diff --git a/tests/Serval.E2ETests/E2EMissingServicesTests.cs b/tests/Serval.E2ETests/MissingServicesTests.cs similarity index 99% rename from tests/Serval.E2ETests/E2EMissingServicesTests.cs rename to tests/Serval.E2ETests/MissingServicesTests.cs index ef2312dc..f1e56ec6 100644 --- a/tests/Serval.E2ETests/E2EMissingServicesTests.cs +++ b/tests/Serval.E2ETests/MissingServicesTests.cs @@ -2,7 +2,7 @@ namespace Serval.E2ETests { [TestFixture] [Category("E2EMissingServices")] - public class E2EMissingServicesTests + public class MissingServicesTests { private ServalClientHelper? _helperClient; diff --git a/tests/Serval.E2ETests/Serval.E2ETests.csproj b/tests/Serval.E2ETests/Serval.E2ETests.csproj index 25fc7b0d..d60d5d41 100644 --- a/tests/Serval.E2ETests/Serval.E2ETests.csproj +++ b/tests/Serval.E2ETests/Serval.E2ETests.csproj @@ -1,25 +1,20 @@  - - net6.0 - enable - enable - + + net6.0 + enable + enable + - - - - - + + + + + - - - - - - - - - + + + + diff --git a/tests/Serval.E2ETests/E2ETests.cs b/tests/Serval.E2ETests/ServalApiTests.cs similarity index 98% rename from tests/Serval.E2ETests/E2ETests.cs rename to tests/Serval.E2ETests/ServalApiTests.cs index d4cfeefd..7c9c18d4 100644 --- a/tests/Serval.E2ETests/E2ETests.cs +++ b/tests/Serval.E2ETests/ServalApiTests.cs @@ -1,14 +1,12 @@ -using static Serval.Shared.Utils.AutoToString; - -namespace Serval.ApiServerE2E; +namespace Serval.E2ETests; [TestFixture] [Category("E2E")] -public class E2ETests +public class ServalApiTests { private ServalClientHelper _helperClient; - public E2ETests() + public ServalApiTests() { _helperClient = InitializeClient(); } @@ -256,7 +254,7 @@ await _helperClient.AddTextCorpusToEngine( .MaxBy(arc => arc.Confidences.Average())! .TargetTokens.All(tk => tk == "truth"), "Best translation should have been 'truth'but returned word graph: \n{0}", - Stringify(result) + JsonSerializer.Serialize(result) ); } @@ -301,7 +299,7 @@ public async Task CircuitousRouteTranslateTopNAsync() Assert.That( results.MaxBy(t => t.Confidences.Average())!.Translation, Is.EqualTo("amour"), - "Expected best translation to be 'amour' but results were this:\n" + Stringify(results) + "Expected best translation to be 'amour' but results were this:\n" + JsonSerializer.Serialize(results) ); } diff --git a/tests/Serval.E2ETests/Usings.cs b/tests/Serval.E2ETests/Usings.cs index 3236511c..8bf6b1ca 100644 --- a/tests/Serval.E2ETests/Usings.cs +++ b/tests/Serval.E2ETests/Usings.cs @@ -1,2 +1,3 @@ -global using NUnit.Framework; +global using System.Text.Json; +global using NUnit.Framework; global using Serval.Client; diff --git a/tests/Serval.Translation.Tests/Usings.cs b/tests/Serval.Translation.Tests/Usings.cs index 241902b7..22d7d58e 100644 --- a/tests/Serval.Translation.Tests/Usings.cs +++ b/tests/Serval.Translation.Tests/Usings.cs @@ -1,8 +1,6 @@ global using Grpc.Core; global using Grpc.Net.ClientFactory; global using Microsoft.Extensions.Options; -global using MongoDB.Bson; -global using MongoDB.Bson.Serialization.Attributes; global using NSubstitute; global using NUnit.Framework; global using Serval.Shared.Configuration; diff --git a/tests/Serval.Webhooks.Tests/Usings.cs b/tests/Serval.Webhooks.Tests/Usings.cs index 2897d389..fb600d13 100644 --- a/tests/Serval.Webhooks.Tests/Usings.cs +++ b/tests/Serval.Webhooks.Tests/Usings.cs @@ -2,8 +2,6 @@ global using System.Text.Json.Serialization; global using Microsoft.AspNetCore.Mvc; global using Microsoft.Extensions.Options; -global using MongoDB.Bson; -global using MongoDB.Bson.Serialization.Attributes; global using NSubstitute; global using NUnit.Framework; global using RichardSzalay.MockHttp;