From d2530819fb316770147672a32e8291db4cc80976 Mon Sep 17 00:00:00 2001 From: Caio Saldanha Date: Tue, 26 Sep 2023 10:46:55 -0700 Subject: [PATCH] [FormRecognizer] Cleaning up misc operations live tests (#38807) --- ...cumentClassifierAdministrationLiveTests.cs | 60 +---- .../DocumentModelAdministrationLiveTests.cs | 69 +----- .../MiscellaneousOperationsLiveTests.cs | 230 ++++++++++-------- .../DisposableDocumentClassifier.cs | 15 +- .../Infrastructure/DisposableDocumentModel.cs | 15 +- .../tests/Infrastructure/DocumentAssert.cs | 130 ++++++++++ sdk/formrecognizer/assets.json | 2 +- 7 files changed, 288 insertions(+), 233 deletions(-) create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DocumentAssert.cs diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentClassifierAdministrationLiveTests.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentClassifierAdministrationLiveTests.cs index 7841adccd9e6f..39987a35a35a0 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentClassifierAdministrationLiveTests.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentClassifierAdministrationLiveTests.cs @@ -107,7 +107,7 @@ public async Task BuildDocumentClassifierWithAzureBlobContentSource() Assert.Greater(classifier.CreatedOn, startTime); Assert.Greater(classifier.ExpiresOn, classifier.CreatedOn); - AssertDocumentTypeDictionariesAreEquivalent(documentTypes, classifier.DocumentTypes); + DocumentAssert.AreEquivalent(documentTypes, classifier.DocumentTypes); } [RecordedTest] @@ -152,7 +152,7 @@ public async Task BuildDocumentClassifierWithAzureBlobFileListSource() Assert.Greater(classifier.CreatedOn, startTime); Assert.Greater(classifier.ExpiresOn, classifier.CreatedOn); - AssertDocumentTypeDictionariesAreEquivalent(documentTypes, classifier.DocumentTypes); + DocumentAssert.AreEquivalent(documentTypes, classifier.DocumentTypes); } #endregion Build @@ -172,13 +172,7 @@ public async Task GetDocumentClassifier(bool useTokenCredential) DocumentClassifierDetails expected = disposableClassifier.Value; DocumentClassifierDetails classifier = await client.GetDocumentClassifierAsync(classifierId); - Assert.AreEqual(expected.ClassifierId, classifier.ClassifierId); - Assert.AreEqual(expected.Description, classifier.Description); - Assert.AreEqual(expected.ServiceVersion, classifier.ServiceVersion); - Assert.AreEqual(expected.CreatedOn, classifier.CreatedOn); - Assert.AreEqual(expected.ExpiresOn, classifier.ExpiresOn); - - AssertDocumentTypeDictionariesAreEquivalent(expected.DocumentTypes, classifier.DocumentTypes); + DocumentAssert.AreEqual(expected, classifier); } [RecordedTest] @@ -234,13 +228,7 @@ public async Task GetDocumentClassifiers(bool useTokenCredential) DocumentClassifierDetails classifier = idMapping[id]; DocumentClassifierDetails expected = expectedIdMapping[id]; - Assert.AreEqual(expected.ClassifierId, classifier.ClassifierId); - Assert.AreEqual(expected.Description, classifier.Description); - Assert.AreEqual(expected.ServiceVersion, classifier.ServiceVersion); - Assert.AreEqual(expected.CreatedOn, classifier.CreatedOn); - Assert.AreEqual(expected.ExpiresOn, classifier.ExpiresOn); - - AssertDocumentTypeDictionariesAreEquivalent(expected.DocumentTypes, classifier.DocumentTypes); + DocumentAssert.AreEqual(expected, classifier); } } @@ -274,45 +262,5 @@ public void DeleteDocumentClassifierThrowsWhenClassifierDoesNotExist() } #endregion Delete - - private void AssertDocumentTypeDictionariesAreEquivalent(IReadOnlyDictionary docTypes1, IReadOnlyDictionary docTypes2) - { - Assert.AreEqual(docTypes1.Count, docTypes2.Count); - - foreach (string key in docTypes1.Keys) - { - ClassifierDocumentTypeDetails docType1 = docTypes1[key]; - ClassifierDocumentTypeDetails docType2 = docTypes2[key]; - - Assert.AreEqual(docType1.TrainingDataSource.Kind, docType2.TrainingDataSource.Kind); - - if (docType1.TrainingDataSource.Kind == DocumentContentSourceKind.Blob) - { - var source1 = docType1.TrainingDataSource as BlobContentSource; - var source2 = docType2.TrainingDataSource as BlobContentSource; - - // The URI returned by the service does not include query parameters, so we're - // making sure they're not included in our comparison. - string uri1 = source1.ContainerUri.GetLeftPart(UriPartial.Path); - string uri2 = source2.ContainerUri.GetLeftPart(UriPartial.Path); - - Assert.AreEqual(uri1, uri2); - Assert.AreEqual(source1.Prefix, source2.Prefix); - } - else if (docType1.TrainingDataSource.Kind == DocumentContentSourceKind.BlobFileList) - { - var source1 = docType1.TrainingDataSource as BlobFileListContentSource; - var source2 = docType2.TrainingDataSource as BlobFileListContentSource; - - // The URI returned by the service does not include query parameters, so we're - // making sure they're not included in our comparison. - string uri1 = source1.ContainerUri.GetLeftPart(UriPartial.Path); - string uri2 = source2.ContainerUri.GetLeftPart(UriPartial.Path); - - Assert.AreEqual(uri1, uri2); - Assert.AreEqual(source1.FileList, source2.FileList); - } - } - } } } diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentModelAdministrationLiveTests.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentModelAdministrationLiveTests.cs index 0ea7ff7b56ae6..a01b87298ff19 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentModelAdministrationLiveTests.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/DocumentModelAdministrationLiveTests.cs @@ -287,8 +287,8 @@ public async Task ComposeDocumentModel(bool useTokenCredential) DocumentTypeDetails documentType0 = model.DocumentTypes[componentModel0.ModelId]; DocumentTypeDetails documentType1 = model.DocumentTypes[componentModel1.ModelId]; - AssertDocumentTypesAreEqual(expectedDocumentType0, documentType0); - AssertDocumentTypesAreEqual(expectedDocumentType1, documentType1); + DocumentAssert.AreEqual(expectedDocumentType0, documentType0); + DocumentAssert.AreEqual(expectedDocumentType1, documentType1); } [RecordedTest] @@ -322,15 +322,7 @@ public async Task GetDocumentModel(bool useTokenCredential) DocumentModelDetails expected = disposableModel.Value; DocumentModelDetails model = await client.GetDocumentModelAsync(disposableModel.ModelId); - Assert.AreEqual(expected.ModelId, model.ModelId); - Assert.AreEqual(expected.Description, model.Description); - Assert.AreEqual(expected.ServiceVersion, model.ServiceVersion); - Assert.AreEqual(expected.CreatedOn, model.CreatedOn); - Assert.AreEqual(expected.ExpiresOn, model.ExpiresOn); - - CollectionAssert.AreEquivalent(expected.Tags, model.Tags); - - AssertDocumentTypeDictionariesAreEquivalent(expected.DocumentTypes, model.DocumentTypes); + DocumentAssert.AreEqual(expected, model); } [RecordedTest] @@ -445,60 +437,5 @@ public async Task GetCopyAuthorization() Assert.IsNotEmpty(copyAuthorization.AccessToken); Assert.Greater(copyAuthorization.ExpiresOn, Recording.UtcNow); } - - private void AssertFieldSchemasAreEqual(DocumentFieldSchema fieldSchema1, DocumentFieldSchema fieldSchema2) - { - if (fieldSchema1 == null) - { - Assert.Null(fieldSchema2); - } - else - { - Assert.NotNull(fieldSchema2); - - Assert.AreEqual(fieldSchema1.Type, fieldSchema2.Type); - Assert.AreEqual(fieldSchema1.Description, fieldSchema2.Description); - Assert.AreEqual(fieldSchema1.Example, fieldSchema2.Example); - - AssertFieldSchemasAreEqual(fieldSchema1.Items, fieldSchema2.Items); - AssertFieldSchemaDictionariesAreEquivalent(fieldSchema1.Properties, fieldSchema2.Properties); - } - } - - private void AssertFieldSchemaDictionariesAreEquivalent(IReadOnlyDictionary fieldSchemas1, IReadOnlyDictionary fieldSchemas2) - { - Assert.AreEqual(fieldSchemas1.Count, fieldSchemas2.Count); - - foreach (string key in fieldSchemas1.Keys) - { - DocumentFieldSchema fieldSchema1 = fieldSchemas1[key]; - DocumentFieldSchema fieldSchema2 = fieldSchemas2[key]; - - AssertFieldSchemasAreEqual(fieldSchema1, fieldSchema2); - } - } - - private void AssertDocumentTypesAreEqual(DocumentTypeDetails docType1, DocumentTypeDetails docType2) - { - Assert.AreEqual(docType1.Description, docType2.Description); - Assert.AreEqual(docType1.BuildMode, docType2.BuildMode); - - CollectionAssert.AreEquivalent(docType1.FieldConfidence, docType2.FieldConfidence); - - AssertFieldSchemaDictionariesAreEquivalent(docType1.FieldSchema, docType2.FieldSchema); - } - - private void AssertDocumentTypeDictionariesAreEquivalent(IReadOnlyDictionary docTypes1, IReadOnlyDictionary docTypes2) - { - Assert.AreEqual(docTypes1.Count, docTypes2.Count); - - foreach (string key in docTypes1.Keys) - { - DocumentTypeDetails docType1 = docTypes1[key]; - DocumentTypeDetails docType2 = docTypes2[key]; - - AssertDocumentTypesAreEqual(docType1, docType2); - } - } } } diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/MiscellaneousOperationsLiveTests.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/MiscellaneousOperationsLiveTests.cs index 538aa96693a13..6254f0130f1d1 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/MiscellaneousOperationsLiveTests.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/DocumentModelAdministrationClient/MiscellaneousOperationsLiveTests.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using Azure.Core.TestFramework; using NUnit.Framework; @@ -19,12 +18,6 @@ namespace Azure.AI.FormRecognizer.DocumentAnalysis.Tests /// public class MiscellaneousOperationsLiveTests : DocumentAnalysisLiveTestBase { - private readonly IReadOnlyDictionary _testingTags = new Dictionary() - { - { "ordinary tag", "an ordinary tag" }, - { "crazy tag", "a CRAZY tag 123!@#$%^&*()[]{}\\/?.,<>" } - }; - /// /// Initializes a new instance of the class. /// @@ -34,151 +27,188 @@ public MiscellaneousOperationsLiveTests(bool isAsync, DocumentAnalysisClientOpti { } - [RecordedTest] - public async Task GetResourceDetails() - { - var client = CreateDocumentModelAdministrationClient(); - - ResourceDetails resourceDetails = await client.GetResourceDetailsAsync(); - - Assert.IsNotNull(resourceDetails.CustomDocumentModelCount); - Assert.IsNotNull(resourceDetails.CustomDocumentModelLimit); - } + #region Resource Details [RecordedTest] [TestCase(true)] [TestCase(false)] - [Ignore("https://github.com/Azure/azure-sdk-for-net/issues/38635")] - public async Task GetAndListOperations(bool useTokenCredential) + public async Task GetResourceDetails(bool useTokenCredential) { var client = CreateDocumentModelAdministrationClient(useTokenCredential); + var startTime = Recording.UtcNow; - // Guarantee there is going to be at least one operation - await using var trainedModel = await BuildDisposableDocumentModelAsync(); + // Ensure we will have at least one custom model to populate the resource details. + await using var disposableModel = await BuildDisposableDocumentModelAsync(); - var modelOperationFromList = client.GetOperationsAsync().ToEnumerableAsync().Result; - Assert.GreaterOrEqual(modelOperationFromList.Count, 1); + ResourceDetails resourceDetails = await client.GetResourceDetailsAsync(); - ValidateOperationSummary(modelOperationFromList.FirstOrDefault()); + Assert.Greater(resourceDetails.CustomDocumentModelCount, 0); + Assert.GreaterOrEqual(resourceDetails.CustomDocumentModelLimit, resourceDetails.CustomDocumentModelCount); - OperationDetails operationDetails = await client.GetOperationAsync(modelOperationFromList.FirstOrDefault().OperationId); + ResourceQuotaDetails neuralQuota = resourceDetails.NeuralDocumentModelQuota; - ValidateOperationDetails(operationDetails); + Assert.GreaterOrEqual(neuralQuota.Used, 0); + Assert.GreaterOrEqual(neuralQuota.Quota, neuralQuota.Used); + Assert.Greater(neuralQuota.QuotaResetsOn, startTime); } + #endregion + + #region Get Operation + [RecordedTest] - public async Task GetAndListOperationsWithTags() + public async Task GetOperationCanAuthenticateWithTokenCredential() { var client = CreateDocumentModelAdministrationClient(); - var trainingFilesUri = new Uri(TestEnvironment.BlobContainerSasUrl); - var modelId = Recording.GenerateId(); - var options = new BuildDocumentModelOptions(); + await using var disposableModel = await BuildDisposableDocumentModelAsync(); - foreach (var tag in _testingTags) - { - options.Tags.Add(tag); - } + OperationDetails operationDetails = await client.GetOperationAsync(disposableModel.Operation.Id); - BuildDocumentModelOperation operation = await client.BuildDocumentModelAsync(WaitUntil.Started, trainingFilesUri, DocumentBuildMode.Template, modelId, options: options); + // Sanity check to make sure we got an actual response back from the service. + Assert.AreEqual(disposableModel.Operation.Id, operationDetails.OperationId); + } - OperationSummary operationSummary = client.GetOperationsAsync().ToEnumerableAsync().Result - .FirstOrDefault(op => op.OperationId == operation.Id); + [RecordedTest] + public async Task GetOperationWithDocumentModelBuild() + { + var client = CreateDocumentModelAdministrationClient(); + var startTime = Recording.UtcNow; + var options = new BuildDocumentModelOptions() + { + Description = $"This model was generated by a .NET test.", + Tags = { { "tag1", "value1" }, { "tag2", "value2" } } + }; + await using var disposableModel = await BuildDisposableDocumentModelAsync(options: options); - Assert.NotNull(operationSummary); + OperationDetails operationDetails = await client.GetOperationAsync(disposableModel.Operation.Id); - CollectionAssert.AreEquivalent(_testingTags, operationSummary.Tags); + var resourceLocation = $"{TestEnvironment.Endpoint}formrecognizer/documentModels/{disposableModel.ModelId}?api-version={ServiceVersionString}"; - OperationDetails operationDetails = await client.GetOperationAsync(operation.Id); + ValidateOperationDetails(operationDetails, disposableModel.Operation.Id, + DocumentOperationKind.DocumentModelBuild, resourceLocation, startTime, options.Tags); - CollectionAssert.AreEquivalent(_testingTags, operationDetails.Tags); + var buildOperationDetails = operationDetails as DocumentModelBuildOperationDetails; - await client.DeleteDocumentModelAsync(modelId); + Assert.IsNotNull(buildOperationDetails); + + DocumentAssert.AreEqual(disposableModel.Value, buildOperationDetails.Result); } [RecordedTest] - public void GetOperationWrongId() + [ServiceVersion(Min = DocumentAnalysisClientOptions.ServiceVersion.V2023_07_31)] + public async Task GetOperationWithDocumentClassifierBuild() { var client = CreateDocumentModelAdministrationClient(); + var classifierId = Recording.GenerateId(); + var description = "This model was generated by a .NET test."; + var startTime = Recording.UtcNow; + var tags = new Dictionary(); + await using var disposableClassifier = await BuildDisposableDocumentClassifierAsync(classifierId, description); - RequestFailedException ex = Assert.ThrowsAsync(() => client.GetOperationAsync("0000000000000000")); - Assert.AreEqual("NotFound", ex.ErrorCode); + OperationDetails operationDetails = await client.GetOperationAsync(disposableClassifier.Operation.Id); + + var resourceLocation = $"{TestEnvironment.Endpoint}formrecognizer/documentClassifiers/{disposableClassifier.ClassifierId}?api-version={ServiceVersionString}"; + + ValidateOperationDetails(operationDetails, disposableClassifier.Operation.Id, + DocumentOperationKind.DocumentClassifierBuild, resourceLocation, startTime, tags); + + var buildOperationDetails = operationDetails as DocumentClassifierBuildOperationDetails; + + Assert.IsNotNull(buildOperationDetails); + + DocumentAssert.AreEqual(disposableClassifier.Value, buildOperationDetails.Result); } - private void ValidateOperationSummary(OperationSummary operationSummary) + [RecordedTest] + public void GetOperationCanParseError() { - Assert.NotNull(operationSummary.OperationId); - Assert.AreNotEqual(default(DateTimeOffset), operationSummary.CreatedOn); - Assert.AreNotEqual(default(DateTimeOffset), operationSummary.LastUpdatedOn); - Assert.AreNotEqual(default(DocumentOperationKind), operationSummary.Kind); - Assert.NotNull(operationSummary.ResourceLocation); + var client = CreateDocumentModelAdministrationClient(); + var fakeId = "00000000-0000-0000-0000-000000000000"; - if (operationSummary.Status == DocumentOperationStatus.Succeeded) - { - Assert.AreEqual(100, operationSummary.PercentCompleted); - } + RequestFailedException ex = Assert.ThrowsAsync(() => client.GetOperationAsync(fakeId)); + Assert.AreEqual("NotFound", ex.ErrorCode); } - private void ValidateOperationDetails(OperationDetails operationDetails) + #endregion + + #region List Operations + + [RecordedTest] + [TestCase(true)] + [TestCase(false)] + public async Task GetOperations(bool useTokenCredential) { - Assert.NotNull(operationDetails.OperationId); - Assert.AreNotEqual(default(DateTimeOffset), operationDetails.CreatedOn); - Assert.AreNotEqual(default(DateTimeOffset), operationDetails.LastUpdatedOn); - Assert.AreNotEqual(default(DocumentOperationKind), operationDetails.Kind); - Assert.NotNull(operationDetails.ResourceLocation); + var client = CreateDocumentModelAdministrationClient(useTokenCredential); + var options = new BuildDocumentModelOptions() + { + Description = $"This model was generated by a .NET test.", + Tags = { { "tag1", "value1" }, { "tag2", "value2" } } + }; + + // Make the models slightly different to make sure the cache won't return copies of the same model. + await using var disposableModel0 = await BuildDisposableDocumentModelAsync(ContainerType.Singleforms, options); + await using var disposableModel1 = await BuildDisposableDocumentModelAsync(ContainerType.MultipageFiles, options); + + OperationDetails operationDetails0 = await client.GetOperationAsync(disposableModel0.Operation.Id); + OperationDetails operationDetails1 = await client.GetOperationAsync(disposableModel1.Operation.Id); - if (operationDetails.Status == DocumentOperationStatus.Succeeded) + var idMapping = new Dictionary(); + var expectedIdMapping = new Dictionary() { - Assert.AreEqual(100, operationDetails.PercentCompleted); + { disposableModel0.Operation.Id, operationDetails0 }, + { disposableModel1.Operation.Id, operationDetails1 } + }; - DocumentModelDetails result = operationDetails switch + await foreach (OperationSummary operationSummary in client.GetOperationsAsync()) + { + if (expectedIdMapping.ContainsKey(operationSummary.OperationId)) { - DocumentModelBuildOperationDetails buildOp => buildOp.Result, - DocumentModelCopyToOperationDetails copyToOp => copyToOp.Result, - DocumentModelComposeOperationDetails composeOp => composeOp.Result, - _ => null - }; + idMapping.Add(operationSummary.OperationId, operationSummary); + } - if (result != null) + if (idMapping.Count == expectedIdMapping.Count) { - ValidateDocumentModelDetails(result); + break; } } - else if (operationDetails.Status == DocumentOperationStatus.Failed) - { - Assert.NotNull(operationDetails.Error); - Assert.NotNull(operationDetails.Error.Code); - Assert.NotNull(operationDetails.Error.Message); - } - } - private void ValidateDocumentModelDetails(DocumentModelDetails model, string description = null, IReadOnlyDictionary tags = null) - { - if (description != null) + foreach (string id in expectedIdMapping.Keys) { - Assert.AreEqual(description, model.Description); - } + Assert.True(idMapping.ContainsKey(id)); - if (tags != null) - { - CollectionAssert.AreEquivalent(tags, model.Tags); - } + OperationSummary operationSummary = idMapping[id]; + OperationDetails expected = expectedIdMapping[id]; - Assert.IsNotNull(model.ModelId); - Assert.AreNotEqual(default(DateTimeOffset), model.CreatedOn); + Assert.AreEqual(expected.OperationId, operationSummary.OperationId); + Assert.AreEqual(expected.ServiceVersion, operationSummary.ServiceVersion); + Assert.AreEqual(expected.Status, operationSummary.Status); + Assert.AreEqual(expected.Kind, operationSummary.Kind); + Assert.AreEqual(expected.PercentCompleted, operationSummary.PercentCompleted); + Assert.AreEqual(expected.ResourceLocation.AbsoluteUri, operationSummary.ResourceLocation.AbsoluteUri); + Assert.AreEqual(expected.CreatedOn, operationSummary.CreatedOn); + Assert.AreEqual(expected.LastUpdatedOn, operationSummary.LastUpdatedOn); - if (_serviceVersion >= DocumentAnalysisClientOptions.ServiceVersion.V2023_07_31) - { - if (model.ExpiresOn.HasValue) - { - Assert.Greater(model.ExpiresOn, model.CreatedOn); - } - } - else - { - Assert.Null(model.ExpiresOn); + CollectionAssert.AreEquivalent(expected.Tags, operationSummary.Tags); } + } + + #endregion - // TODO add validation for Doctypes https://github.com/Azure/azure-sdk-for-net-pr/issues/1432 + private void ValidateOperationDetails(OperationDetails operationDetails, string id, DocumentOperationKind kind, string resourceLocation, DateTimeOffset startTime, IDictionary tags) + { + Assert.AreEqual(id, operationDetails.OperationId); + Assert.AreEqual(DocumentOperationStatus.Succeeded, operationDetails.Status); + Assert.AreEqual(kind, operationDetails.Kind); + Assert.AreEqual(100, operationDetails.PercentCompleted); + Assert.AreEqual(resourceLocation, operationDetails.ResourceLocation.AbsoluteUri); + Assert.Null(operationDetails.ServiceVersion); + Assert.Null(operationDetails.Error); + + // Add a 4-hour tolerance because model could have been cached before this test. + Assert.Greater(operationDetails.CreatedOn, startTime - TimeSpan.FromHours(4)); + Assert.Greater(operationDetails.LastUpdatedOn, operationDetails.CreatedOn); + + CollectionAssert.AreEquivalent(tags, operationDetails.Tags); } } } diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentClassifier.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentClassifier.cs index d62ae960a5fd2..198ddf774e62b 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentClassifier.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentClassifier.cs @@ -21,17 +21,22 @@ public class DisposableDocumentClassifier : IAsyncDisposable /// Initializes a new instance of the class. /// /// The client to use for deleting the classifier upon disposal. - /// The classifier to associate with this instance. It will be deleted upon disposal. - private DisposableDocumentClassifier(DocumentModelAdministrationClient client, DocumentClassifierDetails value) + /// The operation that built the classifier this instance is associated with. + private DisposableDocumentClassifier(DocumentModelAdministrationClient client, BuildDocumentClassifierOperation operation) { _client = client; - Value = value; + Operation = operation; } + /// + /// The operation that built the classifier this instance is associated with. + /// + public BuildDocumentClassifierOperation Operation { get; } + /// /// The classifier this instance is associated with. It will be deleted upon disposal. /// - public DocumentClassifierDetails Value { get; } + public DocumentClassifierDetails Value => Operation.Value; /// /// The identifier of the classifier this instance is associated with. @@ -51,7 +56,7 @@ public static async Task BuildAsync(DocumentModelA { BuildDocumentClassifierOperation operation = await client.BuildDocumentClassifierAsync(WaitUntil.Completed, documentTypes, classifierId, description); - return new DisposableDocumentClassifier(client, operation.Value); + return new DisposableDocumentClassifier(client, operation); } /// diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentModel.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentModel.cs index ab4cd92becdb4..47bf59a7bb28d 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentModel.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DisposableDocumentModel.cs @@ -23,19 +23,24 @@ public class DisposableDocumentModel : IAsyncDisposable /// Initializes a new instance of the class. /// /// The client to use for deleting the model. - /// The model to associate with this instance. + /// The operation that built the model this instance is associated with. /// Whether the model should be deleted on disposal. - private DisposableDocumentModel(DocumentModelAdministrationClient client, DocumentModelDetails value, bool deleteOnDisposal) + private DisposableDocumentModel(DocumentModelAdministrationClient client, BuildDocumentModelOperation operation, bool deleteOnDisposal) { _client = client; _deleteOnDisposal = deleteOnDisposal; - Value = value; + Operation = operation; } + /// + /// The operation that built the model this instance is associated with. + /// + public BuildDocumentModelOperation Operation { get; } + /// /// The model this instance is associated with. /// - public DocumentModelDetails Value { get; } + public DocumentModelDetails Value => Operation.Value; /// /// The identifier of the model this instance is associated with. @@ -57,7 +62,7 @@ public static async Task BuildAsync(DocumentModelAdmini { BuildDocumentModelOperation operation = await client.BuildDocumentModelAsync(WaitUntil.Completed, trainingFilesUri, buildMode, modelId, options: options); - return new DisposableDocumentModel(client, operation.Value, deleteOnDisposal); + return new DisposableDocumentModel(client, operation, deleteOnDisposal); } /// diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DocumentAssert.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DocumentAssert.cs new file mode 100644 index 0000000000000..b0880229d2696 --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/DocumentAssert.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace Azure.AI.FormRecognizer.DocumentAnalysis.Tests +{ + internal static class DocumentAssert + { + public static void AreEqual(DocumentClassifierDetails expected, DocumentClassifierDetails actual) + { + Assert.AreEqual(expected.ClassifierId, actual.ClassifierId); + Assert.AreEqual(expected.Description, actual.Description); + Assert.AreEqual(expected.ServiceVersion, actual.ServiceVersion); + Assert.AreEqual(expected.CreatedOn, actual.CreatedOn); + Assert.AreEqual(expected.ExpiresOn, actual.ExpiresOn); + + AreEquivalent(expected.DocumentTypes, actual.DocumentTypes); + } + + public static void AreEqual(DocumentFieldSchema expected, DocumentFieldSchema actual) + { + if (expected == null) + { + Assert.Null(actual); + return; + } + + Assert.NotNull(actual); + + Assert.AreEqual(expected.Type, actual.Type); + Assert.AreEqual(expected.Description, actual.Description); + Assert.AreEqual(expected.Example, actual.Example); + + AreEqual(expected.Items, actual.Items); + AreEquivalent(expected.Properties, actual.Properties); + } + + public static void AreEqual(DocumentModelDetails expected, DocumentModelDetails actual) + { + Assert.AreEqual(expected.ModelId, actual.ModelId); + Assert.AreEqual(expected.Description, actual.Description); + Assert.AreEqual(expected.ServiceVersion, actual.ServiceVersion); + Assert.AreEqual(expected.CreatedOn, actual.CreatedOn); + Assert.AreEqual(expected.ExpiresOn, actual.ExpiresOn); + + CollectionAssert.AreEquivalent(expected.Tags, actual.Tags); + + AreEquivalent(expected.DocumentTypes, actual.DocumentTypes); + } + + public static void AreEqual(DocumentTypeDetails expected, DocumentTypeDetails actual) + { + Assert.AreEqual(expected.Description, actual.Description); + Assert.AreEqual(expected.BuildMode, actual.BuildMode); + + CollectionAssert.AreEquivalent(expected.FieldConfidence, actual.FieldConfidence); + + AreEquivalent(expected.FieldSchema, actual.FieldSchema); + } + + public static void AreEquivalent(IReadOnlyDictionary expected, IReadOnlyDictionary actual) + { + Assert.AreEqual(expected.Count, actual.Count); + + foreach (string key in expected.Keys) + { + ClassifierDocumentTypeDetails docType1 = expected[key]; + ClassifierDocumentTypeDetails docType2 = actual[key]; + + Assert.AreEqual(docType1.TrainingDataSource.Kind, docType2.TrainingDataSource.Kind); + + if (docType1.TrainingDataSource.Kind == DocumentContentSourceKind.Blob) + { + var source1 = docType1.TrainingDataSource as BlobContentSource; + var source2 = docType2.TrainingDataSource as BlobContentSource; + + // The URI returned by the service does not include query parameters, so we're + // making sure they're not included in our comparison. + string uri1 = source1.ContainerUri.GetLeftPart(UriPartial.Path); + string uri2 = source2.ContainerUri.GetLeftPart(UriPartial.Path); + + Assert.AreEqual(uri1, uri2); + Assert.AreEqual(source1.Prefix, source2.Prefix); + } + else if (docType1.TrainingDataSource.Kind == DocumentContentSourceKind.BlobFileList) + { + var source1 = docType1.TrainingDataSource as BlobFileListContentSource; + var source2 = docType2.TrainingDataSource as BlobFileListContentSource; + + // The URI returned by the service does not include query parameters, so we're + // making sure they're not included in our comparison. + string uri1 = source1.ContainerUri.GetLeftPart(UriPartial.Path); + string uri2 = source2.ContainerUri.GetLeftPart(UriPartial.Path); + + Assert.AreEqual(uri1, uri2); + Assert.AreEqual(source1.FileList, source2.FileList); + } + } + } + + public static void AreEquivalent(IReadOnlyDictionary expected, IReadOnlyDictionary actual) + { + Assert.AreEqual(expected.Count, actual.Count); + + foreach (string key in expected.Keys) + { + DocumentFieldSchema fieldSchema1 = expected[key]; + DocumentFieldSchema fieldSchema2 = actual[key]; + + AreEqual(fieldSchema1, fieldSchema2); + } + } + + public static void AreEquivalent(IReadOnlyDictionary expected, IReadOnlyDictionary actual) + { + Assert.AreEqual(expected.Count, actual.Count); + + foreach (string key in expected.Keys) + { + DocumentTypeDetails docType1 = expected[key]; + DocumentTypeDetails docType2 = actual[key]; + + AreEqual(docType1, docType2); + } + } + } +} diff --git a/sdk/formrecognizer/assets.json b/sdk/formrecognizer/assets.json index 55d78fb1de7df..e91bae31ae15a 100644 --- a/sdk/formrecognizer/assets.json +++ b/sdk/formrecognizer/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "net", "TagPrefix": "net/formrecognizer", - "Tag": "net/formrecognizer_3db885206c" + "Tag": "net/formrecognizer_8d3721cae5" }