Skip to content

Commit 144fe86

Browse files
authored
Add explicit test for hash collision handling. (#11)
1 parent 3ddcf84 commit 144fe86

4 files changed

Lines changed: 56 additions & 20 deletions

File tree

UnitTests/BadHashCode.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace UnitTests
2+
{
3+
struct BadHashCode
4+
{
5+
public int Value;
6+
7+
public override int GetHashCode() => 42;
8+
9+
public static implicit operator BadHashCode(int i) => new BadHashCode { Value = i };
10+
11+
public static implicit operator int(BadHashCode bhc) => bhc.Value;
12+
}
13+
}

UnitTests/CacheTableTestBase.cs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace UnitTests
1010
{
11-
public abstract class CacheTableTestBase<TCacheTable> where TCacheTable : ICacheTable<int, int>
11+
public abstract class CacheTableTestBase
1212
{
1313
protected ITestOutputHelper output;
1414

@@ -17,12 +17,12 @@ protected CacheTableTestBase(ITestOutputHelper output)
1717
this.output = output;
1818
}
1919

20-
protected abstract TCacheTable CreateTable(int numRows, int numColumns);
20+
protected abstract ICacheTable<TKey, TValue> CreateTable<TKey, TValue>(int numRows, int numColumns);
2121

2222
[Fact]
2323
public void SetAndTryGetValue()
2424
{
25-
var table = this.CreateTable(10, 4);
25+
var table = this.CreateTable<int, int>(10, 4);
2626
table[1] = 2;
2727
table.TryGetValue(1, out int val).Should().BeTrue();
2828
val.Should().Be(2);
@@ -31,23 +31,23 @@ public void SetAndTryGetValue()
3131
[Fact]
3232
public void TryGetNonExistentValue()
3333
{
34-
var table = this.CreateTable(10, 4);
34+
var table = this.CreateTable<int, int>(10, 4);
3535
table.TryGetValue(1, out int val).Should().BeFalse();
3636
val.Should().Be(default(int));
3737
}
3838

3939
[Fact]
4040
public void SetAndIndex()
4141
{
42-
var table = this.CreateTable(10, 4);
42+
var table = this.CreateTable<int, int>(10, 4);
4343
table[1] = 2;
4444
table[1].Should().Be(2);
4545
}
4646

4747
[Fact]
4848
public void Update()
4949
{
50-
var table = this.CreateTable(10, 4);
50+
var table = this.CreateTable<int, int>(10, 4);
5151

5252
for (int i = 0; i < 4; i++)
5353
{
@@ -72,7 +72,7 @@ public void Update()
7272
[Fact]
7373
public void IndexNonExistentKeyThrows()
7474
{
75-
var table = this.CreateTable(10, 4);
75+
var table = this.CreateTable<int, int>(10, 4);
7676
Action act = () => Console.WriteLine(table[0]);
7777
act.Should().Throw<KeyNotFoundException>()
7878
.WithMessage("No value found for 0");
@@ -81,7 +81,7 @@ public void IndexNonExistentKeyThrows()
8181
[Fact]
8282
public void ContainsKey()
8383
{
84-
var table = this.CreateTable(10, 4);
84+
var table = this.CreateTable<int, int>(10, 4);
8585
table.ContainsKey(0).Should().BeFalse();
8686
table[0] = 1;
8787
table.ContainsKey(0).Should().BeTrue();
@@ -90,7 +90,7 @@ public void ContainsKey()
9090
[Fact]
9191
public void Remove()
9292
{
93-
var table = this.CreateTable(10, 4);
93+
var table = this.CreateTable<int, int>(10, 4);
9494
table[1] = 2;
9595
table.Remove(1).Should().BeTrue();
9696
table.TryGetValue(1, out int val).Should().BeFalse();
@@ -103,7 +103,7 @@ public void Clear()
103103
{
104104
const int numInserts = 40;
105105

106-
var table = this.CreateTable(10, 4);
106+
var table = this.CreateTable<int, int>(10, 4);
107107
for (int i = 0; i < numInserts; i++)
108108
{
109109
table[i] = i;
@@ -123,7 +123,7 @@ public void Clear()
123123
[Fact]
124124
public void Count()
125125
{
126-
var table = this.CreateTable(10, 4);
126+
var table = this.CreateTable<int, int>(10, 4);
127127
table.Count.Should().Be(0);
128128

129129
for (int i = 0; i < 4; i++)
@@ -142,7 +142,7 @@ public void Count()
142142
[Fact]
143143
public void Enumerate()
144144
{
145-
var table = this.CreateTable(10, 4);
145+
var table = this.CreateTable<int, int>(10, 4);
146146
var rng = new Random();
147147
List<KeyValuePair<int, int>> expected = new List<KeyValuePair<int, int>>();
148148

@@ -160,7 +160,7 @@ public void Enumerate()
160160
[Fact]
161161
public void InsertOnFullTableOverwrites()
162162
{
163-
var table = this.CreateTable(5, 4);
163+
var table = this.CreateTable<int, int>(5, 4);
164164

165165
int i = 0;
166166
do
@@ -183,5 +183,28 @@ public void InsertOnFullTableOverwrites()
183183
after.Count.Should().Be(1);
184184
after.First().Should().Be(i);
185185
}
186+
187+
[Theory]
188+
[InlineData(4)]
189+
[InlineData(7)]
190+
public void ResolvesHashCollisions(int numColumns)
191+
{
192+
var table = this.CreateTable<BadHashCode, int>(5, numColumns);
193+
194+
for (int i = 0; i < numColumns; i++)
195+
{
196+
table[i] = i;
197+
}
198+
199+
for (int i = 0; i < numColumns; i++)
200+
{
201+
table[i].Should().Be(i);
202+
}
203+
204+
// This is going to overwrite a value
205+
table[numColumns] = numColumns;
206+
table[numColumns].Should().Be(numColumns);
207+
table.Count.Should().Be(numColumns);
208+
}
186209
}
187210
}

UnitTests/CacheTableTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33

44
namespace UnitTests
55
{
6-
public class CacheTableTests : CacheTableTestBase<CacheTable<int, int>>
6+
public class CacheTableTests : CacheTableTestBase
77
{
88
public CacheTableTests(ITestOutputHelper output) : base(output)
99
{
1010
}
1111

12-
protected override CacheTable<int, int> CreateTable(int numRows, int numColumns)
12+
protected override ICacheTable<TKey, TValue> CreateTable<TKey, TValue>(int numRows, int numColumns)
1313
{
14-
return new CacheTable<int, int>(numRows, numColumns);
14+
return new CacheTable<TKey, TValue>(numRows, numColumns);
1515
}
1616
}
1717
}

UnitTests/ConcurrentCacheTableTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@
66

77
namespace UnitTests
88
{
9-
public class ConcurrentCacheTableTests : CacheTableTestBase<ConcurrentCacheTable<int, int>>
9+
public class ConcurrentCacheTableTests : CacheTableTestBase
1010
{
1111
public ConcurrentCacheTableTests(ITestOutputHelper output) : base(output)
1212
{
1313
}
1414

15-
protected override ConcurrentCacheTable<int, int> CreateTable(int numRows, int numColumns)
15+
protected override ICacheTable<TKey, TValue> CreateTable<TKey, TValue>(int numRows, int numColumns)
1616
{
17-
return new ConcurrentCacheTable<int, int>(numRows, numColumns, 3);
17+
return new ConcurrentCacheTable<TKey, TValue>(numRows, numColumns, 3);
1818
}
1919

2020
[Fact]
2121
public async Task ConcurrentWrites()
2222
{
23-
var table = CreateTable(5, 4);
23+
var table = this.CreateTable<int, int>(5, 4);
2424

2525
const int numWrites = 1000;
2626

0 commit comments

Comments
 (0)