Files
CBDD/tests/CBDD.Tests/IndexOptimizationTests.cs

137 lines
4.5 KiB
C#
Executable File

using Xunit;
using ZB.MOM.WW.CBDD.Core.Query;
using ZB.MOM.WW.CBDD.Core.Indexing;
using System.Linq.Expressions;
using System.Collections.Generic;
using System;
namespace ZB.MOM.WW.CBDD.Tests
{
public class IndexOptimizationTests
{
public class TestEntity
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int Age { get; set; }
}
[Fact]
public void Optimizer_Identifies_Equality()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_age", PropertyPaths = ["Age"] }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Age == 30;
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldNotBeNull();
result.IndexName.ShouldBe("idx_age");
result.MinValue.ShouldBe(30);
result.MaxValue.ShouldBe(30);
result.IsRange.ShouldBeFalse();
}
[Fact]
public void Optimizer_Identifies_Range_GreaterThan()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_age", PropertyPaths = ["Age"] }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Age > 25;
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldNotBeNull();
result.IndexName.ShouldBe("idx_age");
result.MinValue.ShouldBe(25);
result.MaxValue.ShouldBeNull();
result.IsRange.ShouldBeTrue();
}
[Fact]
public void Optimizer_Identifies_Range_LessThan()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_age", PropertyPaths = ["Age"] }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Age < 50;
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldNotBeNull();
result.IndexName.ShouldBe("idx_age");
result.MinValue.ShouldBeNull();
result.MaxValue.ShouldBe(50);
result.IsRange.ShouldBeTrue();
}
[Fact]
public void Optimizer_Identifies_Range_Between_Simulated()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_age", PropertyPaths = ["Age"] }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Age > 20 && x.Age < 40;
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldNotBeNull();
result.IndexName.ShouldBe("idx_age");
result.MinValue.ShouldBe(20);
result.MaxValue.ShouldBe(40);
result.IsRange.ShouldBeTrue();
}
[Fact]
public void Optimizer_Identifies_StartsWith()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_name", PropertyPaths = ["Name"], Type = IndexType.BTree }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Name.StartsWith("Ali");
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldNotBeNull();
result.IndexName.ShouldBe("idx_name");
result.MinValue.ShouldBe("Ali");
// "Ali" + next char -> "Alj"
result.MaxValue.ShouldBe("Alj");
result.IsRange.ShouldBeTrue();
}
[Fact]
public void Optimizer_Ignores_NonIndexed_Fields()
{
var indexes = new List<CollectionIndexInfo>
{
new CollectionIndexInfo { Name = "idx_age", PropertyPaths = ["Age"] }
};
Expression<Func<TestEntity, bool>> predicate = x => x.Name == "Alice"; // Name is not indexed
var model = new QueryModel { WhereClause = predicate };
var result = IndexOptimizer.TryOptimize<TestEntity>(model, indexes);
result.ShouldBeNull();
}
}
}