Initialize CBDD solution and add a .NET-focused gitignore for generated artifacts.

This commit is contained in:
Joseph Doherty
2026-02-20 12:54:07 -05:00
commit b8ed5ec500
214 changed files with 101452 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
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();
}
}
}