Skip to content

Commit e650a08

Browse files
committed
More tests
1 parent 114c78b commit e650a08

File tree

8 files changed

+134
-8
lines changed

8 files changed

+134
-8
lines changed

Akade.IndexedSet.Tests/FullTextIndices.cs

+38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Akade.IndexedSet.Tests.TestUtilities;
22
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System.Diagnostics.CodeAnalysis;
34

45
namespace Akade.IndexedSet.Tests;
56

@@ -100,4 +101,41 @@ public void TryGetSingle()
100101
Assert.IsFalse(_indexedSet.TryGetSingle(x => x.Name, "Elephant", out Animal? animal2));
101102
Assert.IsNull(animal2);
102103
}
104+
105+
[TestMethod]
106+
[Experimental(Experiments.TextSearchImprovements)]
107+
public void Retrieval_via_multi_key_retrieves_correct_items()
108+
{
109+
static IEnumerable<string> Multikeys(Animal d) => new[] { d.Name, d.Category };
110+
111+
var data = new Animal[] {
112+
_bonobo,
113+
_booby,
114+
_boomslang,
115+
_borador,
116+
_tiger,
117+
_tarantula,
118+
_tapir,
119+
_penguin,
120+
_panther,
121+
_pangolin,
122+
_parrot,
123+
};
124+
125+
_indexedSet = data.ToIndexedSet()
126+
.WithFullTextIndex(Multikeys)
127+
.Build();
128+
129+
// only reptile & spider
130+
_indexedSet.AssertSingleItem(Multikeys, _boomslang);
131+
_indexedSet.AssertSingleItem(Multikeys, _tarantula);
132+
133+
CollectionAssert.AreEquivalent(_indexedSet.Where(Multikeys, "Bird").ToArray(), new[] { _booby, _penguin, _parrot });
134+
135+
CollectionAssert.AreEquivalent(_indexedSet.Contains(Multikeys, "ird").ToArray(), new[] { _booby, _penguin, _parrot });
136+
CollectionAssert.AreEquivalent(_indexedSet.FuzzyContains(Multikeys, "ard", 1).ToArray(), new[] { _borador, _booby, _penguin, _parrot, _tarantula });
137+
138+
CollectionAssert.AreEquivalent(_indexedSet.StartsWith(Multikeys, "Bir").ToArray(), new[] { _booby, _penguin, _parrot });
139+
CollectionAssert.AreEquivalent(_indexedSet.FuzzyStartsWith(Multikeys, "Lir", 1).ToArray(), new[] { _booby, _penguin, _parrot });
140+
}
103141
}

Akade.IndexedSet.Tests/PrefixIndices.cs

+34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Akade.IndexedSet.Tests.TestUtilities;
22
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System.Diagnostics.CodeAnalysis;
34

45
namespace Akade.IndexedSet.Tests;
56

@@ -87,4 +88,37 @@ public void TryGetSingle()
8788
Assert.IsFalse(_indexedSet.TryGetSingle(x => x.Name, "Elephant", out Animal? animal2));
8889
Assert.IsNull(animal2);
8990
}
91+
92+
[TestMethod]
93+
[Experimental(Experiments.TextSearchImprovements)]
94+
public void Retrieval_via_multi_key_retrieves_correct_items()
95+
{
96+
static IEnumerable<string> Multikeys(Animal d) => new[] { d.Name, d.Category };
97+
98+
var data = new Animal[] {
99+
_bonobo,
100+
_booby,
101+
_boomslang,
102+
_borador,
103+
_tiger,
104+
_tarantula,
105+
_tapir,
106+
_penguin,
107+
_panther,
108+
_pangolin,
109+
_parrot,
110+
};
111+
112+
_indexedSet = data.ToIndexedSet()
113+
.WithPrefixIndex(Multikeys)
114+
.Build();
115+
116+
// only reptile & spider
117+
_indexedSet.AssertSingleItem(Multikeys, _boomslang);
118+
_indexedSet.AssertSingleItem(Multikeys, _tarantula);
119+
120+
CollectionAssert.AreEquivalent(_indexedSet.Where(Multikeys, "Bird").ToArray(), new[] { _booby, _penguin, _parrot });
121+
CollectionAssert.AreEquivalent(_indexedSet.StartsWith(Multikeys, "Bir").ToArray(), new[] { _booby, _penguin, _parrot });
122+
CollectionAssert.AreEquivalent(_indexedSet.FuzzyStartsWith(Multikeys, "Lir", 1).ToArray(), new[] { _booby, _penguin, _parrot });
123+
}
90124
}

Akade.IndexedSet.Tests/RangeIndices.cs

+22
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,26 @@ public void TryGetSingle_on_secondary_key()
204204
Assert.IsTrue(_indexedSet.TryGetSingle(x => x.IntProperty, 11, out TestData? data3));
205205
Assert.IsNotNull(data3);
206206
}
207+
208+
[TestMethod]
209+
public void Retrieval_via_multi_key_retrieves_correct_items()
210+
{
211+
// duplication of primary key is intentional => tests if the range index correctly returns & counts distinct elements
212+
static IEnumerable<int> Multikeys(TestData x) => new[] { x.PrimaryKey, x.PrimaryKey, x.PrimaryKey + 1 };
213+
214+
TestData[] data = new[] { _a, _b, _c };
215+
_indexedSet = data.ToIndexedSet(x => x.PrimaryKey)
216+
.WithRangeIndex(Multikeys)
217+
.Build();
218+
219+
220+
CollectionAssert.AreEqual(new[] { _a, _b, _c }, _indexedSet.Range(Multikeys, _a.PrimaryKey, _c.PrimaryKey, inclusiveEnd: true).ToArray());
221+
222+
// matches _a
223+
_ = _indexedSet.TryGetSingle(Multikeys, _a.PrimaryKey, out TestData? data1);
224+
Assert.AreEqual(_a, data1);
225+
226+
// matches _a & _b
227+
Assert.IsFalse(_indexedSet.TryGetSingle(Multikeys, _b.PrimaryKey, out _));
228+
}
207229
}

Akade.IndexedSet.Tests/TestUtilities/IndexAssert.cs

+15
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ public static void AssertSingleItem<TElement, TIndexKey>(this IndexedSet<TElemen
2323
Assert.AreEqual(testData, accessViaWhere);
2424
}
2525

26+
public static void AssertSingleItem<TElement, TIndexKey>(this IndexedSet<TElement> indexedSet, Func<TElement, IEnumerable<TIndexKey>> indexAccessor, TElement testData, [CallerArgumentExpression("indexAccessor")] string? indexName = null)
27+
where TIndexKey : notnull
28+
{
29+
Assert.IsNotNull(indexName);
30+
31+
foreach (TIndexKey indexKey in indexAccessor(testData))
32+
{
33+
TElement accessViaSingle = indexedSet.Single(indexAccessor, indexKey, indexName);
34+
TElement accessViaWhere = indexedSet.Where(indexAccessor, indexKey, indexName).Single();
35+
36+
Assert.AreEqual(testData, accessViaSingle);
37+
Assert.AreEqual(testData, accessViaWhere);
38+
}
39+
}
40+
2641
public static void AssertMultipleItems<TElement, TIndexKey>(this IndexedSet<TElement> indexedSet, Func<TElement, TIndexKey> indexAccessor, [CallerArgumentExpression("indexAccessor")] string? indexName = null, bool requireOrder = false, params TElement[] expectedElements)
2742
where TIndexKey : notnull
2843
{

Akade.IndexedSet.Tests/UniqueIndices.cs

+15
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,19 @@ public void TryGetSingle_on_secondary_key()
9191
Assert.IsTrue(_indexedSet.TryGetSingle(x => x.IntProperty, 10, out TestData? data2));
9292
Assert.IsNotNull(data2);
9393
}
94+
95+
[TestMethod]
96+
public void Retrieval_via_multi_key_retrieves_correct_items()
97+
{
98+
static IEnumerable<int> Multikeys(TestData d) => new[] { d.PrimaryKey, d.IntProperty };
99+
100+
TestData[] data = new[] { _a, _b, _c };
101+
_indexedSet = data.ToIndexedSet(x => x.PrimaryKey)
102+
.WithUniqueIndex(Multikeys)
103+
.Build();
104+
105+
_indexedSet.AssertSingleItem(Multikeys, _a);
106+
_indexedSet.AssertSingleItem(Multikeys, _b);
107+
_indexedSet.AssertSingleItem(Multikeys, _c);
108+
}
94109
}

Akade.IndexedSet/Experiments.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace Akade.IndexedSet;
1+
using System.Globalization;
2+
3+
namespace Akade.IndexedSet;
24

35
#if !NET8_0_OR_GREATER
46
/// <summary>
@@ -33,7 +35,7 @@ internal ExperimentalAttribute(string diagnosticsId)
3335
/// <inheritdoc/>
3436
public override string ToString()
3537
{
36-
return UrlFormat is null ? _diagnosticsId : string.Format(UrlFormat, _diagnosticsId);
38+
return UrlFormat is null ? _diagnosticsId : string.Format(CultureInfo.InvariantCulture, UrlFormat, _diagnosticsId);
3739
}
3840

3941
/// <summary>

Akade.IndexedSet/IndexedSet.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ public IEnumerable<TElement> Contains(Func<TElement, string> indexAccessor, Read
700700
/// <param name="indexName">The name of the index. Usually, you should not specify this as the expression in <paramref name="indexAccessor"/> is automatically passed by the compiler.</param>
701701
[ReadAccess]
702702
[Experimental(Experiments.TextSearchImprovements, UrlFormat = Experiments.UrlTemplate)]
703-
public IEnumerable<TElement> Contains(Func<TElement, IEnumerator<string>> indexAccessor, ReadOnlySpan<char> infix, [CallerArgumentExpression("indexAccessor")] string? indexName = null)
703+
public IEnumerable<TElement> Contains(Func<TElement, IEnumerable<string>> indexAccessor, ReadOnlySpan<char> infix, [CallerArgumentExpression("indexAccessor")] string? indexName = null)
704704
{
705705
TypedIndex<TElement, string> typedIndex = GetIndex<string>(indexName);
706706
return typedIndex.Contains(infix);
@@ -731,7 +731,7 @@ public IEnumerable<TElement> FuzzyContains(Func<TElement, string> indexAccessor,
731731
/// <param name="indexName">The name of the index. Usually, you should not specify this as the expression in <paramref name="indexAccessor"/> is automatically passed by the compiler.</param>
732732
[ReadAccess]
733733
[Experimental(Experiments.TextSearchImprovements, UrlFormat = Experiments.UrlTemplate)]
734-
public IEnumerable<TElement> FuzzyContains(Func<TElement, IEnumerator<string>> indexAccessor, ReadOnlySpan<char> infix, int maxDistance, [CallerArgumentExpression("indexAccessor")] string? indexName = null)
734+
public IEnumerable<TElement> FuzzyContains(Func<TElement, IEnumerable<string>> indexAccessor, ReadOnlySpan<char> infix, int maxDistance, [CallerArgumentExpression("indexAccessor")] string? indexName = null)
735735
{
736736
TypedIndex<TElement, string> typedIndex = GetIndex<string>(indexName);
737737
return typedIndex.FuzzyContains(infix, maxDistance);

Akade.IndexedSet/PublicAPI/PublicAPI.Shipped.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ override Akade.IndexedSet.IndexedSetBuilder<TPrimaryKey, TElement>.WithRangeInde
120120
override Akade.IndexedSet.IndexedSetBuilder<TPrimaryKey, TElement>.WithUniqueIndex<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! keyAccessor, string? indexName = null) -> Akade.IndexedSet.IndexedSetBuilder<TPrimaryKey, TElement>!
121121
virtual Akade.IndexedSet.IndexedSetBuilder<TElement>.WithFullTextIndex(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! keyAccessor, string? indexName = null) -> Akade.IndexedSet.IndexedSetBuilder<TElement>!
122122
virtual Akade.IndexedSet.IndexedSetBuilder<TElement>.WithRangeIndex<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! keyAccessor, string? indexName = null) -> Akade.IndexedSet.IndexedSetBuilder<TElement>!
123-
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.Contains(System.Func<TElement, System.Collections.Generic.IEnumerator<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
124-
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.FuzzyContains(System.Func<TElement, System.Collections.Generic.IEnumerator<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
123+
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.Contains(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
124+
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.FuzzyContains(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
125125
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.FuzzyStartsWith(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> prefix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
126126
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.GreaterThan<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, TIndexKey value, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
127127
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.GreaterThanOrEqual<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, TIndexKey value, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
@@ -133,8 +133,8 @@ Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.Min<TIndexKey>(Syste
133133
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.MinBy<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
134134
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.Range<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, TIndexKey start, TIndexKey end, bool inclusiveStart = true, bool inclusiveEnd = false, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
135135
Akade.IndexedSet.Concurrency.ConcurrentIndexedSet<TElement>.StartsWith(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> prefix, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
136-
Akade.IndexedSet.IndexedSet<TElement>.Contains(System.Func<TElement, System.Collections.Generic.IEnumerator<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
137-
Akade.IndexedSet.IndexedSet<TElement>.FuzzyContains(System.Func<TElement, System.Collections.Generic.IEnumerator<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
136+
Akade.IndexedSet.IndexedSet<TElement>.Contains(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
137+
Akade.IndexedSet.IndexedSet<TElement>.FuzzyContains(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> infix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
138138
Akade.IndexedSet.IndexedSet<TElement>.FuzzyStartsWith(System.Func<TElement, System.Collections.Generic.IEnumerable<string!>!>! indexAccessor, System.ReadOnlySpan<char> prefix, int maxDistance, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
139139
Akade.IndexedSet.IndexedSet<TElement>.GreaterThan<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, TIndexKey value, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!
140140
Akade.IndexedSet.IndexedSet<TElement>.GreaterThanOrEqual<TIndexKey>(System.Func<TElement, System.Collections.Generic.IEnumerable<TIndexKey>!>! indexAccessor, TIndexKey value, string? indexName = null) -> System.Collections.Generic.IEnumerable<TElement>!

0 commit comments

Comments
 (0)