diff --git a/src/Serval.Client/Client.g.cs b/src/Serval.Client/Client.g.cs
index e44dbf1b..02de8cdf 100644
--- a/src/Serval.Client/Client.g.cs
+++ b/src/Serval.Client/Client.g.cs
@@ -970,26 +970,15 @@ public partial interface ITranslationEnginesClient
///
* The references defined in the SourceFile per line, if any.
///
* An auto-generated reference of `[TextId]:[lineNumber]`, 1 indexed.
///
* **Translation**: the text of the pretranslation
+ ///
+ ///
Pretranslations can be filtered by text id if provided.
///
/// The translation engine id
/// The corpus id
+ /// The text id (optional)
/// The pretranslations
/// A server side error occurred.
- System.Threading.Tasks.Task> GetAllPretranslationsAsync(string id, string corpusId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Gets all pretranslations from a TextId
- ///
- ///
- /// Similar to "get all pretranslations of a corpus," except that the results are filtered by TextId.
- ///
- /// The translation engine id
- /// The corpus id
- /// The text id
- /// The pretranslations
- /// A server side error occurred.
- System.Threading.Tasks.Task> GetAllPretranslations2Async(string id, string corpusId, string textId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
+ System.Threading.Tasks.Task> GetAllPretranslationsAsync(string id, string corpusId, string? textId = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken));
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
@@ -2588,12 +2577,15 @@ public string BaseUrl
///
* The references defined in the SourceFile per line, if any.
///
* An auto-generated reference of `[TextId]:[lineNumber]`, 1 indexed.
///
* **Translation**: the text of the pretranslation
+ ///
+ ///
Pretranslations can be filtered by text id if provided.
///
/// The translation engine id
/// The corpus id
+ /// The text id (optional)
/// The pretranslations
/// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> GetAllPretranslationsAsync(string id, string corpusId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
+ public virtual async System.Threading.Tasks.Task> GetAllPretranslationsAsync(string id, string corpusId, string? textId = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
{
if (id == null)
throw new System.ArgumentNullException("id");
@@ -2602,133 +2594,14 @@ public string BaseUrl
throw new System.ArgumentNullException("corpusId");
var urlBuilder_ = new System.Text.StringBuilder();
- urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/translation/engines/{id}/corpora/{corpusId}/pretranslations");
+ urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/translation/engines/{id}/corpora/{corpusId}/pretranslations?");
urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture)));
urlBuilder_.Replace("{corpusId}", System.Uri.EscapeDataString(ConvertToString(corpusId, System.Globalization.CultureInfo.InvariantCulture)));
-
- var client_ = _httpClient;
- var disposeClient_ = false;
- try
- {
- using (var request_ = new System.Net.Http.HttpRequestMessage())
- {
- request_.Method = new System.Net.Http.HttpMethod("GET");
- request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
-
- PrepareRequest(client_, request_, urlBuilder_);
-
- var url_ = urlBuilder_.ToString();
- request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
-
- PrepareRequest(client_, request_, url_);
-
- var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
- var disposeResponse_ = true;
- try
- {
- var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
- if (response_.Content != null && response_.Content.Headers != null)
- {
- foreach (var item_ in response_.Content.Headers)
- headers_[item_.Key] = item_.Value;
- }
-
- ProcessResponse(client_, response_);
-
- var status_ = (int)response_.StatusCode;
- if (status_ == 200)
- {
- var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false);
- if (objectResponse_.Object == null)
- {
- throw new ServalApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
- }
- return objectResponse_.Object;
- }
- else
- if (status_ == 401)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The client is not authenticated", status_, responseText_, headers_, null);
- }
- else
- if (status_ == 403)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The authenticated client cannot perform the operation or does not own the translation engine", status_, responseText_, headers_, null);
- }
- else
- if (status_ == 404)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The engine or corpus does not exist", status_, responseText_, headers_, null);
- }
- else
- if (status_ == 405)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The method is not supported", status_, responseText_, headers_, null);
- }
- else
- if (status_ == 409)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The engine needs to be built first", status_, responseText_, headers_, null);
- }
- else
- 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);
- }
- else
- {
- var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
- }
- }
- finally
- {
- if (disposeResponse_)
- response_.Dispose();
- }
- }
- }
- finally
+ if (textId != null)
{
- if (disposeClient_)
- client_.Dispose();
+ urlBuilder_.Append(System.Uri.EscapeDataString("textId") + "=").Append(System.Uri.EscapeDataString(ConvertToString(textId, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
}
- }
-
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- /// Gets all pretranslations from a TextId
- ///
- ///
- /// Similar to "get all pretranslations of a corpus," except that the results are filtered by TextId.
- ///
- /// The translation engine id
- /// The corpus id
- /// The text id
- /// The pretranslations
- /// A server side error occurred.
- public virtual async System.Threading.Tasks.Task> GetAllPretranslations2Async(string id, string corpusId, string textId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken))
- {
- if (id == null)
- throw new System.ArgumentNullException("id");
-
- if (corpusId == null)
- throw new System.ArgumentNullException("corpusId");
-
- if (textId == null)
- throw new System.ArgumentNullException("textId");
-
- var urlBuilder_ = new System.Text.StringBuilder();
- urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/translation/engines/{id}/corpora/{corpusId}/pretranslations/{textId}");
- urlBuilder_.Replace("{id}", System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture)));
- urlBuilder_.Replace("{corpusId}", System.Uri.EscapeDataString(ConvertToString(corpusId, System.Globalization.CultureInfo.InvariantCulture)));
- urlBuilder_.Replace("{textId}", System.Uri.EscapeDataString(ConvertToString(textId, System.Globalization.CultureInfo.InvariantCulture)));
+ urlBuilder_.Length--;
var client_ = _httpClient;
var disposeClient_ = false;
@@ -2785,13 +2658,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 corpus or text does not exist", status_, responseText_, headers_, null);
- }
- else
- if (status_ == 405)
- {
- string responseText_ = ( response_.Content == null ) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
- throw new ServalApiException("The method is not supported", status_, responseText_, headers_, null);
+ throw new ServalApiException("The engine or corpus does not exist", status_, responseText_, headers_, null);
}
else
if (status_ == 409)
diff --git a/src/Serval.Shared/Controllers/AbortedRpcExceptionFilter.cs b/src/Serval.Shared/Controllers/AbortedRpcExceptionFilter.cs
new file mode 100644
index 00000000..1685ffd5
--- /dev/null
+++ b/src/Serval.Shared/Controllers/AbortedRpcExceptionFilter.cs
@@ -0,0 +1,13 @@
+namespace Serval.Shared.Controllers;
+
+public class AbortedRpcExceptionFilter : ExceptionFilterAttribute
+{
+ public override void OnException(ExceptionContext context)
+ {
+ if (context.Exception is RpcException rpcException && rpcException.StatusCode == StatusCode.Aborted)
+ {
+ context.Result = new ConflictObjectResult(rpcException.Message);
+ context.ExceptionHandled = true;
+ }
+ }
+}
diff --git a/src/Serval.Shared/Controllers/HttpResultFilter.cs b/src/Serval.Shared/Controllers/ErrorResultFilter.cs
similarity index 74%
rename from src/Serval.Shared/Controllers/HttpResultFilter.cs
rename to src/Serval.Shared/Controllers/ErrorResultFilter.cs
index eb381ae2..68207df8 100644
--- a/src/Serval.Shared/Controllers/HttpResultFilter.cs
+++ b/src/Serval.Shared/Controllers/ErrorResultFilter.cs
@@ -2,13 +2,13 @@
namespace Serval.Shared.Controllers
{
- public class HttpResultFilter : ResultFilterAttribute
+ public class ErrorResultFilter : ResultFilterAttribute
{
private readonly ILogger _logger;
- public HttpResultFilter(ILoggerFactory loggerFactory)
+ public ErrorResultFilter(ILoggerFactory loggerFactory)
{
- _logger = loggerFactory.CreateLogger();
+ _logger = loggerFactory.CreateLogger();
}
public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
diff --git a/src/Serval.Shared/Controllers/ServalControllerBase.cs b/src/Serval.Shared/Controllers/ServalControllerBase.cs
index 7ca55c75..bebcdf29 100644
--- a/src/Serval.Shared/Controllers/ServalControllerBase.cs
+++ b/src/Serval.Shared/Controllers/ServalControllerBase.cs
@@ -4,8 +4,9 @@
[Produces("application/json")]
[TypeFilter(typeof(OperationCancelledExceptionFilter))]
[TypeFilter(typeof(NotSupportedExceptionFilter))]
-[TypeFilter(typeof(ServiceUnavailableException))]
-[TypeFilter(typeof(HttpResultFilter))]
+[TypeFilter(typeof(ServiceUnavailableExceptionFilter))]
+[TypeFilter(typeof(ErrorResultFilter))]
+[TypeFilter(typeof(AbortedRpcExceptionFilter))]
public abstract class ServalControllerBase : Controller
{
private readonly IAuthorizationService _authService;
diff --git a/src/Serval.Shared/Controllers/ServiceUnavailableExceptionFilter.cs b/src/Serval.Shared/Controllers/ServiceUnavailableExceptionFilter.cs
index e9039f08..b7f2ca4d 100644
--- a/src/Serval.Shared/Controllers/ServiceUnavailableExceptionFilter.cs
+++ b/src/Serval.Shared/Controllers/ServiceUnavailableExceptionFilter.cs
@@ -1,21 +1,19 @@
-using Newtonsoft.Json.Linq;
-
namespace Serval.Shared.Controllers;
-public class ServiceUnavailableException : ExceptionFilterAttribute
+public class ServiceUnavailableExceptionFilter : ExceptionFilterAttribute
{
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
- public ServiceUnavailableException(ILoggerFactory loggerFactory)
+ public ServiceUnavailableExceptionFilter(ILoggerFactory loggerFactory)
{
- _logger = loggerFactory.CreateLogger();
+ _logger = loggerFactory.CreateLogger();
}
public override void OnException(ExceptionContext context)
{
if (
- (context.Exception is System.TimeoutException)
- || (context.Exception is Grpc.Core.RpcException rpcEx && rpcEx.StatusCode == StatusCode.Unavailable)
+ (context.Exception is TimeoutException)
+ || (context.Exception is RpcException rpcEx && rpcEx.StatusCode == StatusCode.Unavailable)
)
{
_logger.Log(
diff --git a/src/Serval.Translation/Controllers/TranslationEnginesController.cs b/src/Serval.Translation/Controllers/TranslationEnginesController.cs
index fd66331d..8507a721 100644
--- a/src/Serval.Translation/Controllers/TranslationEnginesController.cs
+++ b/src/Serval.Translation/Controllers/TranslationEnginesController.cs
@@ -1,7 +1,4 @@
-using Serval.Translation.Models;
-using System.Threading;
-
-namespace Serval.Translation.Controllers;
+namespace Serval.Translation.Controllers;
[ApiVersion(1.0)]
[Route("api/v{version:apiVersion}/translation/engines")]
@@ -218,8 +215,6 @@ CancellationToken cancellationToken
{
if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult))
return errorResult;
- if (!await IsBuilt(id))
- return Conflict();
TranslationResult? result = await _engineService.TranslateAsync(id, segment, cancellationToken);
if (result == null)
@@ -261,8 +256,6 @@ CancellationToken cancellationToken
{
if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult))
return errorResult;
- if (!await IsBuilt(id))
- return Conflict();
IEnumerable? results = await _engineService.TranslateAsync(
id,
@@ -307,8 +300,6 @@ CancellationToken cancellationToken
{
if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult))
return errorResult;
- if (!await IsBuilt(id))
- return Conflict();
WordGraph? wordGraph = await _engineService.GetWordGraphAsync(id, segment, cancellationToken);
if (wordGraph == null)
@@ -351,8 +342,6 @@ CancellationToken cancellationToken
{
if (!(await AuthorizeAsync(id, cancellationToken)).IsSuccess(out ActionResult? errorResult))
return errorResult;
- if (!await IsBuilt(id))
- return Conflict();
if (
!await _engineService.TrainSegmentPairAsync(
@@ -600,15 +589,17 @@ CancellationToken cancellationToken
/// * The references defined in the SourceFile per line, if any.
/// * An auto-generated reference of `[TextId]:[lineNumber]`, 1 indexed.
/// * **Translation**: the text of the pretranslation
+ ///
+ /// Pretranslations can be filtered by text id if provided.
///
/// The translation engine id
/// The corpus id
+ /// The text id (optional)
///
/// The pretranslations
/// The client is not authenticated
/// The authenticated client cannot perform the operation or does not own the translation engine
/// The engine or corpus does not exist
- /// The method is not supported
/// The engine needs to be built first
/// A necessary service is currently unavailable. Check `/health` for more details.
[Authorize(Scopes.ReadTranslationEngines)]
@@ -617,12 +608,12 @@ CancellationToken cancellationToken
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
[ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)]
- [ProducesResponseType(typeof(void), StatusCodes.Status405MethodNotAllowed)]
[ProducesResponseType(typeof(void), StatusCodes.Status409Conflict)]
[ProducesResponseType(typeof(void), StatusCodes.Status503ServiceUnavailable)]
public async Task>> GetAllPretranslationsAsync(
[NotNull] string id,
[NotNull] string corpusId,
+ [FromQuery] string? textId,
CancellationToken cancellationToken
)
{
@@ -631,57 +622,11 @@ CancellationToken cancellationToken
return NotFound();
if (!await AuthorizeIsOwnerAsync(engine))
return Forbid();
- IEnumerable pretranslations = await _pretranslationService.GetAllAsync(
- id,
- engine.ModelRevision,
- corpusId,
- cancellationToken
- );
- if (pretranslations is null || pretranslations.Count() == 0)
+ if (!engine.Corpora.Any(c => c.Id == corpusId))
return NotFound();
- if (!await IsBuilt(id))
+ if (engine.ModelRevision == 0)
return Conflict();
- return Ok((pretranslations).Select(Map));
- }
- ///
- /// Gets all pretranslations from a TextId
- ///
- ///
- /// Similar to "get all pretranslations of a corpus," except that the results are filtered by TextId.
- ///
- /// The translation engine id
- /// The corpus id
- /// The text id
- ///
- /// The pretranslations
- /// The client is not authenticated
- /// The authenticated client cannot perform the operation or does not own the translation engine
- /// The engine or corpus or text does not exist
- /// The method is not supported
- /// The engine needs to be built first
- /// A necessary service is currently unavailable. Check `/health` for more details.
- [Authorize(Scopes.ReadTranslationEngines)]
- [HttpGet("{id}/corpora/{corpusId}/pretranslations/{textId}")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- [ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
- [ProducesResponseType(typeof(void), StatusCodes.Status403Forbidden)]
- [ProducesResponseType(typeof(void), StatusCodes.Status404NotFound)]
- [ProducesResponseType(typeof(void), StatusCodes.Status405MethodNotAllowed)]
- [ProducesResponseType(typeof(void), StatusCodes.Status409Conflict)]
- [ProducesResponseType(typeof(void), StatusCodes.Status503ServiceUnavailable)]
- public async Task>> GetAllPretranslationsAsync(
- [NotNull] string id,
- [NotNull] string corpusId,
- [NotNull] string textId,
- CancellationToken cancellationToken
- )
- {
- Engine? engine = await _engineService.GetAsync(id, cancellationToken);
- if (engine == null)
- return NotFound();
- if (!await AuthorizeIsOwnerAsync(engine))
- return Forbid();
IEnumerable pretranslations = await _pretranslationService.GetAllAsync(
id,
engine.ModelRevision,
@@ -689,11 +634,7 @@ CancellationToken cancellationToken
textId,
cancellationToken
);
- if (pretranslations is null || pretranslations.Count() == 0)
- return NotFound();
- if (!await IsBuilt(id))
- return Conflict();
- return Ok((pretranslations).Select(Map));
+ return Ok(pretranslations.Select(Map));
}
///
@@ -1186,10 +1127,4 @@ private TranslationCorpusFileDto Map(CorpusFile source)
TextId = source.TextId
};
}
-
- 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/Services/IPretranslationService.cs b/src/Serval.Translation/Services/IPretranslationService.cs
index 762d5ea6..40ea2920 100644
--- a/src/Serval.Translation/Services/IPretranslationService.cs
+++ b/src/Serval.Translation/Services/IPretranslationService.cs
@@ -6,13 +6,7 @@ Task> GetAllAsync(
string engineId,
int modelRevision,
string corpusId,
- CancellationToken cancellationToken = default
- );
- Task> GetAllAsync(
- string engineId,
- int modelRevision,
- string corpusId,
- string textId,
+ string? textId = null,
CancellationToken cancellationToken = default
);
}
diff --git a/src/Serval.Translation/Services/PretranslationService.cs b/src/Serval.Translation/Services/PretranslationService.cs
index db231b0e..917f1239 100644
--- a/src/Serval.Translation/Services/PretranslationService.cs
+++ b/src/Serval.Translation/Services/PretranslationService.cs
@@ -9,20 +9,7 @@ public async Task> GetAllAsync(
string engineId,
int modelRevision,
string corpusId,
- CancellationToken cancellationToken = default
- )
- {
- return await Entities.GetAllAsync(
- pt => pt.EngineRef == engineId && pt.ModelRevision == modelRevision && pt.CorpusRef == corpusId,
- cancellationToken
- );
- }
-
- public async Task> GetAllAsync(
- string engineId,
- int modelRevision,
- string corpusId,
- string textId,
+ string? textId = null,
CancellationToken cancellationToken = default
)
{
@@ -31,7 +18,7 @@ public async Task> GetAllAsync(
pt.EngineRef == engineId
&& pt.ModelRevision == modelRevision
&& pt.CorpusRef == corpusId
- && pt.TextId == textId,
+ && (textId == null || pt.TextId == textId),
cancellationToken
);
}
diff --git a/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs b/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs
index bb2a2129..ed5cd037 100644
--- a/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs
+++ b/tests/Serval.ApiServer.IntegrationTests/TranslationEngineTests.cs
@@ -7,21 +7,50 @@ namespace Serval.ApiServer;
[Category("Integration")]
public class TranslationEngineTests
{
- TestEnvironment? _env;
- TranslationCorpusConfig? _testCorpusConfig;
- TranslationCorpusConfig? _testCorpusConfigNonEcho;
+ private readonly TranslationCorpusConfig TestCorpusConfig =
+ new()
+ {
+ Name = "TestCorpus",
+ SourceLanguage = "en",
+ TargetLanguage = "en",
+ SourceFiles =
+ {
+ new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" }
+ },
+ TargetFiles =
+ {
+ new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" }
+ }
+ };
+ private readonly TranslationCorpusConfig TestCorpusConfigNonEcho =
+ new()
+ {
+ Name = "TestCorpus",
+ SourceLanguage = "en",
+ TargetLanguage = "es",
+ SourceFiles =
+ {
+ new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" }
+ },
+ TargetFiles =
+ {
+ new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" }
+ }
+ };
- const string ECHO_ENGINE1_ID = "e00000000000000000000001";
- const string ECHO_ENGINE2_ID = "e00000000000000000000002";
- const string ECHO_ENGINE3_ID = "e00000000000000000000003";
- const string SMT_ENGINE1_ID = "be0000000000000000000001";
- const string NMT_ENGINE1_ID = "ce0000000000000000000001";
- const string FILE1_ID = "f00000000000000000000001";
- const string FILE1_FILENAME = "abcd";
- const string FILE2_ID = "f00000000000000000000002";
- const string FILE2_FILENAME = "efgh";
- const string DOES_NOT_EXIST_ENGINE_ID = "e00000000000000000000004";
- const string DOES_NOT_EXIST_CORPUS_ID = "c00000000000000000000001";
+ private const string ECHO_ENGINE1_ID = "e00000000000000000000001";
+ private const string ECHO_ENGINE2_ID = "e00000000000000000000002";
+ private const string ECHO_ENGINE3_ID = "e00000000000000000000003";
+ private const string SMT_ENGINE1_ID = "be0000000000000000000001";
+ private const string NMT_ENGINE1_ID = "ce0000000000000000000001";
+ private const string FILE1_ID = "f00000000000000000000001";
+ private const string FILE1_FILENAME = "abcd";
+ private const string FILE2_ID = "f00000000000000000000002";
+ private const string FILE2_FILENAME = "efgh";
+ private const string DOES_NOT_EXIST_ENGINE_ID = "e00000000000000000000004";
+ private const string DOES_NOT_EXIST_CORPUS_ID = "c00000000000000000000001";
+
+ private TestEnvironment? _env;
[SetUp]
public async Task SetUp()
@@ -97,35 +126,6 @@ public async Task SetUp()
Format = Shared.Contracts.FileFormat.Text
};
await _env.DataFiles.InsertAllAsync(new[] { srcFile, trgFile });
-
- _testCorpusConfig = new TranslationCorpusConfig
- {
- Name = "TestCorpus",
- SourceLanguage = "en",
- TargetLanguage = "en",
- SourceFiles =
- {
- new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" }
- },
- TargetFiles =
- {
- new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" }
- }
- };
- _testCorpusConfigNonEcho = new TranslationCorpusConfig
- {
- Name = "TestCorpus",
- SourceLanguage = "en",
- TargetLanguage = "es",
- SourceFiles =
- {
- new TranslationCorpusFileConfig { FileId = FILE1_ID, TextId = "all" }
- },
- TargetFiles =
- {
- new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" }
- }
- };
}
[Test]
@@ -283,6 +283,7 @@ string engineId
)
{
ITranslationEnginesClient client = _env!.CreateClient(scope);
+ ServalApiException ex;
switch (expectedStatusCode)
{
case 200:
@@ -297,14 +298,22 @@ await _env.Builds.InsertAsync(
Has.All.EquivalentTo(new[] { Client.TranslationSource.Primary, Client.TranslationSource.Secondary })
);
break;
- case 404:
case 409:
- var ex = Assert.ThrowsAsync(async () =>
+ _env.EchoClient
+ .TranslateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Aborted));
+ ex = Assert.ThrowsAsync(async () =>
+ {
+ await client.TranslateAsync(engineId, "This is a test .");
+ });
+ Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
+ break;
+ case 404:
+ ex = Assert.ThrowsAsync(async () =>
{
await client.TranslateAsync(engineId, "This is a test .");
});
Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
-
break;
default:
Assert.Fail("Unanticipated expectedStatusCode. Check test case for typo.");
@@ -323,6 +332,7 @@ string engineId
)
{
ITranslationEnginesClient client = _env!.CreateClient(scope);
+ ServalApiException ex;
switch (expectedStatusCode)
{
case 200:
@@ -342,14 +352,22 @@ await _env.Builds.InsertAsync(
Has.All.EquivalentTo(new[] { Client.TranslationSource.Primary, Client.TranslationSource.Secondary })
);
break;
- case 404:
case 409:
- var ex = Assert.ThrowsAsync(async () =>
+ _env.EchoClient
+ .TranslateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Aborted));
+ ex = Assert.ThrowsAsync(async () =>
+ {
+ await client.TranslateNAsync(engineId, 1, "This is a test .");
+ });
+ Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
+ break;
+ case 404:
+ ex = Assert.ThrowsAsync(async () =>
{
await client.TranslateNAsync(engineId, 1, "This is a test .");
});
Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
-
break;
default:
Assert.Fail("Unanticipated expectedStatusCode. Check test case for typo.");
@@ -368,10 +386,11 @@ string engineId
)
{
ITranslationEnginesClient client = _env!.CreateClient(scope);
+ ServalApiException ex;
switch (expectedStatusCode)
{
case 200:
- TranslationCorpus addedCorpus = 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 }
);
@@ -382,9 +401,18 @@ await _env.Builds.InsertAsync(
Assert.That(wg.Arcs, Has.Count.EqualTo(4));
});
break;
- case 404:
case 409:
- var ex = Assert.ThrowsAsync(async () =>
+ _env.EchoClient
+ .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Aborted));
+ ex = Assert.ThrowsAsync(async () =>
+ {
+ await client.GetWordGraphAsync(engineId, "This is a test .");
+ });
+ Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
+ break;
+ case 404:
+ ex = Assert.ThrowsAsync(async () =>
{
await client.GetWordGraphAsync(engineId, "This is a test .");
});
@@ -413,18 +441,28 @@ string engineId
TargetSegment = "This is a test .",
SentenceStart = true
};
+ ServalApiException ex;
switch (expectedStatusCode)
{
case 200:
- TranslationCorpus addedCorpus = 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 }
);
await client.TrainSegmentAsync(engineId, sp);
break;
- case 404:
case 409:
- var ex = Assert.ThrowsAsync(async () =>
+ _env.EchoClient
+ .TrainSegmentPairAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Aborted));
+ ex = Assert.ThrowsAsync(async () =>
+ {
+ await client.TrainSegmentAsync(engineId, sp);
+ });
+ Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
+ break;
+ case 404:
+ ex = Assert.ThrowsAsync(async () =>
{
await client.TrainSegmentAsync(engineId, sp);
});
@@ -445,7 +483,7 @@ public async Task AddCorpusToEngineByIdAsync(IEnumerable scope, int expe
switch (expectedStatusCode)
{
case 201:
- TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ TranslationCorpus result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
Assert.Multiple(() =>
{
Assert.That(result.Name, Is.EqualTo("TestCorpus"));
@@ -463,7 +501,7 @@ public async Task AddCorpusToEngineByIdAsync(IEnumerable scope, int expe
case 404:
var ex = Assert.ThrowsAsync(async () =>
{
- result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
});
Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
break;
@@ -499,7 +537,7 @@ string engineId
switch (expectedStatusCode)
{
case 200:
- TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ TranslationCorpus result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
var src = new[]
{
new TranslationCorpusFileConfig { FileId = FILE2_ID, TextId = "all" }
@@ -563,7 +601,7 @@ string engineId
switch (expectedStatusCode)
{
case 200:
- TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ TranslationCorpus result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
TranslationCorpus resultAfterAdd = (await client.GetAllCorporaAsync(engineId)).First();
Assert.Multiple(() =>
{
@@ -603,7 +641,7 @@ public async Task GetCorpusByIdForEngineByIdAsync(
TranslationCorpus? result = null;
if (addCorpus)
{
- result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
}
switch (expectedStatusCode)
{
@@ -647,7 +685,7 @@ string engineId
switch (expectedStatusCode)
{
case 200:
- TranslationCorpus result = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ TranslationCorpus result = await client.AddCorpusAsync(engineId, TestCorpusConfig);
await client.DeleteCorpusAsync(engineId, result.Id);
ICollection resultsAfterDelete = await client.GetAllCorporaAsync(engineId);
Assert.That(resultsAfterDelete, Has.Count.EqualTo(0));
@@ -667,171 +705,114 @@ string engineId
}
[Test]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 200,
- ECHO_ENGINE1_ID
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 409,
- ECHO_ENGINE1_ID
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 404,
- DOES_NOT_EXIST_ENGINE_ID,
- false
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 404,
- ECHO_ENGINE1_ID,
- false
- )]
- public async Task GetAllPretranslationsForCorpusByIdForEngineByIdAsync(
- IEnumerable scope,
- int expectedStatusCode,
- string engineId,
- bool addCorpus = true
- )
+ public async Task GetAllPretranslationsAsync_Exists()
{
- ITranslationEnginesClient client = _env!.CreateClient(scope);
- TranslationCorpus? addedCorpus = null;
- if (addCorpus)
- {
- addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
- var pret = new Translation.Models.Pretranslation
- {
- CorpusRef = addedCorpus.Id,
- TextId = "all",
- EngineRef = engineId,
- Refs = new List { "ref1", "ref2" },
- Translation = "translation"
- };
- await _env.Pretranslations.InsertAsync(pret);
- }
+ ITranslationEnginesClient client = _env!.CreateClient();
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(ECHO_ENGINE1_ID, TestCorpusConfig);
- switch (expectedStatusCode)
+ await _env.Engines.UpdateAsync(ECHO_ENGINE1_ID, u => u.Set(e => e.ModelRevision, 1));
+ var pret = new Translation.Models.Pretranslation
{
- case 200:
- 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 = await client.GetAllPretranslationsAsync(
- engineId,
- addedCorpus!.Id
- );
- Assert.That(results.First().TextId, Is.EqualTo("all"));
- break;
- case 404:
- case 409:
- var ex = Assert.ThrowsAsync(async () =>
- {
- results = await client.GetAllPretranslationsAsync(
- engineId,
- addCorpus ? addedCorpus!.Id : "cccccccccccccccccccccccc"
- );
- });
- Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
- break;
- default:
- Assert.Fail("Unanticipated expectedStatusCode. Check test case for typo.");
- break;
- }
+ CorpusRef = addedCorpus.Id,
+ TextId = "all",
+ EngineRef = ECHO_ENGINE1_ID,
+ Refs = new List { "ref1", "ref2" },
+ Translation = "translation",
+ ModelRevision = 1
+ };
+ await _env.Pretranslations.InsertAsync(pret);
+
+ ICollection results = await client.GetAllPretranslationsAsync(
+ ECHO_ENGINE1_ID,
+ addedCorpus.Id
+ );
+ Assert.That(results.All(p => p.TextId == "all"), Is.True);
}
[Test]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 200,
- ECHO_ENGINE1_ID,
- true,
- "all"
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 409,
- ECHO_ENGINE1_ID,
- true,
- "all"
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 404,
- DOES_NOT_EXIST_ENGINE_ID,
- false,
- "all"
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 404,
- ECHO_ENGINE1_ID,
- false,
- "all"
- )]
- [TestCase(
- new[] { Scopes.ReadTranslationEngines, Scopes.CreateTranslationEngines, Scopes.UpdateTranslationEngines },
- 404,
- ECHO_ENGINE1_ID,
- true,
- "not_the_right_id"
- )]
- public async Task GetPretranslationForTextByIdForCorpusByIdForEngineByIdAsync(
- IEnumerable scope,
- int expectedStatusCode,
- string engineId,
- bool addCorpus,
- string textId
- )
+ public void GetAllPretranslationsAsync_EngineDoesNotExist()
{
- ITranslationEnginesClient client = _env!.CreateClient(scope);
- TranslationCorpus? addedCorpus = null;
- if (addCorpus)
+ ITranslationEnginesClient client = _env!.CreateClient();
+
+ var ex = Assert.ThrowsAsync(
+ () => client.GetAllPretranslationsAsync(DOES_NOT_EXIST_ENGINE_ID, "cccccccccccccccccccccccc")
+ );
+ Assert.That(ex!.StatusCode, Is.EqualTo(404));
+ }
+
+ [Test]
+ public void GetAllPretranslationsAsync_CorpusDoesNotExist()
+ {
+ ITranslationEnginesClient client = _env!.CreateClient();
+
+ var ex = Assert.ThrowsAsync(
+ () => client.GetAllPretranslationsAsync(ECHO_ENGINE1_ID, "cccccccccccccccccccccccc")
+ );
+ Assert.That(ex!.StatusCode, Is.EqualTo(404));
+ }
+
+ [Test]
+ public async Task GetAllPretranslationsAsync_EngineNotBuilt()
+ {
+ ITranslationEnginesClient client = _env!.CreateClient();
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(ECHO_ENGINE1_ID, TestCorpusConfig);
+
+ var ex = Assert.ThrowsAsync(
+ () => client.GetAllPretranslationsAsync(ECHO_ENGINE1_ID, addedCorpus.Id)
+ );
+ Assert.That(ex!.StatusCode, Is.EqualTo(409));
+ }
+
+ [Test]
+ public async Task GetAllPretranslationsAsync_TextIdExists()
+ {
+ ITranslationEnginesClient client = _env!.CreateClient();
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(ECHO_ENGINE1_ID, TestCorpusConfig);
+
+ await _env.Engines.UpdateAsync(ECHO_ENGINE1_ID, u => u.Set(e => e.ModelRevision, 1));
+ var pret = new Translation.Models.Pretranslation
{
- addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
- var pret = new Translation.Models.Pretranslation
- {
- CorpusRef = addedCorpus.Id,
- TextId = "all", //Note that this is not equal to textId necessarily
- EngineRef = engineId,
- Refs = new List { "ref1", "ref2" },
- Translation = "translation"
- };
- await _env.Pretranslations.InsertAsync(pret);
- }
+ CorpusRef = addedCorpus.Id,
+ TextId = "all",
+ EngineRef = ECHO_ENGINE1_ID,
+ Refs = new List { "ref1", "ref2" },
+ Translation = "translation",
+ ModelRevision = 1
+ };
+ await _env.Pretranslations.InsertAsync(pret);
- switch (expectedStatusCode)
+ ICollection results = await client.GetAllPretranslationsAsync(
+ ECHO_ENGINE1_ID,
+ addedCorpus.Id,
+ "all"
+ );
+ Assert.That(results.All(p => p.TextId == "all"), Is.True);
+ }
+
+ [Test]
+ public async Task GetAllPretranslationsAsync_TextIdDoesNotExist()
+ {
+ ITranslationEnginesClient client = _env!.CreateClient();
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(ECHO_ENGINE1_ID, TestCorpusConfig);
+
+ await _env.Engines.UpdateAsync(ECHO_ENGINE1_ID, u => u.Set(e => e.ModelRevision, 1));
+ var pret = new Translation.Models.Pretranslation
{
- case 200:
- 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 = await client.GetAllPretranslations2Async(
- engineId,
- addedCorpus!.Id,
- textId
- );
- Assert.That(results.First().TextId, Is.EqualTo("all"));
- break;
- case 404:
- case 409:
- var ex = Assert.ThrowsAsync(async () =>
- {
- results = await client.GetAllPretranslations2Async(
- engineId,
- addCorpus ? addedCorpus!.Id : "cccccccccccccccccccccccc",
- textId
- );
- });
- Assert.That(ex!.StatusCode, Is.EqualTo(expectedStatusCode));
- break;
- default:
- Assert.Fail("Unanticipated expectedStatusCode. Check test case for typo.");
- break;
- }
+ CorpusRef = addedCorpus.Id,
+ TextId = "all",
+ EngineRef = ECHO_ENGINE1_ID,
+ Refs = new List { "ref1", "ref2" },
+ Translation = "translation",
+ ModelRevision = 1
+ };
+ await _env.Pretranslations.InsertAsync(pret);
+
+ ICollection results = await client.GetAllPretranslationsAsync(
+ ECHO_ENGINE1_ID,
+ addedCorpus.Id,
+ "not_the_right_id"
+ );
+ Assert.That(results, Is.Empty);
}
[Test]
@@ -952,7 +933,7 @@ public async Task StartBuildForEngineByIdAsync(IEnumerable scope, int ex
switch (expectedStatusCode)
{
case 201:
- TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfig!);
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, TestCorpusConfig);
ptcc = new PretranslateCorpusConfig
{
CorpusId = addedCorpus.Id,
@@ -1084,7 +1065,7 @@ public async Task TryToQueueMultipleBuildsPerSingleUser()
ITranslationEnginesClient client = _env!.CreateClient();
var engineId = NMT_ENGINE1_ID;
var expectedStatusCode = 409;
- TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, _testCorpusConfigNonEcho!);
+ TranslationCorpus addedCorpus = await client.AddCorpusAsync(engineId, TestCorpusConfigNonEcho);
var ptcc = new PretranslateCorpusConfig
{
CorpusId = addedCorpus.Id,
@@ -1106,7 +1087,7 @@ public void AddCorpusWithSameSourceAndTargetLangs()
ITranslationEnginesClient client = _env!.CreateClient();
var ex = Assert.ThrowsAsync(async () =>
{
- await client.AddCorpusAsync(NMT_ENGINE1_ID, _testCorpusConfig!);
+ await client.AddCorpusAsync(NMT_ENGINE1_ID, TestCorpusConfig);
});
Assert.That(ex, Is.Not.Null);
Assert.That(ex.StatusCode, Is.EqualTo(422));
@@ -1118,6 +1099,29 @@ public void TearDown()
_env!.Dispose();
}
+ private static AsyncUnaryCall CreateAsyncUnaryCall(StatusCode statusCode)
+ {
+ var status = new Status(statusCode, string.Empty);
+ return new AsyncUnaryCall(
+ Task.FromException(new RpcException(status)),
+ Task.FromResult(new Metadata()),
+ () => status,
+ () => new Metadata(),
+ () => { }
+ );
+ }
+
+ private static AsyncUnaryCall CreateAsyncUnaryCall(TResponse response)
+ {
+ return new AsyncUnaryCall(
+ Task.FromResult(response),
+ Task.FromResult(new Metadata()),
+ () => Status.DefaultSuccess,
+ () => new Metadata(),
+ () => { }
+ );
+ }
+
private class TestEnvironment : DisposableBase
{
private readonly IServiceScope _scope;
@@ -1137,6 +1141,151 @@ public TestEnvironment()
IRepository
>();
Builds = _scope.ServiceProvider.GetRequiredService>();
+
+ EchoClient = Substitute.For();
+ EchoClient
+ .CreateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ EchoClient
+ .DeleteAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ EchoClient
+ .StartBuildAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ EchoClient
+ .CancelBuildAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ var wg = new Translation.V1.WordGraph
+ {
+ SourceTokens = { "This is a test .".Split() },
+ FinalStates = { 4 },
+ Arcs =
+ {
+ new Translation.V1.WordGraphArc
+ {
+ PrevState = 0,
+ NextState = 1,
+ Score = 1.0
+ },
+ new Translation.V1.WordGraphArc
+ {
+ PrevState = 1,
+ NextState = 2,
+ Score = 1.0
+ },
+ new Translation.V1.WordGraphArc
+ {
+ PrevState = 2,
+ NextState = 3,
+ Score = 1.0
+ },
+ new Translation.V1.WordGraphArc
+ {
+ PrevState = 3,
+ NextState = 4,
+ Score = 1.0
+ }
+ }
+ };
+ var wgr = new GetWordGraphResponse { WordGraph = wg };
+ EchoClient
+ .TrainSegmentPairAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ EchoClient
+ .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(wgr));
+
+ var translationResult = new Translation.V1.TranslationResult
+ {
+ Translation = "This is a test .",
+ SourceTokens = { "This is a test .".Split() },
+ TargetTokens = { "This is a test .".Split() },
+ Confidences = { 1.0, 1.0, 1.0, 1.0, 1.0 },
+ Sources =
+ {
+ new TranslationSources
+ {
+ Values =
+ {
+ Translation.V1.TranslationSource.Primary,
+ Translation.V1.TranslationSource.Secondary
+ }
+ },
+ new TranslationSources
+ {
+ Values =
+ {
+ Translation.V1.TranslationSource.Primary,
+ Translation.V1.TranslationSource.Secondary
+ }
+ },
+ new TranslationSources
+ {
+ Values =
+ {
+ Translation.V1.TranslationSource.Primary,
+ Translation.V1.TranslationSource.Secondary
+ }
+ },
+ new TranslationSources
+ {
+ Values =
+ {
+ Translation.V1.TranslationSource.Primary,
+ Translation.V1.TranslationSource.Secondary
+ }
+ },
+ new TranslationSources
+ {
+ Values =
+ {
+ Translation.V1.TranslationSource.Primary,
+ Translation.V1.TranslationSource.Secondary
+ }
+ }
+ },
+ Alignment =
+ {
+ new Translation.V1.AlignedWordPair { SourceIndex = 0, TargetIndex = 0 },
+ new Translation.V1.AlignedWordPair { SourceIndex = 1, TargetIndex = 1 },
+ new Translation.V1.AlignedWordPair { SourceIndex = 2, TargetIndex = 2 },
+ new Translation.V1.AlignedWordPair { SourceIndex = 3, TargetIndex = 3 },
+ new Translation.V1.AlignedWordPair { SourceIndex = 4, TargetIndex = 4 }
+ },
+ Phrases =
+ {
+ new Translation.V1.Phrase
+ {
+ SourceSegmentStart = 0,
+ SourceSegmentEnd = 5,
+ TargetSegmentCut = 5
+ }
+ }
+ };
+ var translateResponse = new TranslateResponse { Results = { translationResult } };
+ EchoClient
+ .TranslateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(translateResponse));
+
+ NmtClient = Substitute.For();
+ NmtClient
+ .CreateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ NmtClient
+ .DeleteAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ NmtClient
+ .StartBuildAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ NmtClient
+ .CancelBuildAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(new Empty()));
+ NmtClient
+ .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Unimplemented));
+ NmtClient
+ .TranslateAsync(Arg.Any(), null, null, Arg.Any())
+ .Returns(CreateAsyncUnaryCall(StatusCode.Unimplemented));
}
ServalWebApplicationFactory Factory { get; }
@@ -1144,6 +1293,8 @@ public TestEnvironment()
public IRepository DataFiles { get; }
public IRepository Pretranslations { get; }
public IRepository Builds { get; }
+ public TranslationEngineApi.TranslationEngineApiClient EchoClient { get; }
+ public TranslationEngineApi.TranslationEngineApiClient NmtClient { get; }
public TranslationEnginesClient CreateClient(IEnumerable? scope = null)
{
@@ -1159,163 +1310,13 @@ public TranslationEnginesClient CreateClient(IEnumerable? scope = null)
{
builder.ConfigureTestServices(services =>
{
- var echoClient = Substitute.For();
- echoClient
- .CreateAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- echoClient
- .DeleteAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- echoClient
- .StartBuildAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- echoClient
- .CancelBuildAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- var wg = new Translation.V1.WordGraph
- {
- SourceTokens = { "This is a test .".Split() },
- FinalStates = { 4 },
- Arcs =
- {
- new Translation.V1.WordGraphArc
- {
- PrevState = 0,
- NextState = 1,
- Score = 1.0
- },
- new Translation.V1.WordGraphArc
- {
- PrevState = 1,
- NextState = 2,
- Score = 1.0
- },
- new Translation.V1.WordGraphArc
- {
- PrevState = 2,
- NextState = 3,
- Score = 1.0
- },
- new Translation.V1.WordGraphArc
- {
- PrevState = 3,
- NextState = 4,
- Score = 1.0
- }
- }
- };
- var wgr = new GetWordGraphResponse { WordGraph = wg };
- echoClient
- .TrainSegmentPairAsync(
- Arg.Any(),
- null,
- null,
- Arg.Any()
- )
- .Returns(CreateAsyncUnaryCall(new Empty()));
- echoClient
- .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(wgr));
-
- var translationResult = new Translation.V1.TranslationResult
- {
- Translation = "This is a test .",
- SourceTokens = { "This is a test .".Split() },
- TargetTokens = { "This is a test .".Split() },
- Confidences = { 1.0, 1.0, 1.0, 1.0, 1.0 },
- Sources =
- {
- new TranslationSources
- {
- Values =
- {
- Translation.V1.TranslationSource.Primary,
- Translation.V1.TranslationSource.Secondary
- }
- },
- new TranslationSources
- {
- Values =
- {
- Translation.V1.TranslationSource.Primary,
- Translation.V1.TranslationSource.Secondary
- }
- },
- new TranslationSources
- {
- Values =
- {
- Translation.V1.TranslationSource.Primary,
- Translation.V1.TranslationSource.Secondary
- }
- },
- new TranslationSources
- {
- Values =
- {
- Translation.V1.TranslationSource.Primary,
- Translation.V1.TranslationSource.Secondary
- }
- },
- new TranslationSources
- {
- Values =
- {
- Translation.V1.TranslationSource.Primary,
- Translation.V1.TranslationSource.Secondary
- }
- }
- },
- Alignment =
- {
- new Translation.V1.AlignedWordPair { SourceIndex = 0, TargetIndex = 0 },
- new Translation.V1.AlignedWordPair { SourceIndex = 1, TargetIndex = 1 },
- new Translation.V1.AlignedWordPair { SourceIndex = 2, TargetIndex = 2 },
- new Translation.V1.AlignedWordPair { SourceIndex = 3, TargetIndex = 3 },
- new Translation.V1.AlignedWordPair { SourceIndex = 4, TargetIndex = 4 }
- },
- Phrases =
- {
- new Translation.V1.Phrase
- {
- SourceSegmentStart = 0,
- SourceSegmentEnd = 5,
- TargetSegmentCut = 5
- }
- }
- };
- var translateResponse = new TranslateResponse { Results = { translationResult } };
- echoClient
- .TranslateAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(translateResponse));
-
- var nmtClient = Substitute.For();
- nmtClient
- .CreateAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- nmtClient
- .DeleteAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- nmtClient
- .StartBuildAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- nmtClient
- .CancelBuildAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new Empty()));
- nmtClient
- .GetWordGraphAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new GetWordGraphResponse(), true));
- nmtClient
- .TranslateAsync(Arg.Any(), null, null, Arg.Any())
- .Returns(CreateAsyncUnaryCall(new TranslateResponse(), true));
-
var grpcClientFactory = Substitute.For();
grpcClientFactory
.CreateClient("Echo")
- .Returns(echoClient);
+ .Returns(EchoClient);
grpcClientFactory
.CreateClient("Nmt")
- .Returns(nmtClient);
+ .Returns(NmtClient);
services.AddSingleton(grpcClientFactory);
});
})
@@ -1330,20 +1331,6 @@ public void ResetDatabases()
_mongoClient.DropDatabase("serval_test_jobs");
}
- private static AsyncUnaryCall CreateAsyncUnaryCall(
- TResponse response,
- bool raisesError = false //Not functional since doesn't seem to pass through middleware
- )
- {
- return new AsyncUnaryCall(
- Task.FromResult(response),
- Task.FromResult(new Metadata()),
- () => raisesError ? new Status(StatusCode.Unimplemented, "") : Status.DefaultSuccess,
- () => new Metadata(),
- () => { }
- );
- }
-
protected override void DisposeManagedResources()
{
_scope.Dispose();