Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests
{
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using System;
Expand Down Expand Up @@ -1304,8 +1304,104 @@ public async Task WithClientEncryptionPolicyFailureTest()
{
Assert.IsTrue(ex.Message.Contains("Only Deterministic encryption type is supported for path: /id."), ex.Message);
}
}

}

[Ignore("Marking as ignore until emulator is updated")]
[TestMethod]
[DataRow("en-US")]
[DataRow("fr-FR")]
[DataRow("de-DE")]
[DataRow("it-IT")]
[DataRow("pt-BR")]
[DataRow("pt-PT")]
[DataRow("es-ES")]
public async Task TestFullTextSearchPolicyWithAllSupportedDefaultLanguages(string defaultLanguage)
{
string fullTextPath1 = "/fts1", fullTextPath2 = "/fts2";
string endpoint = "";
string key = "";

string databaseName = "TestDatabaseFullTextPolicy";
string containerName = "TestContainerFullTextPolicy_"+ defaultLanguage;

CosmosClientOptions clientOptions = new CosmosClientOptions
{
ConnectionMode = ConnectionMode.Direct,
};
CosmosClient client = new(endpoint, key, clientOptions);

Database databaseForFullTextSearch = await client.CreateDatabaseIfNotExistsAsync(databaseName);
try
{
string partitionKeyPath = "/pk";

Collection<FullTextPath> fullTextPaths = new Collection<FullTextPath>()
{
new FullTextPath()
{
Path = fullTextPath1,
Language = defaultLanguage,
},
new FullTextPath()
{
Path = fullTextPath2,
Language = defaultLanguage,
}
};

ContainerResponse containerResponse =
await databaseForFullTextSearch.DefineContainer(containerName, partitionKeyPath)
.WithFullTextPolicy(
defaultLanguage: defaultLanguage,
fullTextPaths: fullTextPaths)
.Attach()
.WithIndexingPolicy()
.WithFullTextIndex()
.Path(fullTextPath1)
.Attach()
.WithFullTextIndex()
.Path(fullTextPath2)
.Attach()
.Attach()
.CreateAsync();

Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode,
$"Failed to create container with default language: {defaultLanguage}");
Assert.AreEqual(containerName, containerResponse.Resource.Id);
Assert.AreEqual(partitionKeyPath, containerResponse.Resource.PartitionKey.Paths.First());

ContainerProperties containerSettings = containerResponse.Resource;

// Validate FullText Policy
Assert.IsNotNull(containerSettings.FullTextPolicy,
$"FullTextPolicy is null for language: {defaultLanguage}");
Assert.AreEqual(defaultLanguage, containerSettings.FullTextPolicy.DefaultLanguage,
$"DefaultLanguage mismatch for: {defaultLanguage}");
Assert.IsNotNull(containerSettings.FullTextPolicy.FullTextPaths);
Assert.AreEqual(fullTextPaths.Count, containerSettings.FullTextPolicy.FullTextPaths.Count());

// Validate each path has the correct language
foreach (FullTextPath path in containerSettings.FullTextPolicy.FullTextPaths)
{
Assert.AreEqual(defaultLanguage, path.Language,
$"Path language mismatch for default language: {defaultLanguage}");
}

// Validate Full Text Indexes
Assert.IsNotNull(containerSettings.IndexingPolicy.FullTextIndexes);
Assert.AreEqual(fullTextPaths.Count, containerSettings.IndexingPolicy.FullTextIndexes.Count());
Assert.AreEqual(fullTextPath1, containerSettings.IndexingPolicy.FullTextIndexes[0].Path);
Assert.AreEqual(fullTextPath2, containerSettings.IndexingPolicy.FullTextIndexes[1].Path);

// Clean up container after test
await containerResponse.Container.DeleteContainerAsync();
}
finally
{
await databaseForFullTextSearch.DeleteAsync();
}
}

private bool VerifyClientEncryptionIncludedPath(ClientEncryptionIncludedPath expected, ClientEncryptionIncludedPath actual)
{
return expected.Path == actual.Path &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,85 @@ public async Task ValidateVectorEmbeddingsAndIndexingPolicyUsingContainerBuilder
It.IsAny<RequestOptions>(),
It.IsAny<CancellationToken>()), Times.Once);
}

[TestMethod]
[DataRow("en-US")]
[DataRow("fr-FR")]
[DataRow("de-DE")]
[DataRow("it-IT")]
[DataRow("pt-BR")]
[DataRow("pt-PT")]
[DataRow("es-ES")]
public async Task ValidateFullTextPolicyWithAllSupportedLanguages(string language)
{
string fullTextPath1 = "/fts1", fullTextPath2 = "/fts2";

Collection<FullTextPath> fullTextPaths = new Collection<FullTextPath>()
{
new Cosmos.FullTextPath()
{
Path = fullTextPath1,
Language = language,
},
new Cosmos.FullTextPath()
{
Path = fullTextPath2,
Language = language,
}
};

Mock<ContainerResponse> mockContainerResponse = new Mock<ContainerResponse>();
mockContainerResponse
.Setup(x => x.StatusCode)
.Returns(HttpStatusCode.Created);

Mock<Database> mockDatabase = new Mock<Database>();
Mock<CosmosClient> mockClient = new Mock<CosmosClient>();
mockDatabase.Setup(m => m.Client).Returns(mockClient.Object);
mockDatabase
.Setup(c => c.CreateContainerAsync(
It.IsAny<ContainerProperties>(),
It.IsAny<int?>(),
It.IsAny<RequestOptions>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(mockContainerResponse.Object);
mockDatabase
.Setup(c => c.Id)
.Returns(Guid.NewGuid().ToString());

ContainerBuilder containerFluentDefinition = new ContainerBuilder(
mockDatabase.Object,
containerName,
partitionKey);

ContainerResponse response = await containerFluentDefinition
.WithFullTextPolicy(
defaultLanguage: language,
fullTextPaths: fullTextPaths)
.Attach()
.WithIndexingPolicy()
.WithFullTextIndex()
.Path(fullTextPath1)
.Attach()
.WithFullTextIndex()
.Path(fullTextPath2)
.Attach()
.Attach()
.CreateAsync();

Assert.AreEqual(HttpStatusCode.Created, response.StatusCode);

// Verify the correct language was passed
mockDatabase.Verify(c => c.CreateContainerAsync(
It.Is<ContainerProperties>((settings) =>
settings.FullTextPolicy.DefaultLanguage == language &&
settings.FullTextPolicy.FullTextPaths.Count == 2 &&
settings.FullTextPolicy.FullTextPaths.All(p => p.Language == language)),
It.IsAny<int?>(),
It.IsAny<RequestOptions>(),
It.IsAny<CancellationToken>()), Times.Once,
$"Failed to verify container creation with language: {language}");
}

private static CosmosClientContext GetContext()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace Microsoft.Azure.Cosmos.Tests
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using FullTextPath = Microsoft.Azure.Cosmos.FullTextPath;
using FullTextPath = Microsoft.Azure.Cosmos.FullTextPath;
using FullTextPolicy = Microsoft.Azure.Cosmos.FullTextPolicy;

[TestClass]
public class SettingsContractTests
Expand Down Expand Up @@ -1203,6 +1204,71 @@ public void FullTextPolicySerialization()
Assert.AreEqual(JTokenType.String, fullTextLanguageDeSerialized.Type, "Full Text Policy serialized language should be a string.");
Assert.IsTrue(fullTextPath1.Equals(fullTextPathsDeSerialized.Value<JArray>()[0].ToObject<Cosmos.FullTextPath>()));
Assert.IsTrue(fullTextPath2.Equals(fullTextPathsDeSerialized.Value<JArray>()[1].ToObject<Cosmos.FullTextPath>()));
}

[TestMethod]
[DataRow("en-US")]
[DataRow("fr-FR")]
[DataRow("de-DE")]
[DataRow("it-IT")]
[DataRow("pt-BR")]
[DataRow("pt-PT")]
[DataRow("es-ES")]
public void FullTextPolicySerializationWithAllSupportedLanguages(string language)
{
FullTextPolicy fullTextPolicy = new FullTextPolicy
{
DefaultLanguage = language,
FullTextPaths = new Collection<FullTextPath>
{
new FullTextPath { Path = "/text1", Language = language },
new FullTextPath { Path = "/text2", Language = "en-US" },
new FullTextPath { Path = "/text3" } // No language specified, should use default
}
};

string serialized = CosmosSerialize(fullTextPolicy);
Assert.IsNotNull(serialized);
Assert.IsTrue(serialized.Contains($"\"defaultLanguage\":\"{language}\""),
$"Serialized JSON should contain defaultLanguage: {language}");

FullTextPolicy deserialized = CosmosDeserialize<FullTextPolicy>(serialized);
Assert.IsNotNull(deserialized);
Assert.AreEqual(language, deserialized.DefaultLanguage,
$"DefaultLanguage mismatch after deserialization for: {language}");
Assert.AreEqual(3, deserialized.FullTextPaths.Count);
Assert.AreEqual(language, deserialized.FullTextPaths[0].Language);
Assert.AreEqual("en-US", deserialized.FullTextPaths[1].Language);
Assert.IsNull(deserialized.FullTextPaths[2].Language);
}

[TestMethod]
[DataRow("en-US")]
[DataRow("fr-FR")]
[DataRow("de-DE")]
[DataRow("it-IT")]
[DataRow("ja-JP")]
[DataRow("pt-BR")]
[DataRow("pt-PT")]
[DataRow("es-ES")]
public void FullTextPathSerializationWithAllLanguages(string language)
{
FullTextPath fullTextPath = new FullTextPath
{
Path = "/testPath",
Language = language
};

string serialized = CosmosSerialize(fullTextPath);
Assert.IsNotNull(serialized);
Assert.IsTrue(serialized.Contains($"\"language\":\"{language}\""),
$"Serialized JSON should contain language: {language}");

FullTextPath deserialized = CosmosDeserialize<FullTextPath>(serialized);
Assert.IsNotNull(deserialized);
Assert.AreEqual("/testPath", deserialized.Path);
Assert.AreEqual(language, deserialized.Language,
$"Language mismatch after deserialization for: {language}");
}

private static T CosmosDeserialize<T>(string payload)
Expand Down