using NUnit.Framework; using Strata.SqlTools.Breakdowns.SqlServer; using Strata.SqlTools.Builders.LinqToSql; using Strata.SqlTools.Converters.LinqToSql; using PostgreSqlBreakdown = Strata.SqlTools.Breakdowns.PostgreSql.QueryBreakdown; using SnowflakeBreakdown = Strata.SqlTools.Breakdowns.Snowflake.QueryBreakdown; namespace Strata.SqlTools.LinqToSql.Tests; [TestFixture] public class ReverseConverterTests { #region SQL Server to LINQ Conversion Tests [Test] public void ToLinqQueryBreakdown_FromSqlServer_PreservesAllClauses() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id, Name, Email"; sqlServerBreakdown.FromClause.Clause = "Users"; sqlServerBreakdown.WhereClause.Clause = "IsActive = 1"; sqlServerBreakdown.OrderByClause.Clause = "Name ASC"; // Act var linqBreakdown = sqlServerBreakdown.ToLinqQueryBreakdown(); // Assert Assert.That(linqBreakdown, Is.Not.Null); Assert.Multiple(() => { Assert.That(linqBreakdown.SelectClause.Clause, Contains.Substring("Id")); Assert.That(linqBreakdown.FromClause.Clause, Is.EqualTo("Users")); Assert.That(linqBreakdown.WhereClause.Clause, Is.EqualTo("IsActive = 1")); Assert.That(linqBreakdown.OrderByClause.Clause, Is.EqualTo("Name ASC")); }); } [Test] public void ToLinqQueryBreakdown_FromSqlServer_WithGroupBy_PreservesGroupByAndHaving() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Department, COUNT(*) as EmployeeCount"; sqlServerBreakdown.FromClause.Clause = "Employees"; sqlServerBreakdown.GroupByClause.Clause = "Department"; sqlServerBreakdown.HavingClause.Clause = "COUNT(*) > 5"; // Act var linqBreakdown = sqlServerBreakdown.ToLinqQueryBreakdown(); Assert.Multiple(() => { // Assert Assert.That(linqBreakdown.GroupByClause.Clause, Is.EqualTo("Department")); Assert.That(linqBreakdown.HavingClause.Clause, Is.EqualTo("COUNT(*) > 5")); }); } [Test] public void ToLinqQueryBreakdown_FromSqlServer_WithNullInput_ThrowsArgumentNullException() { // Arrange QueryBreakdown? sqlServerBreakdown = null; // Act & Assert #pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => sqlServerBreakdown.ToLinqQueryBreakdown()); #pragma warning restore CS8604 // Possible null reference argument. } #endregion #region PostgreSQL to LINQ Conversion Tests [Test] public void ToLinqQueryBreakdown_FromPostgreSQL_PreservesAllClauses() { // Arrange var pgBreakdown = new PostgreSqlBreakdown(); pgBreakdown.SelectClause.Clause = "user_id, user_name"; pgBreakdown.FromClause.Clause = "users"; pgBreakdown.WhereClause.Clause = "is_active = true"; // Act var linqBreakdown = pgBreakdown.ToLinqQueryBreakdown(); // Assert Assert.That(linqBreakdown, Is.Not.Null); Assert.Multiple(() => { Assert.That(linqBreakdown.SelectClause.Clause, Contains.Substring("user_id")); Assert.That(linqBreakdown.FromClause.Clause, Is.EqualTo("users")); Assert.That(linqBreakdown.WhereClause.Clause, Is.EqualTo("is_active = true")); }); } [Test] public void ToLinqQueryBreakdown_FromPostgreSQL_WithNullInput_ThrowsArgumentNullException() { // Arrange PostgreSqlBreakdown? pgBreakdown = null; // Act & Assert #pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => pgBreakdown.ToLinqQueryBreakdown()); #pragma warning restore CS8604 // Possible null reference argument. } #endregion #region Snowflake to LINQ Conversion Tests [Test] public void ToLinqQueryBreakdown_FromSnowflake_PreservesAllClauses() { // Arrange var sfBreakdown = new SnowflakeBreakdown(); sfBreakdown.SelectClause.Clause = "USER_ID, USER_NAME"; sfBreakdown.FromClause.Clause = "USERS"; sfBreakdown.WhereClause.Clause = "IS_ACTIVE = TRUE"; // Act var linqBreakdown = sfBreakdown.ToLinqQueryBreakdown(); // Assert Assert.That(linqBreakdown, Is.Not.Null); Assert.Multiple(() => { Assert.That(linqBreakdown.SelectClause.Clause, Contains.Substring("USER_ID")); Assert.That(linqBreakdown.FromClause.Clause, Is.EqualTo("USERS")); Assert.That(linqBreakdown.WhereClause.Clause, Is.EqualTo("IS_ACTIVE = TRUE")); }); } [Test] public void ToLinqQueryBreakdown_FromSnowflake_WithNullInput_ThrowsArgumentNullException() { // Arrange SnowflakeBreakdown? sfBreakdown = null; // Act & Assert #pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => sfBreakdown.ToLinqQueryBreakdown()); #pragma warning restore CS8604 // Possible null reference argument. } #endregion #region Dialect-to-Dialect Conversion Tests [Test] public void ConvertToDialect_SqlServerToPostgreSQL_ReturnsPostgreSQLBreakdown() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id, Name"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var result = sqlServerBreakdown.ConvertToDialect("postgresql"); // Assert Assert.That(result, Is.TypeOf()); } [Test] public void ConvertToDialect_SqlServerToSnowflake_ReturnsSnowflakeBreakdown() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id, Name"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var result = sqlServerBreakdown.ConvertToDialect("snowflake"); // Assert Assert.That(result, Is.TypeOf()); } [Test] public void ConvertToDialect_SqlServerToLINQ_ReturnsLinqQueryBreakdown() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id, Name"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var result = sqlServerBreakdown.ConvertToDialect("linq"); // Assert Assert.That(result, Is.TypeOf()); } [Test] public void ConvertToDialect_SqlServerToSqlServer_ReturnsSameSqlServerBreakdown() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id, Name"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var result = sqlServerBreakdown.ConvertToDialect("sqlserver"); // Assert Assert.That(result, Is.SameAs(sqlServerBreakdown)); } [Test] public void ConvertToDialect_PostgresToSqlServer_ReturnsSqlServerBreakdown() { // Arrange var pgBreakdown = new PostgreSqlBreakdown(); pgBreakdown.SelectClause.Clause = "id, name"; pgBreakdown.FromClause.Clause = "users"; // Act var result = pgBreakdown.ConvertToDialect("sqlserver"); // Assert Assert.That(result, Is.TypeOf()); } [Test] public void ConvertToDialect_SnowflakeToPostgreSQL_ReturnsPostgresBreakdown() { // Arrange var sfBreakdown = new SnowflakeBreakdown(); sfBreakdown.SelectClause.Clause = "ID, NAME"; sfBreakdown.FromClause.Clause = "USERS"; // Act var result = sfBreakdown.ConvertToDialect("postgres"); // Assert Assert.That(result, Is.TypeOf()); } [Test] public void ConvertToDialect_WithUnknownDialect_ThrowsArgumentException() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act & Assert Assert.Throws(() => sqlServerBreakdown.ConvertToDialect("unknown")); } [Test] public void ConvertToDialect_IsCaseInsensitive() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var result1 = sqlServerBreakdown.ConvertToDialect("PostgreSQL"); var result2 = sqlServerBreakdown.ConvertToDialect("POSTGRESQL"); var result3 = sqlServerBreakdown.ConvertToDialect("postgresql"); Assert.Multiple(() => { // Assert Assert.That(result1, Is.TypeOf()); Assert.That(result2, Is.TypeOf()); Assert.That(result3, Is.TypeOf()); }); } #endregion #region Round-Trip Conversion Tests [Test] public void RoundTrip_SqlServer_ToLinq_ToPostgres_ToLinq_ToSqlServer_PreservesData() { // Arrange var original = LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Where("IsActive = true") .OrderByAscending("Name") .Build(); // Act - Convert: LINQ -> SqlServer -> LINQ -> PostgreSQL -> LINQ -> SqlServer var toSqlServer = original.ConvertToSqlServerBreakdown() as QueryBreakdown; var backToLinq = toSqlServer!.ToLinqQueryBreakdown(); var toPostgres = backToLinq.ConvertToPostgreSqlBreakdown() as PostgreSqlBreakdown; var backToLinq2 = toPostgres!.ToLinqQueryBreakdown(); var finalToSqlServer = backToLinq2.ConvertToSqlServerBreakdown(); Assert.Multiple(() => { // Assert - Check that clauses are preserved Assert.That(backToLinq.SelectClause.Clause, Contains.Substring("Id")); Assert.That(backToLinq.FromClause.Clause, Is.EqualTo("Users")); Assert.That(backToLinq.WhereClause.Clause, Is.EqualTo("IsActive = true")); }); } #endregion #region Null Handling Tests [Test] public void ToLinqQueryBreakdown_WithNullPostgreSQL_ThrowsArgumentNullException() { // Arrange PostgreSqlBreakdown? pgBreakdown = null; // Act & Assert #pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => pgBreakdown.ToLinqQueryBreakdown()); #pragma warning restore CS8604 // Possible null reference argument. } [Test] public void ConvertToDialect_WithNullBreakdown_ThrowsArgumentNullException() { // Arrange QueryBreakdown? sqlServerBreakdown = null; // Act & Assert #pragma warning disable CS8604 // Possible null reference argument. Assert.Throws(() => sqlServerBreakdown.ConvertToDialect("postgresql")); #pragma warning restore CS8604 // Possible null reference argument. } #endregion #region Alternative Dialect Names Tests [Test] public void ConvertToDialect_AcceptsAlternativeDialectNames() { // Arrange var sqlServerBreakdown = new QueryBreakdown(); sqlServerBreakdown.SelectClause.Clause = "Id"; sqlServerBreakdown.FromClause.Clause = "Users"; // Act var resultPostgres1 = sqlServerBreakdown.ConvertToDialect("postgres"); var resultPostgres2 = sqlServerBreakdown.ConvertToDialect("postgresql"); var resultSqlServer1 = sqlServerBreakdown.ConvertToDialect("sqlserver"); var resultSqlServer2 = sqlServerBreakdown.ConvertToDialect("sql_server"); Assert.Multiple(() => { // Assert Assert.That(resultPostgres1, Is.TypeOf()); Assert.That(resultPostgres2, Is.TypeOf()); Assert.That(resultSqlServer1, Is.SameAs(sqlServerBreakdown)); Assert.That(resultSqlServer2, Is.SameAs(sqlServerBreakdown)); }); } #endregion }