Microsoft CDM Release Version Update: 1.0

This commit is contained in:
Nenad Banfic 2020-02-28 01:36:20 +00:00
Родитель 3d60a3a0dd
Коммит e1e78e0a9e
5055 изменённых файлов: 1662337 добавлений и 676545 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -17,7 +17,7 @@
</div>
<div class="column">
<a href="SchemaViz.html?"> <img src="advanced.PNG" /></a>
<a href="SchemaViz.html"> <img src="advanced.PNG" /></a>
<div style="font-weight: bold;">ADVANCED NAVIGATOR</div>
</div>
</div>
@ -165,4 +165,4 @@
</body>
</html>
</html>

Просмотреть файл

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
(function () {
/**

Просмотреть файл

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.All</id>
<version>1.0.0</version>
<authors>Microsoft Corporation.</authors>
<owners>Microsoft Corporation.</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<projectUrl>https://commondatamodel.visualstudio.com/CDM</projectUrl>
<description>The ADLS adapter implementation for the Microsoft Common Data Model Object Model.</description>
<copyright>Copyright (c) Microsoft Corporation. All rights reserved.</copyright>
<repository url="https://commondatamodel.visualstudio.com/CDM/_git/CDM.ObjectModel.CSharp" />
<tags>Microsoft Common Data Model</tags>
<dependencies>
<group targetFramework=".NETFramework4.5" />
<group targetFramework=".NETFramework4.6.2" />
<group targetFramework=".NETStandard2.0" />
</dependencies>
</metadata>
<files>
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net45\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\net45\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" target="lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\net462\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" target="lib\net462\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Algorithms.dll" target="lib\net462\System.Security.Cryptography.Algorithms.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Encoding.dll" target="lib\net462\System.Security.Cryptography.Encoding.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Primitives.dll" target="lib\net462\System.Security.Cryptography.Primitives.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.X509Certificates.dll" target="lib\net462\System.Security.Cryptography.X509Certificates.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.deps.json" target="lib\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.deps.json" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
</files>
</package>

Просмотреть файл

@ -2,10 +2,10 @@
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net45;net462</TargetFrameworks>
<Version>0.9.0-preview31</Version>
<Version>1.0.0</Version>
<Authors>Microsoft</Authors>
<Description>The ADLS adapter implementation for the Microsoft Common Data Model Object Model.</Description>
<Copyright>Copyright Microsoft 2018</Copyright>
<Copyright>Copyright Microsoft 2020</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<RepositoryUrl>https://commondatamodel.visualstudio.com/CDM/_git/CDM.ObjectModel.CSharp</RepositoryUrl>
<PackageProjectUrl>https://commondatamodel.visualstudio.com/CDM</PackageProjectUrl>
@ -21,4 +21,5 @@
<ItemGroup>
<ProjectReference Include="..\Microsoft.CommonDataModel.ObjectModel\Microsoft.CommonDataModel.ObjectModel.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>Microsoft.CommonDataModel.ObjectModel.Adapter.Adls</id>
<version>1.0.0</version>
<authors>Microsoft Corporation.</authors>
<owners>Microsoft Corporation.</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<projectUrl>https://commondatamodel.visualstudio.com/CDM</projectUrl>
<description>The ADLS adapter implementation for the Microsoft Common Data Model Object Model.</description>
<copyright>Copyright (c) Microsoft Corporation. All rights reserved.</copyright>
<repository url="https://commondatamodel.visualstudio.com/CDM/_git/CDM.ObjectModel.CSharp" />
<tags>Microsoft Common Data Model</tags>
<dependencies>
<group targetFramework=".NETFramework4.5">
<dependency id="Microsoft.CSharp" version="4.5.0" />
<dependency id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="5.2.4" />
<dependency id="Newtonsoft.Json" version="12.0.2" />
</group>
<group targetFramework=".NETFramework4.6.2">
<dependency id="Microsoft.CSharp" version="4.5.0" />
<dependency id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="5.2.4" />
<dependency id="Newtonsoft.Json" version="12.0.2" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Microsoft.CSharp" version="4.5.0" />
<dependency id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="5.2.4" />
<dependency id="Newtonsoft.Json" version="12.0.2" />
</group>
</dependencies>
</metadata>
<files>
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net45\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\net45\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\net462\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Algorithms.dll" target="lib\net462\System.Security.Cryptography.Algorithms.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Encoding.dll" target="lib\net462\System.Security.Cryptography.Encoding.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.Primitives.dll" target="lib\net462\System.Security.Cryptography.Primitives.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\net462\System.Security.Cryptography.X509Certificates.dll" target="lib\net462\System.Security.Cryptography.X509Certificates.dll" />
<file src="..\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls\bin\Release\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" target="lib\netstandard2.0\Microsoft.CommonDataModel.ObjectModel.Adapter.Adls.dll" />
</files>
</package>

Просмотреть файл

@ -1,8 +1,5 @@
//-----------------------------------------------------------------------
// <copyright file="ADLSAdapter.cs" company="Microsoft">
// All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Storage
{
@ -48,7 +45,20 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// <summary>
/// The hostname of ADLS.
/// </summary>
public string Hostname { get; private set; }
public string Hostname
{
get
{
return this._hostname;
}
private set
{
this._hostname = value;
this.formattedHostname = this.FormatHostname(this._hostname);
}
}
private string _hostname;
/// <summary>
/// The tenant.
@ -73,11 +83,21 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// <inheritdoc />
public string LocationHint { get; set; }
/// <summary>
/// The map from corpus path to adapter path.
/// </summary>
private readonly IDictionary<string, string> adapterPaths = new Dictionary<string, string>();
/// <summary>
/// The file-system name.
/// </summary>
private string fileSystem = "";
/// <summary>
/// The formatted hostname for validation in CreateCorpusPath.
/// </summary>
private string formattedHostname = "";
/// <summary>
/// The sub-path.
/// </summary>
@ -103,6 +123,11 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// </summary>
private const string HttpXmsVersion = "x-ms-version";
/// <summary>
/// The user-defined token provider.
/// </summary>
private TokenProvider tokenProvider;
internal const string Type = "adls";
/// <summary>
@ -110,13 +135,12 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// </summary>
public ADLSAdapter(string hostname, string root, string tenant, string clientId, string secret)
{
this.Root = root;
this.Hostname = hostname;
this.Root = root;
this.Tenant = tenant;
this.ClientId = clientId;
this.Secret = secret;
this.Context = new AuthenticationContext("https://login.windows.net/" + this.Tenant);
this.httpClient = new CdmHttpClient();
}
@ -136,10 +160,19 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
this.Hostname = hostname;
this.Root = root;
this.SharedKey = sharedKey;
this.httpClient = new CdmHttpClient();
}
/// <summary>
/// The ADLS constructor for user-defined token provider.
/// </summary>
public ADLSAdapter(string hostname, string root, TokenProvider tokenProvider)
{
this.Hostname = hostname;
this.Root = root;
this.tokenProvider = tokenProvider;
}
/// <inheritdoc />
public bool CanRead()
{
@ -189,16 +222,43 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// <inheritdoc />
public string CreateAdapterPath(string corpusPath)
{
return $"https://{this.Hostname}{this.Root}{this.FormatCorpusPath(corpusPath)}";
var formattedCorpusPath = this.FormatCorpusPath(corpusPath);
if(adapterPaths.ContainsKey(formattedCorpusPath))
{
return adapterPaths[formattedCorpusPath];
}
else
{
return $"https://{this.Hostname}{this.Root}{formattedCorpusPath}";
}
}
/// <inheritdoc />
public string CreateCorpusPath(string adapterPath)
{
var prefix = $"https://{this.Hostname}{this.Root}";
if (!string.IsNullOrEmpty(adapterPath) && adapterPath.StartsWith(prefix))
if (!string.IsNullOrEmpty(adapterPath))
{
return adapterPath.Substring(prefix.Length);
var startIndex = "https://".Length;
var endIndex = adapterPath.IndexOf("/", startIndex + 1);
if (endIndex < startIndex)
{
throw new Exception($"Unexpected adapter path: {adapterPath}");
}
var hostname = this.FormatHostname(adapterPath.Substring(startIndex, endIndex - startIndex));
if (hostname.Equals(this.formattedHostname) && adapterPath.Substring(endIndex).StartsWith(this.Root))
{
var corpusPath = adapterPath.Substring(endIndex + this.Root.Length);
if (!adapterPaths.ContainsKey(corpusPath))
{
adapterPaths.Add(corpusPath, adapterPath);
}
return corpusPath;
}
}
return null;
@ -213,9 +273,9 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
/// <inheritdoc />
public async Task<DateTimeOffset?> ComputeLastModifiedTimeAsync(string corpusPath)
{
var url = this.CreateAdapterPath(corpusPath);
var adapterPath = this.CreateAdapterPath(corpusPath);
var request = await this.BuildRequest(url, HttpMethod.Head);
var request = await this.BuildRequest(adapterPath, HttpMethod.Head);
try
{
@ -239,7 +299,7 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
public async Task<List<string>> FetchAllFilesAsync(string folderCorpusPath)
{
var url = $"https://{this.Hostname}/{this.fileSystem}";
var directory = $"{this.subPath}{FormatCorpusPath(folderCorpusPath)}";
if (directory.StartsWith("/"))
{
@ -264,9 +324,9 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
{
jObject.TryGetValue("name", StringComparison.OrdinalIgnoreCase, out JToken name);
string nameWithoutSubPath = this.subPath.Length > 0 && name.ToString().StartsWith(this.subPath) ?
string nameWithoutSubPath = this.subPath.Length > 0 && name.ToString().StartsWith(this.subPath) ?
name.ToString().Substring(this.subPath.Length + 1) : name.ToString();
result.Add(this.FormatCorpusPath(nameWithoutSubPath));
}
}
@ -399,7 +459,7 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
if (corpusPath.StartsWith("adls:"))
{
corpusPath = corpusPath.Substring(5);
}
}
else if (corpusPath.Length > 0 && corpusPath[0] != '/')
{
corpusPath = $"/{corpusPath}";
@ -408,6 +468,25 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
return corpusPath;
}
/// <summary>
/// Normalizes the hostname to point to a DFS endpoint, with default port removed.
/// </summary>
/// <param name="corpusPath">The hostname.</param>
/// <returns>The formatted hostname.</returns>
private string FormatHostname(string hostname)
{
hostname = hostname.Replace(".blob.", ".dfs.");
var port = ":443";
if (hostname.Contains(port))
{
hostname = hostname.Substring(0, hostname.Length - port.Length);
}
return hostname;
}
/// <summary>
/// Encodes from base 64 string to the byte array.
/// </summary>
@ -430,6 +509,7 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
private Task<AuthenticationResult> GenerateBearerToken()
{
// In-memory token caching is handled by AuthenticationContext by default.
var clientCredentials = new ClientCredential(this.ClientId, this.Secret);
return this.Context.AcquireTokenAsync(Resource, clientCredentials);
}
@ -451,12 +531,20 @@ namespace Microsoft.CommonDataModel.ObjectModel.Storage
{
request = this.SetUpCdmRequest(url, ApplySharedKey(this.SharedKey, url, method, content, contentType), method);
}
else
else if (this.Context != null)
{
var token = await this.GenerateBearerToken();
request = this.SetUpCdmRequest(url, new Dictionary<string, string> { { "authorization", $"{token.AccessTokenType} {token.AccessToken}" } }, method);
}
else if (this.tokenProvider != null)
{
request = this.SetUpCdmRequest(url, new Dictionary<string, string> { { "authorization", $"{this.tokenProvider.GetToken()}" } }, method);
}
else
{
throw new Exception($"Adls adapter is not configured with any auth method");
}
if (content != null)
{

Просмотреть файл

@ -1,4 +1,7 @@
using NUnit.Framework;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Enums;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -58,7 +61,7 @@
Assert.IsTrue(document.NeedsIndexing);
Assert.AreEqual(folder, document.Owner);
Assert.IsTrue(folder.DocumentLookup.ContainsKey(document.Name));
Assert.IsTrue(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document)));
Assert.IsTrue(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document)));
}
[TestMethod]
@ -169,10 +172,10 @@
var document2 = folder.Documents.Add("DocumentName2");
var document3 = folder.Documents.Add("DocumentName3");
Assert.AreEqual(manifest.Ctx.Corpus.AllDocuments.Count, 3);
Assert.IsTrue(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document)));
Assert.IsTrue(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document2)));
Assert.IsTrue(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document3)));
Assert.AreEqual(manifest.Ctx.Corpus.documentLibrary.ListAllDocuments().Count, 3);
Assert.IsTrue(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document)));
Assert.IsTrue(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document2)));
Assert.IsTrue(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document3)));
Assert.AreEqual(folder.DocumentLookup.Count, 3);
Assert.IsTrue(folder.DocumentLookup.ContainsKey(document.Name));
@ -183,10 +186,10 @@
folder.Documents.Remove("DocumentName");
folder.Documents.Remove(document3);
Assert.AreEqual(manifest.Ctx.Corpus.AllDocuments.Count, 0);
Assert.IsFalse(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document)));
Assert.IsFalse(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document2)));
Assert.IsFalse(manifest.Ctx.Corpus.AllDocuments.Contains(Tuple.Create(folder, document3)));
Assert.AreEqual(manifest.Ctx.Corpus.documentLibrary.ListAllDocuments().Count, 0);
Assert.IsFalse(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document)));
Assert.IsFalse(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document2)));
Assert.IsFalse(manifest.Ctx.Corpus.documentLibrary.Contains(Tuple.Create(folder, document3)));
Assert.AreEqual(folder.DocumentLookup.Count, 0);
Assert.IsFalse(folder.DocumentLookup.ContainsKey(document.Name));
@ -210,7 +213,7 @@
folder.Documents.Clear();
Assert.AreEqual(0, folder.DocumentLookup.Count);
Assert.AreEqual(0, manifest.Ctx.Corpus.AllDocuments.Count);
Assert.AreEqual(0, manifest.Ctx.Corpus.documentLibrary.ListAllDocuments().Count);
Assert.AreEqual(0, folder.Documents.Count);
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;
@ -93,7 +96,7 @@
var callback = new EventCallback();
var functionWasCalled = false;
var functionParameter1 = CdmStatusLevel.Info;
string functionParameter2 = null, functionParameter3 = null;
string functionParameter2 = null;
callback.Invoke = (CdmStatusLevel statusLevel, string message1) =>
{
functionWasCalled = true;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.CdmCollection
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.ResolvedModel;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
{
using System;
using System.Collections.Generic;
@ -60,7 +63,7 @@
var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestResolveEntities");
((CdmCorpusDefinition)cdmCorpus).RootPath = testInputPath;
cdmCorpus.RootPath = testInputPath;
cdmCorpus.Storage.Mount("local", new LocalAdapter(testInputPath));
cdmCorpus.Storage.DefaultNamespace = "local";
var entities = this.GetAllEntities(cdmCorpus);

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Enums;
@ -29,7 +32,7 @@
[TestMethod]
public async Task TestCalculateRelationshipsAndPopulateManifests()
{
var corpus = this.GetCorpus();
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests");
var rootManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("local:/default.manifest.cdm.json");
var subManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(rootManifest.SubManifests[0].Definition);
@ -37,34 +40,12 @@
await corpus.CalculateEntityGraphAsync(rootManifest);
await rootManifest.PopulateManifestRelationshipsAsync();
Assert.AreEqual(5, rootManifest.Relationships.Count);
Assert.AreEqual(7, subManifest.Relationships.Count);
var expectedAllManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests", "expectedAllManifestRels.json")).ToObject<List<E2ERelationship>>();
var expectedAllSubManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests", "expectedAllSubManifestRels.json")).ToObject<List<E2ERelationship>>();
// check that each relationship has been created correctly
foreach (E2ERelationship expectedRel in expectedAllManifestRels)
{
List<CdmE2ERelationship> found = rootManifest.Relationships.AllItems.Where(x =>
x.FromEntity == expectedRel.FromEntity
&& x.FromEntityAttribute == expectedRel.FromEntityAttribute
&& x.ToEntity == expectedRel.ToEntity
&& x.ToEntityAttribute == expectedRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
foreach (E2ERelationship expectedSubRel in expectedAllSubManifestRels)
{
List<CdmE2ERelationship> found = subManifest.Relationships.AllItems.Where(x =>
x.FromEntity == expectedSubRel.FromEntity
&& x.FromEntityAttribute == expectedSubRel.FromEntityAttribute
&& x.ToEntity == expectedSubRel.ToEntity
&& x.ToEntityAttribute == expectedSubRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
VerifyRelationships(rootManifest, expectedAllManifestRels);
VerifyRelationships(subManifest, expectedAllSubManifestRels);
}
/// <summary>
@ -74,7 +55,7 @@
[TestMethod]
public async Task TestCalculateRelationshipsAndPopulateManifestsWithExclusiveFlag()
{
var corpus = this.GetCorpus();
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests");
var rootManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("local:/default.manifest.cdm.json");
var subManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(rootManifest.SubManifests[0].Definition);
@ -83,34 +64,12 @@
// make sure only relationships where to and from entities are in the manifest are found with the "exclusive" option is passed in
await rootManifest.PopulateManifestRelationshipsAsync(CdmRelationshipDiscoveryStyle.Exclusive);
Assert.AreEqual(3, rootManifest.Relationships.Count);
Assert.AreEqual(3, subManifest.Relationships.Count);
var expectedExclusiveManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests", "expectedExclusiveManifestRels.json")).ToObject<List<E2ERelationship>>();
var expectedExclusiveSubManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests", "expectedExclusiveSubManifestRels.json")).ToObject<List<E2ERelationship>>();
// check that each relationship has been created correctly
foreach (E2ERelationship expectedRel in expectedExclusiveManifestRels)
{
List<CdmE2ERelationship> found = rootManifest.Relationships.AllItems.Where(x =>
x.FromEntity == expectedRel.FromEntity
&& x.FromEntityAttribute == expectedRel.FromEntityAttribute
&& x.ToEntity == expectedRel.ToEntity
&& x.ToEntityAttribute == expectedRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
foreach (E2ERelationship expectedSubRel in expectedExclusiveSubManifestRels)
{
List<CdmE2ERelationship> found = subManifest.Relationships.AllItems.Where(x =>
x.FromEntity == expectedSubRel.FromEntity
&& x.FromEntityAttribute == expectedSubRel.FromEntityAttribute
&& x.ToEntity == expectedSubRel.ToEntity
&& x.ToEntityAttribute == expectedSubRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
VerifyRelationships(rootManifest, expectedExclusiveManifestRels);
VerifyRelationships(subManifest, expectedExclusiveSubManifestRels);
}
/// <summary>
@ -120,7 +79,7 @@
[TestMethod]
public async Task TestCalculateRelationshipsAndPopulateManifestsWithNoneFlag()
{
var corpus = this.GetCorpus();
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests", null);
var rootManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("local:/default.manifest.cdm.json");
var subManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(rootManifest.SubManifests[0].Definition);
@ -142,6 +101,8 @@
{
var expectedResolvedManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsOnResolvedEntities", "expectedResolvedManifestRels.json")).ToObject<List<E2ERelationship>>();
var expectedResolvedSubManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsOnResolvedEntities", "expectedResolvedSubManifestRels.json")).ToObject<List<E2ERelationship>>();
var expectedResolvedExcManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsOnResolvedEntities", "expectedResolvedExcManifestRels.json")).ToObject<List<E2ERelationship>>();
var expectedResolvedExcSubManifestRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsOnResolvedEntities", "expectedResolvedExcSubManifestRels.json")).ToObject<List<E2ERelationship>>();
CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestCalculateRelationshipsOnResolvedEntities");
@ -152,31 +113,14 @@
CdmManifestDefinition subManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(subManifestPath) as CdmManifestDefinition;
// using createResolvedManifest will only populate exclusive relationships
Assert.AreEqual(expectedResolvedManifestRels.Count, resolvedManifest.Relationships.Count);
Assert.AreEqual(expectedResolvedSubManifestRels.Count, subManifest.Relationships.Count);
VerifyRelationships(resolvedManifest, expectedResolvedExcManifestRels);
VerifyRelationships(subManifest, expectedResolvedExcSubManifestRels);
// check that each relationship has been created correctly
foreach (E2ERelationship expectedRel in expectedResolvedManifestRels)
{
List<CdmE2ERelationship> found = resolvedManifest.Relationships.Where(x =>
x.FromEntity == expectedRel.FromEntity
&& x.FromEntityAttribute == expectedRel.FromEntityAttribute
&& x.ToEntity == expectedRel.ToEntity
&& x.ToEntityAttribute == expectedRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
foreach (E2ERelationship expectedSubRel in expectedResolvedSubManifestRels)
{
List<CdmE2ERelationship> found = subManifest.Relationships.Where(x =>
x.FromEntity == expectedSubRel.FromEntity
&& x.FromEntityAttribute == expectedSubRel.FromEntityAttribute
&& x.ToEntity == expectedSubRel.ToEntity
&& x.ToEntityAttribute == expectedSubRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
// check that each relationship has been created correctly with the all flag
await resolvedManifest.PopulateManifestRelationshipsAsync();
await subManifest.PopulateManifestRelationshipsAsync();
VerifyRelationships(resolvedManifest, expectedResolvedManifestRels);
VerifyRelationships(subManifest, expectedResolvedSubManifestRels);
// it is not enough to check if the relationships are correct.
// We need to check if the incoming and outgoing relationships are
@ -195,9 +139,11 @@
var bEnt = await corpus.FetchObjectAsync<CdmEntityDefinition>(resolvedManifest.Entities[1].EntityPath, resolvedManifest);
var bInRels = corpus.FetchIncomingRelationships(bEnt);
var bOutRels = corpus.FetchOutgoingRelationships(bEnt);
Assert.AreEqual(1, bInRels.Count);
Assert.AreEqual(2, bInRels.Count);
Assert.AreEqual("local:/A-resolved.cdm.json/A", bInRels[0].FromEntity);
Assert.AreEqual("local:/B-resolved.cdm.json/B", bInRels[0].ToEntity);
Assert.AreEqual("local:/sub/C-resolved.cdm.json/C", bInRels[1].FromEntity);
Assert.AreEqual("local:/B-resolved.cdm.json/B", bInRels[1].ToEntity);
Assert.AreEqual(0, bOutRels.Count);
// C
@ -207,8 +153,7 @@
Assert.AreEqual(0, cInRels.Count);
Assert.AreEqual(2, cOutRels.Count);
Assert.AreEqual("local:/sub/C-resolved.cdm.json/C", cOutRels[0].FromEntity);
// TODO: this should point to the resolved entity, currently an open bug
Assert.AreEqual("local:/B.cdm.json/B", cOutRels[0].ToEntity);
Assert.AreEqual("local:/B-resolved.cdm.json/B", cOutRels[0].ToEntity);
Assert.AreEqual("local:/sub/C-resolved.cdm.json/C", cOutRels[1].FromEntity);
Assert.AreEqual("local:/sub/D-resolved.cdm.json/D", cOutRels[1].ToEntity);
@ -220,20 +165,59 @@
Assert.AreEqual("local:/sub/C-resolved.cdm.json/C", dInRels[0].FromEntity);
Assert.AreEqual("local:/sub/D-resolved.cdm.json/D", dInRels[0].ToEntity);
Assert.AreEqual(0, dOutRels.Count);
// E
var eEnt = await corpus.FetchObjectAsync<CdmEntityDefinition>(resolvedManifest.Entities[2].EntityPath, resolvedManifest);
var eInRels = corpus.FetchIncomingRelationships(eEnt);
var eOutRels = corpus.FetchOutgoingRelationships(eEnt);
Assert.AreEqual(1, eInRels.Count);
Assert.AreEqual(0, eOutRels.Count);
Assert.AreEqual("local:/sub/F-resolved.cdm.json/F", eInRels[0].FromEntity);
Assert.AreEqual("local:/E-resolved.cdm.json/E", eInRels[0].ToEntity);
// F
var fEnt = await corpus.FetchObjectAsync<CdmEntityDefinition>(subManifest.Entities[2].EntityPath, subManifest);
var fInRels = corpus.FetchIncomingRelationships(fEnt);
var fOutRels = corpus.FetchOutgoingRelationships(fEnt);
Assert.AreEqual(0, fInRels.Count);
Assert.AreEqual(1, fOutRels.Count);
Assert.AreEqual("local:/sub/F-resolved.cdm.json/F", fOutRels[0].FromEntity);
Assert.AreEqual("local:/E-resolved.cdm.json/E", fOutRels[0].ToEntity);
}
private CdmCorpusDefinition GetCorpus()
/// <summary>
/// Testing calculating relationships for the special kind of attribute that uses the "select one" directive
/// </summary>
[TestMethod]
public async Task TestCalculateRelationshipsForSelectsOneAttribute()
{
var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestCalculateRelationshipsAndPopulateManifests");
CdmCorpusDefinition corpus = new CdmCorpusDefinition();
corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
corpus.Storage.Mount("local", new LocalAdapter(testInputPath));
var expectedRels = JToken.Parse(TestHelper.GetExpectedOutputFileContent(testsSubpath, "TestCalculateRelationshipsForSelectsOneAttribute", "expectedRels.json")).ToObject<List<E2ERelationship>>();
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestCalculateRelationshipsForSelectsOneAttribute");
corpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
corpus.Storage.DefaultNamespace = "local";
var manifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("local:/selectsOne.manifest.cdm.json");
return corpus;
await corpus.CalculateEntityGraphAsync(manifest);
await manifest.PopulateManifestRelationshipsAsync();
// check that each relationship has been created correctly
VerifyRelationships(manifest, expectedRels);
}
private static void VerifyRelationships(CdmManifestDefinition manifest, List<E2ERelationship> expectedRelationships)
{
Assert.AreEqual(manifest.Relationships.Count, expectedRelationships.Count);
foreach (E2ERelationship expectedRel in expectedRelationships)
{
List<CdmE2ERelationship> found = manifest.Relationships.Where(x =>
x.FromEntity == expectedRel.FromEntity
&& x.FromEntityAttribute == expectedRel.FromEntityAttribute
&& x.ToEntity == expectedRel.ToEntity
&& x.ToEntityAttribute == expectedRel.ToEntityAttribute
).ToList();
Assert.AreEqual(1, found.Count);
}
}
private async static Task<CdmManifestDefinition> LoadAndResolveManifest(CdmCorpusDefinition corpus, CdmManifestDefinition manifest, string renameSuffix)

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
{
using System;
using System.Collections.Generic;
@ -10,7 +13,6 @@
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
/// <summary>
/// Tests to verify if entity resolution is taking places as expected.
@ -28,11 +30,6 @@
/// </summary>
private string testsSubpath = Path.Combine("Cdm", "Resolution", "EntityResolution");
/// <summary>
/// Whether debugging files should be written or not.
/// </summary>
private const bool doesWriteDebuggingFiles = TestHelper.DoesWriteTestDebuggingFiles;
/// <summary>
/// Test whether or not the test corpus can be resolved
/// The input of this test is a manifest from SchemaDocs, so this test does not need any individual input files.
@ -102,9 +99,9 @@
/// Test if the POVResolution resolved entities match
/// </summary>
[TestMethod]
public async Task TestResolvedPov()
public async Task TestResolvedPovResolution()
{
await this.ResolveSaveDebuggingFileAndAssert("TestResolvedPov", "POVResolution");
await this.ResolveSaveDebuggingFileAndAssert("TestResolvedPOVResolution", "POVResolution");
}
/// <summary>
@ -116,11 +113,120 @@
await this.ResolveSaveDebuggingFileAndAssert("TestResolvedWebClicks", "webClicks");
}
/// <summary>
/// Test that monikered references on resolved entities can be resolved correctly, previously
/// the inclusion of the resolvedFrom moniker stopped the source document from being found
/// </summary>
[TestMethod]
public async Task TestResolveWithExtended()
{
CdmCorpusDefinition cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestResolveWithExtended");
cdmCorpus.SetEventCallback(new EventCallback { Invoke = (CdmStatusLevel statusLevel, string message) =>
{
if (message.Contains("unable to resolve the reference"))
Assert.Fail();
}
}, CdmStatusLevel.Warning);
CdmEntityDefinition ent = await cdmCorpus.FetchObjectAsync<CdmEntityDefinition>("local:/sub/Account.cdm.json/Account");
await ent.CreateResolvedEntityAsync("Account_");
}
/// <summary>
/// Test that attributes with the same name are merged on resolve and that
/// traits are merged and attribute contexts are mapped correctly
/// </summary>
[TestMethod]
public async Task TestAttributesThatAreReplaced()
{
CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestAttributesThatAreReplaced");
corpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
CdmEntityDefinition extendedEntity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/extended.cdm.json/extended");
CdmEntityDefinition resExtendedEnt = await extendedEntity.CreateResolvedEntityAsync("resExtended");
// the attribute from the base class should be merged with the attribute
// from the extended class into a single attribute
Assert.AreEqual(1, resExtendedEnt.Attributes.Count);
// check that traits from the base class merged with the traits from the extended class
CdmAttributeItem attribute = resExtendedEnt.Attributes[0];
// base trait
Assert.AreNotEqual(-1, attribute.AppliedTraits.IndexOf("means.identity.brand"));
// extended trait
Assert.AreNotEqual(-1, attribute.AppliedTraits.IndexOf("means.identity.company.name"));
// make sure the attribute context and entity foreign key were maintained correctly
CdmAttributeContext foreignKeyForBaseAttribute = ((resExtendedEnt.AttributeContext.Contents[1] as CdmAttributeContext).Contents[1] as CdmAttributeContext);
Assert.AreEqual(foreignKeyForBaseAttribute.Name, "_generatedAttributeSet");
CdmAttributeReference fkReference = ((foreignKeyForBaseAttribute.Contents[0] as CdmAttributeContext).Contents[0] as CdmAttributeContext).Contents[0] as CdmAttributeReference;
Assert.AreEqual("resExtended/hasAttributes/regardingObjectId", fkReference.NamedReference);
}
/// <summary>
/// Test that resolved attribute limit is calculated correctly and respected
/// </summary>
[TestMethod]
public async Task TestResolvedAttributeLimit()
{
CdmCorpusDefinition corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestResolvedAttributeLimit");
CdmEntityDefinition mainEntity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/mainEntity.cdm.json/mainEntity");
ResolveOptions resOpt = new ResolveOptions { WrtDoc = mainEntity.InDocument, Directives = new AttributeResolutionDirectiveSet(new HashSet<string> { "normalized", "referenceOnly" }) };
// if attribute limit is reached, entity should be null
resOpt.ResolvedAttributeLimit = 4;
var resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_zeroAtts", resOpt);
Assert.IsNull(resEnt);
// when the attribute limit is set to null, there should not be a limit on the possible number of attributes
resOpt.ResolvedAttributeLimit = null;
resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet<string> { "normalized", "referenceOnly" });
var ras = mainEntity.FetchResolvedAttributes(resOpt);
resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_referenceOnly", resOpt);
// there are 5 total attributes
Assert.AreEqual(ras.ResolvedAttributeCount, 5);
Assert.AreEqual(ras.Set.Count, 5);
Assert.AreEqual(mainEntity.Attributes.Count, 3);
// there are 2 attributes grouped in an entity attribute
// and 2 attributes grouped in an attribute group
Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);
// using the default limit number
resOpt = new ResolveOptions { WrtDoc = mainEntity.InDocument, Directives = new AttributeResolutionDirectiveSet(new HashSet<string> { "normalized", "referenceOnly" }) };
ras = mainEntity.FetchResolvedAttributes(resOpt);
resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_referenceOnly", resOpt);
// there are 5 total attributes
Assert.AreEqual(ras.ResolvedAttributeCount, 5);
Assert.AreEqual(ras.Set.Count, 5);
Assert.AreEqual(mainEntity.Attributes.Count, 3);
// there are 2 attributes grouped in an entity attribute
// and 2 attributes grouped in an attribute group
Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);
resOpt.Directives = new AttributeResolutionDirectiveSet(new HashSet<string> { "normalized", "structured" });
ras = mainEntity.FetchResolvedAttributes(resOpt);
resEnt = await mainEntity.CreateResolvedEntityAsync($"{mainEntity.EntityName}_normalized_structured", resOpt);
// there are 5 total attributes
Assert.AreEqual(ras.ResolvedAttributeCount, 5);
// the attribute count is different because one attribute is a group that contains two different attributes
Assert.AreEqual(ras.Set.Count, 4);
Assert.AreEqual(mainEntity.Attributes.Count, 3);
// again there are 2 attributes grouped in an entity attribute
// and 2 attributes grouped in an attribute group
Assert.AreEqual(((mainEntity.Attributes[2] as CdmAttributeGroupReference).ExplicitReference as CdmAttributeGroupDefinition).Members.Count, 2);
}
/// <summary>
/// Creates a storage adapter used to retrieve input files associated with test.
/// </summary>
/// <param name="testName">The name of the test we should retrieve input files for.</param>
/// <returns>The storage adapter to be used by the named test method.</returns>
/// <param name="testName">The name of the test we should retrieve input files for. </param>
/// <returns>The storage adapter to be used by the named test method. </returns>
private StorageAdapter CreateStorageAdapterConfigForTest(string testName)
{
return new LocalAdapter(TestHelper.GetInputFolderPath(this.testsSubpath, testName));
@ -131,10 +237,11 @@
/// Writes a helper function used for debugging.
/// Asserts the result matches the expected result stored in a file.
/// </summary>
/// <param name="testName">The name of the test. It is used to decide the path of input / output files.</param>
/// <parameter name="manifestName">The name of the manifest to be used.</parameter>
/// <returns>Task associated with this function.</returns>
private async Task ResolveSaveDebuggingFileAndAssert(string testName, string manifestName)
/// <param name="testName">The name of the test. It is used to decide the path of input / output files. </param>
/// <parameter name="manifestName">The name of the manifest to be used. </parameter>
/// <parameter name="doesWriteDebuggingFiles">Whether debugging files should be written or not. </parameter>
/// <returns>Task associated with this function. </returns>
private async Task ResolveSaveDebuggingFileAndAssert(string testName, string manifestName, bool doesWriteDebuggingFiles = false)
{
Assert.IsNotNull(testName);
var result = (await this.ResolveEnvironment(testName, manifestName));
@ -152,12 +259,11 @@
/// <summary>
/// Resolve the entities in the given manifest.
/// </summary>
/// <param name="testName">The name of the test. It is used to decide the path of input / output files.</param>
/// <parameter name="manifestName">The name of the manifest to be used.</parameter>
/// <param name="testName">The name of the test. It is used to decide the path of input / output files. </param>
/// <parameter name="manifestName">The name of the manifest to be used. </parameter>
/// <returns> The resolved entities. </returns>
private async Task<string> ResolveEnvironment(string testName, string manifestName)
{
var cdmCorpus = new CdmCorpusDefinition();
cdmCorpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
var testLocalAdapter = this.CreateStorageAdapterConfigForTest(testName);
@ -174,7 +280,7 @@
/// <param name="cdmCorpus"> The CDM corpus. </param>
/// <param name="directives"> The directives to use while getting the resolved entities. </param>
/// <param name="manifest"> The manifest to be resolved. </param>
/// <param name="spew"> The object used to store the text to be returned.</param>
/// <param name="spew"> The object used to store the text to be returned. </param>
/// <returns> The text version of the resolved entities. (it's in a form that facilitates debugging) </returns>
internal static async Task<string> ListAllResolved(CdmCorpusDefinition cdmCorpus, AttributeResolutionDirectiveSet directives, CdmManifestDefinition manifest, StringSpewCatcher spew = null)
{

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Resolution
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Resolution
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;
@ -24,7 +27,7 @@
private static readonly string TestsSubpath = Path.Combine("Cdm", "ResolutionGuidance");
[TestMethod]
public async Task TestResolutionGuidanceCopy()
public void TestResolutionGuidanceCopy()
{
var corpus = new CdmCorpusDefinition();
var resolutionGuidance = new CdmAttributeResolutionGuidance(corpus.Ctx)

Просмотреть файл

@ -1,19 +1,19 @@
//-----------------------------------------------------------------------
// <copyright file="CommonDataLoader.cs" company="Microsoft">
// All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Runtime.CompilerServices;
#if INTERNAL_VSTS
[assembly: InternalsVisibleTo("Microsoft.CommonDataModel.ObjectModel.Persistence.Odi.Tests" + Microsoft.CommonDataModel.AssemblyRef.TestPublicKey)]
#else
[assembly: InternalsVisibleTo("Microsoft.CommonDataModel.ObjectModel.Persistence.Odi.Tests")]
#endif
namespace Microsoft.CommonDataModel.Tools.Processor
{
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CommonDataModel.ObjectModel.Cdm;
@ -23,6 +23,7 @@ namespace Microsoft.CommonDataModel.Tools.Processor
using Newtonsoft.Json.Serialization;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types;
using Microsoft.CommonDataModel.ObjectModel.Persistence;
class CommonDataModelLoader
{
@ -60,7 +61,7 @@ namespace Microsoft.CommonDataModel.Tools.Processor
{
return;
}
string endMatch = (!string.IsNullOrEmpty(version)) ? $".{version}.cdm.json" : ".cdm.json";
string endMatch = (!string.IsNullOrEmpty(version)) ? $".{version}{PersistenceLayer.CdmExtension}" : PersistenceLayer.CdmExtension;
if (!Directory.Exists(path))
{
@ -109,11 +110,11 @@ namespace Microsoft.CommonDataModel.Tools.Processor
{
Console.WriteLine("resolving imports");
for (int i = 0; i < ((CdmCorpusDefinition)cdmCorpus).AllDocuments.Count; i++)
List<CdmDocumentDefinition> AllDocuments = ((CdmCorpusDefinition)cdmCorpus).documentLibrary.ListAllDocuments();
for (int i = 0; i < AllDocuments.Count; i++)
{
Tuple<CdmFolderDefinition, CdmDocumentDefinition> tuple = ((CdmCorpusDefinition)cdmCorpus).AllDocuments[i];
ResolveOptions resOpt = new ResolveOptions() { WrtDoc = tuple.Item2, Directives = directives };
await tuple.Item2.RefreshAsync(resOpt);
ResolveOptions resOpt = new ResolveOptions() { WrtDoc = AllDocuments[i], Directives = directives };
await AllDocuments[i].RefreshAsync(resOpt);
}
return true;
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -24,7 +27,7 @@
/// Test load legacy entity declaration.
/// </summary>
[TestMethod]
public async Task TestLoadLegacyEntityDeclaration()
public void TestLoadLegacyEntityDeclaration()
{
var content = TestHelper.GetInputFileContent(testsSubpath, "TestLoadLegacyEntityDeclaration", "entities.manifest.cdm.json");
var cdmManifest = ManifestPersistence.FromObject(new ResolveContext(new CdmCorpusDefinition(), null), "", "", "", JsonConvert.DeserializeObject<ManifestContent>(content));
@ -35,4 +38,4 @@
Assert.AreEqual("Account.cdm.json/Account", cdmManifest.Entities[1].EntityPath);
}
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -88,4 +91,4 @@
Assert.AreEqual(absolutePartitionData.Value<string>("location"), absolutePartition.Location);
}
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -70,4 +73,4 @@
Assert.IsNotNull(cdmManifest.Entities[0].DataPartitionPatterns[0].LastFileStatusCheckTime);
}
}
}
}

Просмотреть файл

@ -1,8 +1,12 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder;
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
@ -14,6 +18,7 @@
/// The path between TestDataPath and TestName.
/// </summary>
private readonly string testsSubpath = Path.Combine("Persistence", "CdmFolder", "Entity");
/// <summary>
/// Testing that traits with multiple properties are maintained
/// even when one of the properties is null
@ -42,5 +47,77 @@
Assert.IsNull(att.MaximumLength);
Assert.IsNull(result);
}
/// <summary>
/// Testing special case where "this.attributes" attributes do not inherit the InDocument field because these attributes
/// are created during resolution (no inDocument propagation during resolution). This error appears when running copyData
/// with stringRefs = true in certain cases
/// </summary>
[TestMethod]
public async Task TestFromAndToDataWithElevatedTraits()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestFromAndToDataWithElevatedTraits", null);
// need to set schema docs to the cdm namespace instead of using resources
corpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
corpus.SetEventCallback(new EventCallback
{
Invoke = (CdmStatusLevel statusLevel, string message) =>
{
if (message.Contains("unable to resolve an entity"))
Assert.Fail();
}
}, CdmStatusLevel.Warning);
var entity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/Account.cdm.json/Account");
var resEntity = await entity.CreateResolvedEntityAsync($"{entity.EntityName}_");
EntityPersistence.ToData(resEntity, new ResolveOptions(resEntity.InDocument), new CopyOptions() { StringRefs = true });
}
/// <summary>
/// Testing that loading entities with missing references logs warnings when the resolve option ShallowValidation = true.
/// </summary>
[TestMethod]
public async Task TestLoadingEntityWithShallowValidation()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingEntityWithShallowValidation", null);
corpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
corpus.SetEventCallback(new EventCallback
{
Invoke = (CdmStatusLevel statusLevel, string message) =>
{
// When messages regarding references not being resolved or loaded are logged, check that they are warnings and not errors.
if (message.Contains("Unable to resolve the reference") || message.Contains("Could not read"))
Assert.AreEqual(CdmStatusLevel.Warning, statusLevel);
}
}, CdmStatusLevel.Warning);
// Load entity with ShallowValidation = true.
await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/Entity.cdm.json/Entity", null, true);
// Load resolved entity with ShallowValidation = true.
await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/ResolvedEntity.cdm.json/ResolvedEntity", null, true);
}
/// <summary>
/// Testing that loading entities with missing references logs errors when the resolve option ShallowValidation = false.
/// </summary>
[TestMethod]
public async Task TestLoadingEntityWithoutShallowValidation()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingEntityWithShallowValidation", null);
corpus.Storage.Mount("cdm", new LocalAdapter(TestHelper.SchemaDocumentsPath));
corpus.SetEventCallback(new EventCallback
{
Invoke = (CdmStatusLevel statusLevel, string message) =>
{
// When messages regarding references not being resolved or loaded are logged, check that they are errors.
if (message.Contains("Unable to resolve the reference") || message.Contains("Could not read"))
Assert.AreEqual(CdmStatusLevel.Error, statusLevel);
}
}, CdmStatusLevel.Warning);
// Load entity with ShallowValidation = false.
await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/Entity.cdm.json/Entity");
// Load resolved entity with ShallowValidation = false.
await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/ResolvedEntity.cdm.json/ResolvedEntity");
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -35,4 +38,4 @@
Assert.AreEqual(subManifest.Definition, "test definition");
}
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -25,7 +28,7 @@
/// Creates Manifest using empty string as namespace.
/// </summary>
[TestMethod]
public async Task TestLoadLocalEntityNoPartition()
public void TestLoadLocalEntityNoPartition()
{
var content = TestHelper.GetInputFileContent(testsSubpath, "TestLoadLocalEntityNoPartition", "entities.manifest.cdm.json");
var cdmManifest = ManifestPersistence.FromObject(new ResolveContext(new CdmCorpusDefinition(), null), "", "", "", JsonConvert.DeserializeObject<ManifestContent>(content));
@ -46,7 +49,7 @@
/// </summary>
/// <returns></returns>
[TestMethod]
public async Task TestLoadLocalEntityNoPartitionNamespaceSet()
public void TestLoadLocalEntityNoPartitionNamespaceSet()
{
var content = TestHelper.GetInputFileContent(testsSubpath, "TestLoadLocalEntityNoPartitionNamespaceSet", "entities.manifest.cdm.json");
ManifestContent manifestContent = JsonConvert.DeserializeObject<ManifestContent>(content);
@ -71,7 +74,7 @@
/// </summary>
/// <returns></returns>
[TestMethod]
public async Task TestLoadLocalEntityNoPartitionAbsoluteNamespaceSet()
public void TestLoadLocalEntityNoPartitionAbsoluteNamespaceSet()
{
var content = TestHelper.GetInputFileContent(testsSubpath, "TestLoadLocalEntityNoPartitionAbsoluteNamespaceSet", "entitiesWithNamespace.manifest.cdm.json");
ManifestContent manifestContent = JsonConvert.DeserializeObject<ManifestContent>(content);
@ -90,4 +93,4 @@
Assert.AreEqual("testNamespace:/Account.cdm.json/Account", manifestToData.Entities[0].Value<string>("entityPath"));
}
}
}
}

Просмотреть файл

@ -1,3 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System;
@ -34,9 +37,9 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
var cdmManifest = ManifestPersistence.FromObject(new ResolveContext(new CdmCorpusDefinition(), null), "cdmTest", "someNamespace", "/", JsonConvert.DeserializeObject<ManifestContent>(content));
Assert.AreEqual(cdmManifest.Schema, "CdmManifestDefinition.cdm.json");
Assert.AreEqual(cdmManifest.ManifestName, "cdmTest");
Assert.AreEqual(cdmManifest.JsonSchemaSemanticVersion, "0.9.0");
Assert.AreEqual(cdmManifest.JsonSchemaSemanticVersion, "1.0.0");
Assert.AreEqual(TimeUtils.GetFormattedDateString((DateTimeOffset)cdmManifest.LastFileModifiedTime), "2008-09-15T23:53:23.000Z");
Assert.AreEqual(cdmManifest.Explanation, "test cdm folder for cdm version 0.9+");
Assert.AreEqual(cdmManifest.Explanation, "test cdm folder for cdm version 1.0+");
Assert.AreEqual(cdmManifest.Imports.Count, 1);
Assert.AreEqual(cdmManifest.Imports[0].CorpusPath, "/primitives.cdm.json");
Assert.AreEqual(cdmManifest.Entities.Count, 0);
@ -92,9 +95,9 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
var cdmManifest = ManifestPersistence.FromObject(new ResolveContext(new CdmCorpusDefinition(), null), "docName", "someNamespace", "/", JsonConvert.DeserializeObject<ManifestContent>(content));
ManifestContent manifestObject = CdmObjectBase.CopyData(cdmManifest, null, null);
Assert.AreEqual(manifestObject.Schema, "CdmManifestDefinition.cdm.json");
Assert.AreEqual(manifestObject.JsonSchemaSemanticVersion, "0.9.0");
Assert.AreEqual(manifestObject.JsonSchemaSemanticVersion, "1.0.0");
Assert.AreEqual(manifestObject.ManifestName, "cdmTest");
Assert.AreEqual(manifestObject.Explanation, "test cdm folder for cdm version 0.9+");
Assert.AreEqual(manifestObject.Explanation, "test cdm folder for cdm version 1.0+");
Assert.AreEqual(manifestObject.Imports.Count, 1);
Assert.AreEqual(manifestObject.Imports[0].CorpusPath, "/primitives.cdm.json");
Assert.AreEqual(manifestObject.ExhibitsTraits.Count, 1);
@ -125,6 +128,9 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// hard coded because the time comes from inside the file
Assert.AreEqual(TimeUtils.GetFormattedDateString(statusTimeAtLoad), "2019-02-01T15:36:19.410Z");
Assert.IsNotNull(cdmManifest._fileSystemModifiedTime);
Assert.IsTrue(cdmManifest._fileSystemModifiedTime < timeBeforeLoad);
System.Threading.Thread.Sleep(100);
await cdmManifest.FileStatusCheckAsync();
@ -305,7 +311,7 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
var callback = new EventCallback();
var functionWasCalled = false;
var functionParameter1 = CdmStatusLevel.Info;
string functionParameter2 = null, functionParameter3 = null;
string functionParameter2 = null;
callback.Invoke = (CdmStatusLevel statusLevel, string message1) =>
{
functionWasCalled = true;
@ -355,7 +361,7 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
var callback = new EventCallback();
var functionWasCalled = false;
var functionParameter1 = CdmStatusLevel.Info;
string functionParameter2 = null, functionParameter3 = null;
string functionParameter2 = null;
callback.Invoke = (CdmStatusLevel statusLevel, string message1) =>
{
functionWasCalled = true;
@ -402,4 +408,4 @@ namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
Assert.IsTrue(functionParameter2.Contains("The path should not contain ../"));
}
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using System.Threading.Tasks;
@ -24,7 +27,7 @@
/// Testing for folder impl instance with referenced entity declaration.
/// </summary>
[TestMethod]
public async Task TestLoadReferencedEntity()
public void TestLoadReferencedEntity()
{
var content = TestHelper.GetInputFileContent(testsSubpath, "TestLoadReferencedEntity", "entities.manifest.cdm.json");
var cdmManifest = ManifestPersistence.FromObject(new ResolveContext(new CdmCorpusDefinition(), null), "testEntity", "testNamespace", "/", JsonConvert.DeserializeObject<ManifestContent>(content));
@ -37,4 +40,4 @@
Assert.AreEqual(entity.ExhibitsTraits.Count, 1);
}
}
}
}

Просмотреть файл

@ -1,43 +0,0 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
[TestClass]
public class NonNullDefaultValueAttribute
{
/// <summary>
/// Testing that deafualt value can be converted to A JToken
/// </summary>
[TestMethod]
public void TestNonNullDefaultValueAttribute()
{
JArray jArray = new JArray(
new JObject(
new JProperty("languageTag", "en"),
new JProperty("displayText", "Preferred Customer"),
new JProperty("attributeValue", "1"),
new JProperty("displayOrder", "0")),
new JObject(
new JProperty("languageTag", "en"),
new JProperty("displayText", "Standard"),
new JProperty("attributeValue", "2"),
new JProperty("displayOrder", "1")));
JObject input = new JObject(new JProperty("defaultValue", jArray));
CdmTypeAttributeDefinition cdmTypeAttributeDefinition = ObjectModel.Persistence.PersistenceLayer.FromData<CdmTypeAttributeDefinition, JToken>(new ResolveContext(new CdmCorpusDefinition(), null), input, "CdmFolder");
TypeAttribute result = ObjectModel.Persistence.PersistenceLayer.ToData<CdmTypeAttributeDefinition, TypeAttribute>(cdmTypeAttributeDefinition, null, null, "CdmFolder");
Assert.IsNotNull(result);
Assert.IsTrue(JToken.DeepEquals(input["defaultValue"], result.DefaultValue));
}
}
}

Просмотреть файл

@ -0,0 +1,259 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.CdmFolder
{
using System.IO;
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder;
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.CommonDataModel.ObjectModel.Storage;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.CommonDataModel.ObjectModel.Enums;
using Microsoft.CommonDataModel.ObjectModel.Persistence;
[TestClass]
public class TypeAttributeTest
{
/// <summary>
/// The path between TestDataPath and TestName.
/// </summary>
private readonly string testsSubpath = Path.Combine("Persistence", "CdmFolder", "TypeAttribute");
/// <summary>
/// Testing that default value can be converted to a JToken.
/// </summary>
[TestMethod]
public void TestNonNullDefaultValueAttribute()
{
JArray jArray = new JArray(
new JObject(
new JProperty("languageTag", "en"),
new JProperty("displayText", "Preferred Customer"),
new JProperty("attributeValue", "1"),
new JProperty("displayOrder", "0")),
new JObject(
new JProperty("languageTag", "en"),
new JProperty("displayText", "Standard"),
new JProperty("attributeValue", "2"),
new JProperty("displayOrder", "1")));
JObject input = new JObject(new JProperty("defaultValue", jArray));
CdmTypeAttributeDefinition cdmTypeAttributeDefinition = TypeAttributePersistence.FromData(new ResolveContext(new CdmCorpusDefinition(), null), input);
TypeAttribute result = PersistenceLayer.ToData<CdmTypeAttributeDefinition, TypeAttribute>(cdmTypeAttributeDefinition, null, null, PersistenceLayer.CdmFolder);
Assert.IsNotNull(result);
Assert.IsTrue(JToken.DeepEquals(input["defaultValue"], result.DefaultValue));
}
/// <summary>
/// Testing that "isPrimaryKey" property value is correct when reading from an unresolved and resolved entity schema.
/// </summary>
[TestMethod]
public async Task TestReadingIsPrimaryKey()
{
var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestReadingIsPrimaryKey");
CdmCorpusDefinition corpus = new CdmCorpusDefinition();
corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
corpus.Storage.Mount("local", new LocalAdapter(testInputPath));
corpus.Storage.DefaultNamespace = "local";
// Read from an unresolved entity schema.
CdmEntityDefinition entity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/TeamMembership.cdm.json/TeamMembership");
CdmAttributeGroupReference attributeGroupRef = (CdmAttributeGroupReference)entity.Attributes[0];
CdmAttributeGroupDefinition attributeGroup = (CdmAttributeGroupDefinition)attributeGroupRef.ExplicitReference;
CdmTypeAttributeDefinition typeAttribute = (CdmTypeAttributeDefinition)attributeGroup.Members[0];
Assert.IsTrue((bool)typeAttribute.IsPrimaryKey);
// Check that the trait "is.identifiedBy" is created with the correct argument.
CdmTraitReference isIdentifiedBy1 = typeAttribute.AppliedTraits[1];
Assert.AreEqual("is.identifiedBy", isIdentifiedBy1.NamedReference);
Assert.AreEqual("TeamMembership/(resolvedAttributes)/teamMembershipId", isIdentifiedBy1.Arguments[0].Value);
// Read from a resolved entity schema.
CdmEntityDefinition resolvedEntity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/TeamMembership_Resolved.cdm.json/TeamMembership");
CdmTypeAttributeDefinition resolvedTypeAttribute = (CdmTypeAttributeDefinition)resolvedEntity.Attributes[0];
Assert.IsTrue((bool)resolvedTypeAttribute.IsPrimaryKey);
// Check that the trait "is.identifiedBy" is created with the correct argument.
CdmTraitReference isIdentifiedBy2 = resolvedTypeAttribute.AppliedTraits[6];
Assert.AreEqual("is.identifiedBy", isIdentifiedBy2.NamedReference);
CdmAttributeReference argumentValue = isIdentifiedBy2.Arguments[0].Value;
Assert.AreEqual("TeamMembership/(resolvedAttributes)/teamMembershipId", argumentValue.NamedReference);
}
/// <summary>
/// Testing that "isPrimaryKey" property is set to true when "purpose" = "identifiedBy".
/// </summary>
[TestMethod]
public async Task TestReadingIsPrimaryKeyConstructedFromPurpose()
{
var testInputPath = TestHelper.GetInputFolderPath(testsSubpath, "TestReadingIsPrimaryKeyConstructedFromPurpose");
CdmCorpusDefinition corpus = new CdmCorpusDefinition();
corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
corpus.Storage.Mount("local", new LocalAdapter(testInputPath));
corpus.Storage.DefaultNamespace = "local";
CdmEntityDefinition entity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/TeamMembership.cdm.json/TeamMembership");
CdmAttributeGroupReference attributeGroupRef = (CdmAttributeGroupReference)entity.Attributes[0];
CdmAttributeGroupDefinition attributeGroup = (CdmAttributeGroupDefinition)attributeGroupRef.ExplicitReference;
CdmTypeAttributeDefinition typeAttribute = (CdmTypeAttributeDefinition)attributeGroup.Members[0];
Assert.AreEqual("identifiedBy", typeAttribute.Purpose.NamedReference);
Assert.IsTrue((bool)typeAttribute.IsPrimaryKey);
}
/// <summary>
/// Testing fromData and toData correctly handles all properties
/// </summary>
[TestMethod]
public async Task TestPropertyPersistence()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestPropertyPersistence", null);
var entity = await corpus.FetchObjectAsync<CdmEntityDefinition>("local:/PropertyEntity.cdm.json/PropertyEntity");
// test loading properties
var attribute = entity.Attributes[0] as CdmTypeAttributeDefinition;
Assert.IsTrue((bool)attribute.IsReadOnly);
Assert.IsTrue((bool)attribute.IsNullable);
Assert.AreEqual(attribute.SourceName, "propertyAttribute");
Assert.AreEqual(attribute.Description, "Attribute that has all properties set.");
Assert.AreEqual(attribute.DisplayName, "Property Attribute");
Assert.AreEqual(attribute.SourceOrdering, 1);
Assert.IsTrue((bool)attribute.ValueConstrainedToList);
Assert.AreEqual(attribute.MaximumLength, 10);
Assert.AreEqual(attribute.MaximumValue, "20");
Assert.AreEqual(attribute.MinimumValue, "1");
Assert.AreEqual(attribute.DataFormat, CdmDataFormat.String);
Assert.AreEqual(attribute.DefaultValue[0]["displayText"], "Default");
// test loading negative value properties
var negativeAttribute = entity.Attributes[1] as CdmTypeAttributeDefinition;
Assert.IsFalse((bool)negativeAttribute.IsReadOnly);
Assert.IsFalse((bool)negativeAttribute.IsNullable);
Assert.IsNull(negativeAttribute.SourceName);
Assert.IsNull(negativeAttribute.Description);
Assert.IsNull(negativeAttribute.DisplayName);
Assert.AreEqual(negativeAttribute.SourceOrdering, 0);
Assert.IsFalse((bool)negativeAttribute.ValueConstrainedToList);
Assert.AreEqual(negativeAttribute.MaximumLength, 0);
Assert.AreEqual(negativeAttribute.MaximumValue, "0");
Assert.AreEqual(negativeAttribute.MinimumValue, "0");
Assert.AreEqual(negativeAttribute.DataFormat, CdmDataFormat.Unknown);
Assert.AreEqual(negativeAttribute.DefaultValue[0]["displayText"], "");
// test loading values with wrongs types in file
var wrongTypesAttribute = entity.Attributes[2] as CdmTypeAttributeDefinition;
Assert.IsTrue((bool)wrongTypesAttribute.IsReadOnly);
Assert.IsTrue((bool)wrongTypesAttribute.IsNullable);
Assert.AreEqual(wrongTypesAttribute.SourceOrdering, 1);
Assert.IsFalse((bool)wrongTypesAttribute.ValueConstrainedToList);
Assert.AreEqual(wrongTypesAttribute.MaximumLength, 0);
Assert.AreEqual(wrongTypesAttribute.MaximumValue, "20");
Assert.AreEqual(wrongTypesAttribute.MinimumValue, "0");
// test loading values with wrong types that cannot be properly converted
var invalidValuesAttribute = entity.Attributes[3] as CdmTypeAttributeDefinition;
Assert.IsFalse((bool)invalidValuesAttribute.IsReadOnly);
Assert.IsNull(invalidValuesAttribute.MaximumLength);
var entityData = EntityPersistence.ToData(entity, null, null);
// test toData for properties
var attributeData = entityData.HasAttributes[0].ToObject<TypeAttribute>();
Assert.IsTrue((bool)attributeData.IsReadOnly);
Assert.IsTrue((bool)attributeData.IsNullable);
Assert.AreEqual(attributeData.SourceName, "propertyAttribute");
Assert.AreEqual(attributeData.Description, "Attribute that has all properties set.");
Assert.AreEqual(attributeData.DisplayName, "Property Attribute");
Assert.AreEqual(attributeData.SourceOrdering, 1);
Assert.IsTrue((bool)attributeData.ValueConstrainedToList);
Assert.AreEqual(attributeData.MaximumLength, 10);
Assert.AreEqual(attributeData.MaximumValue, "20");
Assert.AreEqual(attributeData.MinimumValue, "1");
Assert.AreEqual(attributeData.DataFormat, "String");
Assert.AreEqual(attributeData.DefaultValue[0]["displayText"], "Default");
// test toData for negative value properties
var negativeAttributeData = entityData.HasAttributes[1].ToObject<TypeAttribute>();
Assert.IsNull(negativeAttributeData.IsReadOnly);
Assert.IsNull(negativeAttributeData.IsNullable);
Assert.IsNull(negativeAttributeData.SourceName);
Assert.IsNull(negativeAttributeData.Description);
Assert.IsNull(negativeAttributeData.DisplayName);
Assert.IsNull(negativeAttributeData.SourceOrdering);
Assert.IsNull(negativeAttributeData.ValueConstrainedToList);
Assert.AreEqual(negativeAttributeData.MaximumLength, 0);
Assert.AreEqual(negativeAttributeData.MaximumValue, "0");
Assert.AreEqual(negativeAttributeData.MinimumValue, "0");
Assert.IsNull(negativeAttributeData.DataFormat);
Assert.AreEqual(negativeAttributeData.DefaultValue[0]["displayText"], "");
// test toData for values with wrong types in file
var wrongTypesAttributeData = entityData.HasAttributes[2].ToObject<TypeAttribute>();
Assert.IsTrue((bool)wrongTypesAttributeData.IsReadOnly);
Assert.IsTrue((bool)wrongTypesAttributeData.IsNullable);
Assert.AreEqual(wrongTypesAttributeData.SourceOrdering, 1);
Assert.IsNull(wrongTypesAttributeData.ValueConstrainedToList);
Assert.AreEqual(wrongTypesAttributeData.MaximumLength, 0);
Assert.AreEqual(wrongTypesAttributeData.MaximumValue, "20");
Assert.AreEqual(wrongTypesAttributeData.MinimumValue, "0");
// test toData with wrong types that cannot be properly converted
var invalidValuesAttributeData = entityData.HasAttributes[3].ToObject<TypeAttribute>();
Assert.IsNull(invalidValuesAttributeData.IsReadOnly);
Assert.IsNull(invalidValuesAttributeData.MaximumLength);
}
/// <summary>
/// Testing that "is.localized.describedAs" trait with a table of three entries (en, rs and cn) is fully preserved when running CdmFolder TypeAttributePersistence ToData.
/// </summary>
[TestMethod]
public void TestCdmFolderToDataTypeAttribute()
{
CdmCorpusDefinition corpus = new CdmCorpusDefinition();
corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
corpus.Storage.Mount("local", new LocalAdapter("C:\\Root\\Path"));
corpus.Storage.DefaultNamespace = "local";
var cdmTypeAttributeDefinition = corpus.MakeObject<CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "TestSavingTraitAttribute", false);
List<string> englishConstantsList = new List<string>() { "en", "Some description in English language" };
List<string> serbianConstantsList = new List<string>() { "sr", "Opis na srpskom jeziku" };
List<string> chineseConstantsList = new List<string>() { "cn", "一些中文描述" };
List<List<string>> listOfConstLists = new List<List<string>> { englishConstantsList, serbianConstantsList, chineseConstantsList };
var constEntDef = corpus.MakeObject<CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef, "localizedDescriptions", false);
constEntDef.ConstantValues = listOfConstLists;
constEntDef.EntityShape = corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, "localizedTable", true);
var traitReference2 = corpus.MakeObject<CdmTraitReference>(CdmObjectType.TraitRef, "is.localized.describedAs", false);
traitReference2.Arguments.Add("localizedDisplayText", corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, constEntDef, true));
cdmTypeAttributeDefinition.AppliedTraits.Add(traitReference2);
TypeAttribute result = PersistenceLayer.ToData<CdmTypeAttributeDefinition, TypeAttribute>(cdmTypeAttributeDefinition, null, null, PersistenceLayer.CdmFolder);
Assert.IsNotNull(result.AppliedTraits);
var argument = result.AppliedTraits[0].ToObject<TraitReferenceDefinition>().Arguments[0].ToObject<Argument>();
List<List<string>> constantValues = argument.Value.ToObject<EntityReferenceDefinition>().EntityReference.ToObject<ConstantEntity>().ConstantValues;
Assert.AreEqual("en", constantValues[0][0]);
Assert.AreEqual("Some description in English language", constantValues[0][1]);
Assert.AreEqual("sr", constantValues[1][0]);
Assert.AreEqual("Opis na srpskom jeziku", constantValues[1][1]);
Assert.AreEqual("cn", constantValues[2][0]);
Assert.AreEqual("一些中文描述", constantValues[2][1]);
}
}
}

Просмотреть файл

@ -1,4 +1,6 @@

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
{
using System.IO;

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Persistence.ModelJson;
@ -11,11 +14,9 @@
using System.IO;
using System.Threading.Tasks;
using Assert = Microsoft.CommonDataModel.ObjectModel.Tests.AssertExtension;
using DocumentContent = Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types.DocumentContent;
using cdmDocument = Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.DocumentPersistence;
using cdmManifestPersistence = Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.ManifestPersistence;
using modelManifestPersistence = Microsoft.CommonDataModel.ObjectModel.Persistence.ModelJson.ManifestPersistence;
using Assert = AssertExtension;
using cdmDocument = ObjectModel.Persistence.CdmFolder.DocumentPersistence;
using cdmManifestPersistence = ObjectModel.Persistence.CdmFolder.ManifestPersistence;
/// <summary>
/// Class containing tests related to MetadataObject class (and it's children) use, serialization and deserialization.
@ -28,7 +29,10 @@
/// </summary>
private string testsSubpath = Path.Combine("Persistence", "ModelJson", "ModelJsonExtensibility");
private bool doesWriteTestDebuggingFiles = TestHelper.DoesWriteTestDebuggingFiles;
/// <summary>
/// Whether debugging files should be written or not.
/// </summary>
private bool doesWriteTestDebuggingFiles = false;
/// <summary>
/// Tests the serializer and the deserializer.
@ -184,7 +188,7 @@
TestHelper.WriteActualOutputFileContent(testsSubpath, "ModelJsonExtensibilityManifestDocuments", manifest.Name, serializedManifest);
}
foreach(var doc in folderObject.Documents)
foreach (var doc in folderObject.Documents)
{
// manifest shows up twice. once as a manifest and again as the model.json conversion cached
if (doc.Name == manifest.Name)
@ -192,7 +196,7 @@
continue;
}
string serializedDocument = Serialize(cdmDocument.ToData(doc, null, null));
string serializedDocument = Serialize(cdmDocument.ToData(doc, null, null));
var expectedOutputDocument = TestHelper.GetExpectedOutputFileContent(testsSubpath, "ModelJsonExtensibilityManifestDocuments", doc.Name);

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
{
using Microsoft.CommonDataModel.ObjectModel.Persistence.ModelJson;
using CdmFolderPersistence = ObjectModel.Persistence.CdmFolder;
@ -12,6 +15,7 @@
using System.Collections.Generic;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.ObjectModel.Persistence;
/// <summary>
/// The model json tests.
@ -23,20 +27,18 @@
/// </summary>
private readonly string testsSubpath = Path.Combine("Persistence", "ModelJson", "ModelJson");
private readonly bool doesWriteTestDebuggingFiles = TestHelper.DoesWriteTestDebuggingFiles;
/// <summary>
/// Test ManifestPersistence fromData and toData and save it back to a file.
/// Test ManifestPersistence fromData and toData.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
[Test]
[Retry(3)]
public async Task TestFromAndToData()
public async Task TestModelJsonFromAndToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestFromAndToData");
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestModelJsonFromAndToData));
var watch = Stopwatch.StartNew();
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("model.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, cdmCorpus.Storage.FetchRootFolder("local"));
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Loading from data");
@ -45,21 +47,21 @@
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Parsing to data");
this.HandleOutput("TestFromAndToData", "model.json", obtainedModelJson);
this.HandleOutput(nameof(TestModelJsonFromAndToData), PersistenceLayer.ModelJsonExtension, obtainedModelJson);
}
/// <summary>
/// Test loading CDM folder files and save the model.json file.
/// Test loading CDM folder files and model json ManifestPersistence toData.
/// </summary>
/// <returns> The <see cref="Task"/>.</returns>
[Test]
[Retry(3)]
public async Task TestLoadingCdmFolderAndSavingModelJson()
public async Task TestLoadingCdmFolderAndModelJsonToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingCdmFolderAndSavingModelJson");
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestLoadingCdmFolderAndModelJsonToData));
var watch = Stopwatch.StartNew();
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("default.manifest.cdm.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>($"default{PersistenceLayer.ManifestExtension}", cdmCorpus.Storage.FetchRootFolder("local"));
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Loading from data");
@ -68,21 +70,21 @@
watch.Stop();
Assert.Performance(5000, watch.ElapsedMilliseconds, "Parsing to data");
this.HandleOutput("TestLoadingCdmFolderAndSavingModelJson", "model.json", obtainedModelJson);
this.HandleOutput(nameof(TestLoadingCdmFolderAndModelJsonToData), PersistenceLayer.ModelJsonExtension, obtainedModelJson);
}
/// <summary>
/// Test loading model json result files and save it as CDM folders files.
/// Test loading model json result files and CDM folders ManifestPersistence toData.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
[Test]
[Retry(3)]
public async Task TestLoadingModelJsonResultAndSavingCdmFolder()
public async Task TestLoadingModelJsonResultAndCdmFolderToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingModelJsonResultAndSavingCdmFolder");
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestLoadingModelJsonResultAndCdmFolderToData));
var watch = Stopwatch.StartNew();
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("model.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, cdmCorpus.Storage.FetchRootFolder("local"));
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Loading from data");
@ -91,21 +93,21 @@
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Parsing to data");
this.HandleOutput("TestLoadingModelJsonResultAndSavingCdmFolder", "cdmFolder.json", obtainedCdmFolder);
this.HandleOutput(nameof(TestLoadingModelJsonResultAndCdmFolderToData), $"cdmFolder{PersistenceLayer.CdmExtension}", obtainedCdmFolder);
}
/// <summary>
/// Test loading model.json files and save as CDM folders files.
/// Test loading model.json files and CDM folders ManifestPersistence toData.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
[Test]
[Retry(3)]
public async Task TestLoadingModelJsonAndSavingCdmFolder()
public async Task TestLoadingModelJsonAndCdmFolderToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingModelJsonAndSavingCdmFolder");
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestLoadingModelJsonAndCdmFolderToData));
var watch = Stopwatch.StartNew();
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("model.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, cdmCorpus.Storage.FetchRootFolder("local"));
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Loading from data");
@ -114,21 +116,21 @@
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Parsing to data");
this.HandleOutput("TestLoadingModelJsonAndSavingCdmFolder", "cdmFolder.json", obtainedCdmFolder);
this.HandleOutput(nameof(TestLoadingModelJsonAndCdmFolderToData), $"cdmFolder{PersistenceLayer.CdmExtension}", obtainedCdmFolder);
}
/// <summary>
/// Test loading CDM folder result files and save as model.json.
/// Test loading CDM folder result files and model json ManifestPersistence toData.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
[Test]
[Retry(3)]
public async Task TestLoadingCdmFolderResultAndSavingModelJson()
public async Task TestLoadingCdmFolderResultAndModelJsonToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestLoadingCdmFolderResultAndSavingModelJson");
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestLoadingCdmFolderResultAndModelJsonToData));
var watch = Stopwatch.StartNew();
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("result.model.manifest.cdm.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>($"result.model{PersistenceLayer.ManifestExtension}", cdmCorpus.Storage.FetchRootFolder("local"));
watch.Stop();
Assert.Performance(1000, watch.ElapsedMilliseconds, "Loading from data");
@ -141,7 +143,7 @@
obtainedModelJson.Entities.ForEach(RemoveDescriptionFromEntityIfEmpty);
obtainedModelJson.Description = null;
this.HandleOutput("TestLoadingCdmFolderResultAndSavingModelJson", "model.json", obtainedModelJson);
this.HandleOutput(nameof(TestLoadingCdmFolderResultAndModelJsonToData), PersistenceLayer.ModelJsonExtension, obtainedModelJson);
}
/// <summary>
@ -152,7 +154,7 @@
[Retry(3)]
public async Task TestManifestFoundationImport()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestManifestFoundationImport");
var corpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestManifestFoundationImport));
var callback = new EventCallback
{
@ -166,7 +168,7 @@
};
corpus.SetEventCallback(callback);
var cdmManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("model.json", corpus.Storage.FetchRootFolder("local"));
var cdmManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, corpus.Storage.FetchRootFolder("local"));
}
/// <summary>
@ -213,9 +215,9 @@
[Test]
public async Task TestReferenceModels()
{
var corpus = TestHelper.GetLocalCorpus(testsSubpath, "TestReferenceModels");
var corpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestReferenceModels));
var manifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("model.json", corpus.Storage.FetchRootFolder("local"));
var manifest = await corpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, corpus.Storage.FetchRootFolder("local"));
// entity with same modelId but different location
var referenceEntity1 = new CdmReferencedEntityDeclarationDefinition(corpus.Ctx, "ReferenceEntity1")
@ -256,24 +258,24 @@
var obtainedModelJson = await ManifestPersistence.ToData(manifest, null, null);
this.HandleOutput("TestReferenceModels", "model.json", obtainedModelJson);
this.HandleOutput(nameof(TestReferenceModels), PersistenceLayer.ModelJsonExtension, obtainedModelJson);
}
/// <summary>
/// Tests loading Model.json and converting to a CdmFolder.
/// Tests loading Model.json and CDM folders ManifestPersistence toData.
/// </summary>
[Test]
public async Task TestExtensibilityLoadingModelJsonAndSavingCdmFolder()
public async Task TestExtensibilityLoadingModelJsonAndCdmFolderToData()
{
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, "TestExtensibilityLoadingModelJsonAndSavingCdmFolder");
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>("model.json", cdmCorpus.Storage.FetchRootFolder("local"));
var cdmCorpus = TestHelper.GetLocalCorpus(testsSubpath, nameof(TestExtensibilityLoadingModelJsonAndCdmFolderToData));
var cdmManifest = await cdmCorpus.FetchObjectAsync<CdmManifestDefinition>(PersistenceLayer.ModelJsonExtension, cdmCorpus.Storage.FetchRootFolder("local"));
var obtainedCdmFolder = CdmFolderPersistence.ManifestPersistence.ToData(cdmManifest, null, null);
// For EntityReferences, entityPath contains a GUID that will not match the snapshot.
obtainedCdmFolder.Entities.ForEach(this.RemoveEntityPathForReferencedEntities);
this.HandleOutput("TestExtensibilityLoadingModelJsonAndSavingCdmFolder", "cdmFolder.json", obtainedCdmFolder);
this.HandleOutput(nameof(TestExtensibilityLoadingModelJsonAndCdmFolderToData), $"cdmFolder{PersistenceLayer.CdmExtension}", obtainedCdmFolder);
}
/// <summary>
@ -285,10 +287,11 @@
/// <param name="testName"> The name of the test.</param>
/// <param name="outputFileName"> The name of the output file. Used both for expected and actual output.</param>
/// <param name="actualOutput"> The output obtaind through operations, that is to be compared with the expected output.</param>
private void HandleOutput<T>(string testName, string outputFileName, T actualOutput)
/// <parameter name="doesWriteDebuggingFiles"> Whether debugging files should be written or not. </parameter>
private void HandleOutput<T>(string testName, string outputFileName, T actualOutput, bool doesWriteTestDebuggingFiles = false)
{
var serializedOutput = Serialize(actualOutput);
if (this.doesWriteTestDebuggingFiles)
if (doesWriteTestDebuggingFiles)
{
TestHelper.WriteActualOutputFileContent(testsSubpath, testName, outputFileName, serializedOutput);
}

Просмотреть файл

@ -1,14 +1,10 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
/// <summary>
/// Base class for ModelJson tests.

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence.ModelJson
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Utilities;
using Microsoft.CommonDataModel.ObjectModel.Persistence.CdmFolder.Types;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.CommonDataModel.ObjectModel.Storage;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.CommonDataModel.ObjectModel.Enums;
using Microsoft.CommonDataModel.ObjectModel.Persistence.ModelJson.types;
using Microsoft.CommonDataModel.ObjectModel.Persistence;
[TestClass]
public class TypeAttributeTest
{
/// <summary>
/// Testing that "is.localized.describedAs" trait with a table of three entries (en, rs and cn) is fully preserved when running ModelJson TypeAttributePersistence ToData.
/// </summary>
[TestMethod]
public void TestModelJsonToDataTypeAttribute()
{
CdmCorpusDefinition corpus = new CdmCorpusDefinition();
corpus.SetEventCallback(new EventCallback { Invoke = CommonDataModelLoader.ConsoleStatusReport }, CdmStatusLevel.Warning);
corpus.Storage.Mount("local", new LocalAdapter("C:\\Root\\Path"));
corpus.Storage.DefaultNamespace = "local";
var cdmTypeAttributeDefinition = corpus.MakeObject<CdmTypeAttributeDefinition>(CdmObjectType.TypeAttributeDef, "TestSavingTraitAttribute", false);
List<string> englishConstantsList = new List<string>() { "en", "Some description in English language" };
List<string> serbianConstantsList = new List<string>() { "sr", "Opis na srpskom jeziku" };
List<string> chineseConstantsList = new List<string>() { "cn", "一些中文描述" };
List<List<string>> listOfConstLists = new List<List<string>> { englishConstantsList, serbianConstantsList, chineseConstantsList };
var constEntDef = corpus.MakeObject<CdmConstantEntityDefinition>(CdmObjectType.ConstantEntityDef, "localizedDescriptions", false);
constEntDef.ConstantValues = listOfConstLists;
constEntDef.EntityShape = corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, "localizedTable", true);
var traitReference2 = corpus.MakeObject<CdmTraitReference>(CdmObjectType.TraitRef, "is.localized.describedAs", false);
traitReference2.Arguments.Add("localizedDisplayText", corpus.MakeRef<CdmEntityReference>(CdmObjectType.EntityRef, constEntDef, true));
cdmTypeAttributeDefinition.AppliedTraits.Add(traitReference2);
var result = PersistenceLayer.ToData<CdmTypeAttributeDefinition, Task<Attribute>>(cdmTypeAttributeDefinition, null, null, PersistenceLayer.ModelJson).Result;
Assert.IsNotNull(result.Traits);
var argument = result.Traits[0].ToObject<TraitReferenceDefinition>().Arguments[0].ToObject<Argument>();
List<List<string>> constantValues = argument.Value.ToObject<EntityReferenceDefinition>().EntityReference.ToObject<ConstantEntity>().ConstantValues;
Assert.AreEqual("en", constantValues[0][0]);
Assert.AreEqual("Some description in English language", constantValues[0][1]);
Assert.AreEqual("sr", constantValues[1][0]);
Assert.AreEqual("Opis na srpskom jeziku", constantValues[1][1]);
Assert.AreEqual("cn", constantValues[2][0]);
Assert.AreEqual("一些中文描述", constantValues[2][1]);
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Persistence
{
using Microsoft.CommonDataModel.ObjectModel.Cdm;
using Microsoft.CommonDataModel.ObjectModel.Storage;
@ -6,6 +9,7 @@
using Microsoft.CommonDataModel.Tools.Processor;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@ -33,7 +37,7 @@
{
invalidManifest = await corpus.FetchObjectAsync<CdmManifestDefinition>("local:/invalidManifest.manifest.cdm.json");
}
catch (Exception e)
catch (Exception)
{
Assert.Fail("Error should not be thrown when input json is invalid.");
}
@ -68,7 +72,7 @@
var manifestFromModelJson = await corpus.FetchObjectAsync<CdmManifestDefinition>("Model.json");
// Swap out the adapter for a fake one so that we aren't actually saving files.
Dictionary<string, string> allDocs = new Dictionary<string, string>();
ConcurrentDictionary<string, string> allDocs = new ConcurrentDictionary<string, string>();
var testAdapter = new TestStorageAdapter(allDocs);
corpus.Storage.SetAdapter("local", testAdapter);
@ -106,7 +110,7 @@
var manifestFromModelJson = await corpus.FetchObjectAsync<CdmManifestDefinition>("sub-folder/model.json");
// Swap out the adapter for a fake one so that we aren't actually saving files.
Dictionary<string, string> allDocs = new Dictionary<string, string>();
ConcurrentDictionary<string, string> allDocs = new ConcurrentDictionary<string, string>();
var testAdapter = new TestStorageAdapter(allDocs);
corpus.Storage.SetAdapter("local", testAdapter);
@ -131,7 +135,7 @@
corpus.Storage.FetchRootFolder("local").Documents.Add(manifest);
Dictionary<string, string> allDocs = new Dictionary<string, string>();
ConcurrentDictionary<string, string> allDocs = new ConcurrentDictionary<string, string>();
var testAdapter = new TestStorageAdapter(allDocs);
corpus.Storage.SetAdapter("local", testAdapter);

Просмотреть файл

@ -0,0 +1,51 @@
using Microsoft.CommonDataModel.ObjectModel.Storage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Storage
{
[TestClass]
public class AdlsAdapterTests
{
/// <summary>
/// Creates corpus path and adapter path.
/// </summary>
[TestMethod]
public void TestCreateCorpusAndAdapterPathInAdlsAdapter()
{
var host1 = "storageaccount.dfs.core.windows.net";
var root = "/fs";
var adlsAdapter = new ADLSAdapter(host1, root, string.Empty);
var adapterPath1 = "https://storageaccount.dfs.core.windows.net/fs/a/1.csv";
var adapterPath2 = "https://storageaccount.dfs.core.windows.net:443/fs/a/2.csv";
var adapterPath3 = "https://storageaccount.blob.core.windows.net/fs/a/3.csv";
var adapterPath4 = "https://storageaccount.blob.core.windows.net:443/fs/a/4.csv";
var corpusPath1 = adlsAdapter.CreateCorpusPath(adapterPath1);
var corpusPath2 = adlsAdapter.CreateCorpusPath(adapterPath2);
var corpusPath3 = adlsAdapter.CreateCorpusPath(adapterPath3);
var corpusPath4 = adlsAdapter.CreateCorpusPath(adapterPath4);
Assert.AreEqual("/a/1.csv", corpusPath1);
Assert.AreEqual("/a/2.csv", corpusPath2);
Assert.AreEqual("/a/3.csv", corpusPath3);
Assert.AreEqual("/a/4.csv", corpusPath4);
Assert.AreEqual(adapterPath1, adlsAdapter.CreateAdapterPath(corpusPath1));
Assert.AreEqual(adapterPath2, adlsAdapter.CreateAdapterPath(corpusPath2));
Assert.AreEqual(adapterPath3, adlsAdapter.CreateAdapterPath(corpusPath3));
Assert.AreEqual(adapterPath4, adlsAdapter.CreateAdapterPath(corpusPath4));
var host2 = "storageaccount.blob.core.windows.net:8888";
adlsAdapter = new ADLSAdapter(host2, root, string.Empty);
var adapterPath5 = "https://storageaccount.blob.core.windows.net:8888/fs/a/5.csv";
var adapterPath6 = "https://storageaccount.dfs.core.windows.net:8888/fs/a/6.csv";
var adapterPath7 = "https://storageaccount.blob.core.windows.net/fs/a/7.csv";
Assert.AreEqual("/a/5.csv", adlsAdapter.CreateCorpusPath(adapterPath5));
Assert.AreEqual("/a/6.csv", adlsAdapter.CreateCorpusPath(adapterPath6));
Assert.AreEqual(null, adlsAdapter.CreateCorpusPath(adapterPath7));
}
}
}

Просмотреть файл

@ -1,4 +1,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Storage
{

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using Microsoft.CommonDataModel.ObjectModel.Storage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Storage
{
[TestClass]
public class LocalAdapterTests
{
/// <summary>
/// Test that CreateAdapterPath returns the same result for a path with or without a leading slash.
/// </summary>
[TestMethod]
public void TestCreateAdapterPath()
{
var adapter = new LocalAdapter("C:/some/dir");
string pathWithLeadingSlash = adapter.CreateAdapterPath("/folder");
string pathWithoutLeadingSlash = adapter.CreateAdapterPath("folder");
Assert.AreEqual(pathWithLeadingSlash, "C:\\some\\dir\\folder");
Assert.AreEqual(pathWithLeadingSlash, pathWithoutLeadingSlash);
}
}
}

Просмотреть файл

@ -1,8 +1,5 @@
//-----------------------------------------------------------------------
// <copyright file="ADLSAdapter.cs" company="Microsoft">
// All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Storage
{

Просмотреть файл

@ -1,4 +1,7 @@
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Storage
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
namespace Microsoft.CommonDataModel.ObjectModel.Tests.Cdm.Storage
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "missing.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "notMissing.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "missing.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "missing.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "missingImport.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "missing.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [],
"definitions": []
}

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "importEntity.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "importEntity.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "subEntity1.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "targetImport.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "targetImport.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [],
"definitions": []
}

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "subEntity1.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "targetImport.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "targetImport.cdm.json"

Просмотреть файл

@ -7,7 +7,7 @@
}
],
"lastFileStatusCheckTime": "0001-01-01T06:00:00.000Z",
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "cdm:/someImport.cdm.json",

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Просмотреть файл

@ -1,5 +1,5 @@
{
"jsonSchemaSemanticVersion": "0.9.0",
"jsonSchemaSemanticVersion": "1.0.0",
"imports": [
{
"corpusPath": "_allImports.cdm.json"

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше