From d9fd18c407f58cc7d7f6e8e0f6b7fa4b0660b7ff Mon Sep 17 00:00:00 2001 From: RubenCerna2079 <32799214+RubenCerna2079@users.noreply.github.com> Date: Fri, 11 Oct 2024 15:46:28 -0700 Subject: [PATCH] Capitalization Collation Tests (#2387) ## Why make this change? Solves issue #2350, to add collation tests related to capitalization. ## What is this change? Added collation tests related to case sensitivity for `MSSQL`, `MYSQL`, & `POSTGRESQL` by creating a new `GraphQLCollationTests` file under `SQLTests` that will have all the tests related to changes in collations for SQL databases. ## How was this tested? - [X] Integration Tests - [ ] Unit Tests --------- Co-authored-by: Ruben Cerna --- .../GraphQLCollationTestBase.cs | 44 +++++++++++++++ .../MsSqlGraphQLCollationTests.cs | 56 +++++++++++++++++++ .../MySqlGraphQLCollationTests.cs | 56 +++++++++++++++++++ .../PostgreSqlGraphQLCollationTests.cs | 55 ++++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 src/Service.Tests/SqlTests/GraphQLCollationTests/GraphQLCollationTestBase.cs create mode 100644 src/Service.Tests/SqlTests/GraphQLCollationTests/MsSqlGraphQLCollationTests.cs create mode 100644 src/Service.Tests/SqlTests/GraphQLCollationTests/MySqlGraphQLCollationTests.cs create mode 100644 src/Service.Tests/SqlTests/GraphQLCollationTests/PostgreSqlGraphQLCollationTests.cs diff --git a/src/Service.Tests/SqlTests/GraphQLCollationTests/GraphQLCollationTestBase.cs b/src/Service.Tests/SqlTests/GraphQLCollationTests/GraphQLCollationTestBase.cs new file mode 100644 index 0000000000..f90896f0d4 --- /dev/null +++ b/src/Service.Tests/SqlTests/GraphQLCollationTests/GraphQLCollationTestBase.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Azure.DataApiBuilder.Service.Tests.SqlTests.GraphQLCollationTests +{ + [TestClass] + public class GraphQLCollationTestBase : SqlTestBase + { + #region Tests + + /// + /// Compares SQL Database Query with GraphQL Query + /// To ensure that GraphQL is working as expected with case sensitive collations + /// + public async Task TestQueryingWithCaseSensitiveCollation(string objectType, string fieldName, string dbQuery, string defaultCollationQuery, string newCollationQuery) + { + string graphQLQueryName = objectType; + string graphQLQuery = @" + query { " + + objectType + @" (orderBy: {" + fieldName + @": ASC" + @"}) { + items { " + + fieldName + @" + } + } + } + "; + + //Change collation to be case sensitive before executing GraphQL test + await GetDatabaseResultAsync(newCollationQuery); + JsonElement actual = await ExecuteGraphQLRequestAsync(graphQLQuery, graphQLQueryName, isAuthenticated: true); + + //Change collation back to default before executing expected test + await GetDatabaseResultAsync(defaultCollationQuery); + string expected = await GetDatabaseResultAsync(dbQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual.GetProperty("items").ToString()); + } + #endregion + } +} diff --git a/src/Service.Tests/SqlTests/GraphQLCollationTests/MsSqlGraphQLCollationTests.cs b/src/Service.Tests/SqlTests/GraphQLCollationTests/MsSqlGraphQLCollationTests.cs new file mode 100644 index 0000000000..536efbe816 --- /dev/null +++ b/src/Service.Tests/SqlTests/GraphQLCollationTests/MsSqlGraphQLCollationTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Azure.DataApiBuilder.Service.Tests.SqlTests.GraphQLCollationTests +{ + /// + /// Test GraphQL Collations validating proper operations. + /// + [TestClass, TestCategory(TestCategory.MSSQL)] + public class MsSqlGraphQLCollationTests : GraphQLCollationTestBase + { + //Collation setting for database + private const string DEFAULT_COLLATION = "Latin1_General_100_CI_AI_SC_UTF8"; + private const string CASE_SENSITIVE_COLLATION = "Latin1_General_100_CS_AI_SC_UTF8"; + + /// + /// Set the database engine for the tests + /// + [ClassInitialize] + public static async Task SetupAsync(TestContext context) + { + DatabaseEngine = TestCategory.MSSQL; + await InitializeTestFixture(); + } + + #region Tests + /// + /// MsSql Collation Tests to ensure that GraphQL is working properly when there is a change in case sensitivity on the database + /// + [DataTestMethod] + [DataRow("comics", "title", @"SELECT title FROM comics ORDER BY title ASC FOR JSON PATH, INCLUDE_NULL_VALUES")] + [DataRow("authors", "name", @"SELECT name FROM authors ORDER BY name ASC FOR JSON PATH, INCLUDE_NULL_VALUES")] + [DataRow("fungi", "habitat", @"SELECT habitat FROM fungi ORDER BY habitat ASC FOR JSON PATH, INCLUDE_NULL_VALUES")] + public async Task MsSqlCaseSensitiveResultQuery(string objectType, string fieldName, string dbQuery) + { + string defaultCollationQuery = MsSqlCollationQuery(objectType, fieldName, DEFAULT_COLLATION); + string newCollationQuery = MsSqlCollationQuery(objectType, fieldName, CASE_SENSITIVE_COLLATION); + await TestQueryingWithCaseSensitiveCollation(objectType, fieldName, dbQuery, defaultCollationQuery, newCollationQuery); + } + + /// + /// Creates collation query for a specific column on a table in the database for MsSql + /// + private static string MsSqlCollationQuery(string table, string column, string newCollation) + { + string dbQuery = @" + ALTER TABLE dbo." + table + @" + ALTER COLUMN " + column + @" varchar(max) COLLATE " + newCollation; + return dbQuery; + } + #endregion + } +} diff --git a/src/Service.Tests/SqlTests/GraphQLCollationTests/MySqlGraphQLCollationTests.cs b/src/Service.Tests/SqlTests/GraphQLCollationTests/MySqlGraphQLCollationTests.cs new file mode 100644 index 0000000000..380ebac321 --- /dev/null +++ b/src/Service.Tests/SqlTests/GraphQLCollationTests/MySqlGraphQLCollationTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Azure.DataApiBuilder.Service.Tests.SqlTests.GraphQLCollationTests +{ + + [TestClass, TestCategory(TestCategory.MYSQL)] + public class MySqlGraphQLCollationTests : GraphQLCollationTestBase + { + //Collation setting for database + private const string DEFAULT_COLLATION = "utf8mb4_0900_ai_ci"; + private const string CASE_SENSITIVE_COLLATION = "utf8mb4_0900_as_cs"; + + /// + /// Set the database engine for the tests + /// + [ClassInitialize] + public static async Task SetupAsync(TestContext context) + { + DatabaseEngine = TestCategory.MYSQL; + await InitializeTestFixture(); + } + + #region Tests + /// + /// MySql Collation Tests to ensure that GraphQL is working properly when there is a change in case sensitivity on the database + /// + [DataTestMethod] + [DataRow("comics", "title", @"SELECT COALESCE(JSON_ARRAYAGG(JSON_OBJECT('title', `subq1`.`title`)), '[]') AS `data` FROM ( SELECT `table0`.`title` AS `title` FROM `comics` AS `table0` WHERE 1 = 1 ORDER BY `table0`.`title` ASC LIMIT 100 ) AS `subq1`")] + [DataRow("authors", "name", @"SELECT COALESCE(JSON_ARRAYAGG(JSON_OBJECT('name', `subq1`.`name`)), '[]') AS `data` FROM ( SELECT `table0`.`name` AS `name` FROM `authors` AS `table0` WHERE 1 = 1 ORDER BY `table0`.`name` ASC LIMIT 100 ) AS `subq1`")] + [DataRow("fungi", "habitat", @"SELECT COALESCE(JSON_ARRAYAGG(JSON_OBJECT('habitat', `subq1`.`habitat`)), '[]') AS `data` FROM ( SELECT `table0`.`habitat` AS `habitat` FROM `fungi` AS `table0` WHERE 1 = 1 ORDER BY `table0`.`habitat` ASC LIMIT 100 ) AS `subq1`")] + + public async Task MySqlCaseSensitiveResultQuery(string objectType, string fieldName, string dbQuery) + { + string defaultCollationQuery = MySqlCollationQuery(objectType, fieldName, DEFAULT_COLLATION); + string newCollationQuery = MySqlCollationQuery(objectType, fieldName, CASE_SENSITIVE_COLLATION); + await TestQueryingWithCaseSensitiveCollation(objectType, fieldName, dbQuery, defaultCollationQuery, newCollationQuery); + } + + /// + /// Creates collation query for a specific column on a table in the database for MySql + /// + private static string MySqlCollationQuery(string table, string column, string newCollation) + { + string dbQuery = @" + ALTER TABLE " + table + @" + MODIFY COLUMN " + column + @" text + CHARACTER SET utf8mb4 COLLATE " + newCollation; + return dbQuery; + } + #endregion + } +} diff --git a/src/Service.Tests/SqlTests/GraphQLCollationTests/PostgreSqlGraphQLCollationTests.cs b/src/Service.Tests/SqlTests/GraphQLCollationTests/PostgreSqlGraphQLCollationTests.cs new file mode 100644 index 0000000000..80079e2cdb --- /dev/null +++ b/src/Service.Tests/SqlTests/GraphQLCollationTests/PostgreSqlGraphQLCollationTests.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Azure.DataApiBuilder.Service.Tests.SqlTests.GraphQLCollationTests +{ + + [TestClass, TestCategory(TestCategory.POSTGRESQL)] + public class PostgreSqlGraphQLCollationTests : GraphQLCollationTestBase + { + //Collation setting for database + private const string DEFAULT_COLLATION = "pg_catalog.\"default\""; + private const string CASE_INSENSITIVE_COLLATION = "pg_catalog.\"en-US-u-va-posix-x-icu\""; + + /// + /// Set the database engine for tests + /// + [ClassInitialize] + public static async Task SetupAsync(TestContext context) + { + DatabaseEngine = TestCategory.POSTGRESQL; + await InitializeTestFixture(); + } + + #region Tests + /// + /// Postgres Collation Tests to ensure that GraphQL is working properly when there is a change in case sensitivity on the database + /// + [DataTestMethod] + [DataRow("comics", "title", @"SELECT json_agg(to_jsonb(table0)) FROM (SELECT title FROM comics ORDER BY title asc) as table0")] + [DataRow("authors", "name", @"SELECT json_agg(to_jsonb(table0)) FROM (SELECT name FROM authors ORDER BY name asc) as table0")] + [DataRow("fungi", "habitat", @"SELECT json_agg(to_jsonb(table0)) FROM (SELECT habitat FROM fungi ORDER BY habitat asc) as table0")] + public async Task PostgresCaseSensitiveResultQuery(string objectType, string fieldName, string dbQuery) + { + string defaultCollationQuery = PostgresCollationQuery(objectType, fieldName, DEFAULT_COLLATION); + string newCollationQuery = PostgresCollationQuery(objectType, fieldName, CASE_INSENSITIVE_COLLATION); + await TestQueryingWithCaseSensitiveCollation(objectType, fieldName, dbQuery, defaultCollationQuery, newCollationQuery); + } + + /// + /// Creates collation query for a specific column on a table in the database for Postgres + /// + private static string PostgresCollationQuery(string table, string column, string newCollation) + { + string dbQuery = @" + ALTER TABLE " + table + @" + ALTER COLUMN " + column + @" TYPE text + COLLATE " + newCollation; + return dbQuery; + } + #endregion + } +}