using ZB.MOM.WW.CBDD.Core; using ZB.MOM.WW.CBDD.Core.Storage; using ZB.MOM.WW.CBDD.Core.Collections; using ZB.MOM.WW.CBDD.Core.Indexing; using ZB.MOM.WW.CBDD.Bson; using Xunit; using System; using System.IO; using System.Linq; using System.Collections.Generic; using ZB.MOM.WW.CBDD.Shared; namespace ZB.MOM.WW.CBDD.Tests { public class LinqTests : IDisposable { private readonly string _testFile; private readonly Shared.TestDbContext _db; public LinqTests() { _testFile = Path.Combine(Path.GetTempPath(), $"linq_tests_{Guid.NewGuid()}.db"); if (File.Exists(_testFile)) File.Delete(_testFile); var wal = Path.ChangeExtension(_testFile, ".wal"); if (File.Exists(wal)) File.Delete(wal); _db = new Shared.TestDbContext(_testFile); // Seed Data _db.Users.Insert(new User { Name = "Alice", Age = 30 }); _db.Users.Insert(new User { Name = "Bob", Age = 25 }); _db.Users.Insert(new User { Name = "Charlie", Age = 35 }); _db.Users.Insert(new User { Name = "Dave", Age = 20 }); _db.Users.Insert(new User { Name = "Eve", Age = 40 }); _db.SaveChanges(); } public void Dispose() { _db.Dispose(); if (File.Exists(_testFile)) File.Delete(_testFile); var wal = Path.ChangeExtension(_testFile, ".wal"); if (File.Exists(wal)) File.Delete(wal); } [Fact] public void Where_FiltersDocuments() { var query = _db.Users.AsQueryable().Where(x => x.Age > 28); var results = query.ToList(); results.Count.ShouldBe(3); // Alice(30), Charlie(35), Eve(40) results.ShouldNotContain(d => d.Name == "Bob"); } [Fact] public void OrderBy_SortsDocuments() { var results = _db.Users.AsQueryable().OrderBy(x => x.Age).ToList(); results.Count.ShouldBe(5); results[0].Name.ShouldBe("Dave"); // 20 results[1].Name.ShouldBe("Bob"); // 25 results.Last().Name.ShouldBe("Eve"); // 40 } [Fact] public void SkipTake_Pagination() { var results = _db.Users.AsQueryable() .OrderBy(x => x.Age) .Skip(1) .Take(2) .ToList(); results.Count.ShouldBe(2); results[0].Name.ShouldBe("Bob"); // 25 (Skipped Dave) results[1].Name.ShouldBe("Alice"); // 30 } [Fact] public void Select_Projections() { var names = _db.Users.AsQueryable() .Where(x => x.Age < 30) .OrderBy(x => x.Age) .Select(x => x.Name) .ToList(); names.Count.ShouldBe(2); names[0].ShouldBe("Dave"); names[1].ShouldBe("Bob"); } [Fact] public void IndexedWhere_UsedIndex() { // Create index on Age _db.Users.EnsureIndex(x => x.Age, "idx_age", false); var query = _db.Users.AsQueryable().Where(x => x.Age > 25); var results = query.ToList(); results.Count.ShouldBe(3); // Alice(30), Charlie(35), Eve(40) results.ShouldNotContain(d => d.Name == "Bob"); // Age 25 (filtered out by strict >) results.ShouldNotContain(d => d.Name == "Dave"); // Age 20 } [Fact] public void StartsWith_UsedIndex() { // Create index on Name _db.Users.EnsureIndex(x => x.Name!, "idx_name", false); // StartsWith "Cha" -> Should find "Charlie" var query = _db.Users.AsQueryable().Where(x => x.Name!.StartsWith("Cha")); var results = query.ToList(); results.Count().ShouldBe(1); results[0].Name.ShouldBe("Charlie"); } [Fact] public void Between_UsedIndex() { // Create index on Age _db.Users.EnsureIndex(x => x.Age, "idx_age_between", false); // Age >= 22 && Age <= 32 // Alice(30), Bob(25) -> Should be found. // Dave(20), Charlie(35), Eve(40) -> excluded. var query = _db.Users.AsQueryable().Where(x => x.Age >= 22 && x.Age <= 32); var results = query.ToList(); results.Count.ShouldBe(2); results.ShouldContain(x => x.Name == "Alice"); results.ShouldContain(x => x.Name == "Bob"); } } }