using NUnit.Framework; using Strata.SqlTools.Analyzers.LinqToSql; using Strata.SqlTools.Builders.LinqToSql; namespace Strata.SqlTools.LinqToSql.Tests; [TestFixture] public class QueryCollectionAnalyzerTests { #region Basic Analysis Tests [Test] public void Analyze_WithEmptyCollection_ReturnsZeroStatistics() { // Arrange var queries = new List(); var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TotalQueries, Is.EqualTo(0)); Assert.That(stats.UniqueQueries, Is.EqualTo(0)); Assert.That(stats.DuplicateQueries, Is.Empty); } [Test] public void Analyze_WithSingleQuery_ReturnsCorrectStatistics() { // Arrange var queries = new List { LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Where("IsActive = true") .Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TotalQueries, Is.EqualTo(1)); Assert.That(stats.UniqueQueries, Is.EqualTo(1)); Assert.That(stats.DuplicateQueries, Is.Empty); } [Test] public void Analyze_WithIdenticalQueries_IdentifiesDuplicates() { // Arrange var query1 = LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Build(); var query2 = LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Build(); var query3 = LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Build(); var queries = new List { query1, query2, query3 }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TotalQueries, Is.EqualTo(3)); Assert.That(stats.UniqueQueries, Is.EqualTo(1)); Assert.That(stats.DuplicateQueries, Has.Count.EqualTo(2)); } #endregion #region Deduplication Rate Tests [Test] public void DeduplicationRate_WithAllUnique_ReturnsOne() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.DeduplicationRate, Is.EqualTo(1.0)); } [Test] public void DeduplicationRate_WithSomeDuplicates_ReturnsCorrectRatio() { // Arrange var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(); var queries = new List { query, LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), // Duplicate LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.DeduplicationRate, Is.EqualTo(2.0 / 3.0).Within(0.01)); } #endregion #region Query Characteristics Tests [Test] public void Analyze_CountsQueriesWithoutWhere() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Where("Amount > 100").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.QueriesWithoutWhere, Is.EqualTo(2)); } [Test] public void Analyze_CountsQueriesWithoutOrderBy() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").OrderByAscending("Name").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.QueriesWithoutOrderBy, Is.EqualTo(2)); } [Test] public void Analyze_CountsQueriesWithSelectAll() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Orders").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Products").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.QueriesWithSelectAll, Is.EqualTo(2)); } #endregion #region Table Usage Analysis Tests [Test] public void Analyze_AnalyzesTableUsageFrequency() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TableUsageFrequency["Users"], Is.EqualTo(3)); Assert.That(stats.TableUsageFrequency["Orders"], Is.EqualTo(1)); } [Test] public void Analyze_IgnoresNullTableNames() { // Arrange var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(); var queries = new List { query }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TableUsageFrequency.ContainsKey("Users"), Is.True); } #endregion #region Column Usage Analysis Tests [Test] public void Analyze_AnalyzesColumnSelectionFrequency() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name", "Email").FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.ColumnSelectionFrequency.ContainsKey("Id"), Is.True); Assert.That(stats.ColumnSelectionFrequency["Id"], Is.EqualTo(3)); Assert.That(stats.ColumnSelectionFrequency["Name"], Is.EqualTo(2)); Assert.That(stats.ColumnSelectionFrequency["Email"], Is.EqualTo(1)); } [Test] public void Analyze_IgnoresSelectAll_InColumnUsage() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.ColumnSelectionFrequency.ContainsKey("*"), Is.False); Assert.That(stats.ColumnSelectionFrequency["Id"], Is.EqualTo(1)); } #endregion #region Complexity Analysis Tests [Test] public void Analyze_CalculatesAverageComplexity() { // Arrange var simpleQuery = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(); var complexQuery = LinqQueryBreakdownBuilder .Create() .SelectColumns("Department", "COUNT(*)") .FromTable("Employees") .Where("Salary > 50000 AND Department IN ('IT', 'HR')") .GroupBy("Department") .Having("COUNT(*) > 5") .OrderByDescending("COUNT(*)") .Build(); var queries = new List { simpleQuery, complexQuery }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.AverageComplexity, Is.GreaterThan(0)); Assert.That(stats.AverageComplexity, Is.LessThanOrEqualTo(10)); } [Test] public void Analyze_CountsComplexQueries() { // Arrange var simpleQuery = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(); var complexQuery = LinqQueryBreakdownBuilder .Create() .SelectColumns("Dept", "COUNT(*)") .FromTable("Emp") .Where("Salary > 50000 AND Department IN ('IT', 'HR')") .GroupBy("Dept") .Having("COUNT(*) > 5") .Build(); var queries = new List { simpleQuery, complexQuery }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.ComplexQueriesCount, Is.GreaterThan(0)); } #endregion #region FindDuplicates Tests [Test] public void FindDuplicates_WithNoDuplicates_ReturnsEmptyList() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var duplicates = analyzer.FindDuplicates(); // Assert Assert.That(duplicates, Is.Empty); } [Test] public void FindDuplicates_WithDuplicates_ReturnsDuplicateQueries() { // Arrange var query = LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(); var queries = new List { query, LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var duplicates = analyzer.FindDuplicates(); // Assert Assert.That(duplicates, Has.Count.EqualTo(2)); } #endregion #region FindSimilarQueries Tests [Test] public void FindSimilarQueries_WithSimilarQueries_ReturnsSimilarPairs() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name", "Email").FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var similar = analyzer.FindSimilarQueries(0.5); // Lower threshold for testing // Assert Assert.That(similar.Count, Is.GreaterThan(0)); } [Test] public void FindSimilarQueries_SimilarityScoresBounded() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectColumns("Id").FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectColumns("Id", "Name").FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var similar = analyzer.FindSimilarQueries(0.5); // Assert foreach (var pair in similar) { Assert.That(pair.Similarity, Is.GreaterThanOrEqualTo(0.5)); Assert.That(pair.Similarity, Is.LessThan(1.0)); } } #endregion #region Report Generation Tests [Test] public void GetReport_IncludesBasicStatistics() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var report = analyzer.GetReport(); // Assert Assert.That(report, Contains.Substring("Query Collection Analysis Report")); Assert.That(report, Contains.Substring("Total Queries: 1")); Assert.That(report, Contains.Substring("Unique Queries: 1")); } [Test] public void GetReport_IncludesTableUsage() { // Arrange var queries = new List { LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Users").Build(), LinqQueryBreakdownBuilder.Create().SelectAll().FromTable("Orders").Build() }; var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var report = analyzer.GetReport(); // Assert Assert.That(report, Contains.Substring("Most Frequently Used Tables")); } #endregion #region Null Handling Tests [Test] public void Constructor_WithNullQueries_ThrowsArgumentNullException() { // Act & Assert Assert.Throws(() => new QueryCollectionAnalyzer(null!)); } #endregion #region Edge Cases [Test] public void Analyze_WithLargeCollection_PerformsAnalysis() { // Arrange var queries = new List(); for (int i = 0; i < 100; i++) { queries.Add(LinqQueryBreakdownBuilder .Create() .SelectColumns("Id", "Name") .FromTable("Users") .Build()); } var analyzer = QueryCollectionAnalyzer.Analyze(queries); // Act var stats = analyzer.Analyze(); // Assert Assert.That(stats.TotalQueries, Is.EqualTo(100)); Assert.That(stats.UniqueQueries, Is.EqualTo(1)); } #endregion }