Skip to content

Commit 52fbc84

Browse files
committed
Add hash code collision testing to proptests
1 parent 5a4c5ec commit 52fbc84

File tree

1 file changed

+42
-0
lines changed
  • crates/bindings-csharp/BSATN.Runtime.Tests

1 file changed

+42
-0
lines changed

crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs

+42
Original file line numberDiff line numberDiff line change
@@ -297,10 +297,39 @@ public BasicDataRecord((int x, string y, int? z, string? w) data)
297297
(int X, string Y, int? Z, string? W) c2
298298
)> GenTwoBasic = Gen.Select(GenBasic, GenBasic, (c1, c2) => (c1, c2));
299299

300+
/// <summary>
301+
/// Count collisions when comparing hashcodes of non-equal structures.
302+
/// </summary>
303+
struct CollisionCounter
304+
{
305+
private uint Comparisons;
306+
private uint Collisions;
307+
308+
public void Add(bool collides)
309+
{
310+
Comparisons += 1;
311+
if (collides)
312+
{
313+
Collisions += 1;
314+
}
315+
}
316+
317+
public double CollisionFraction
318+
{
319+
get => (double)Collisions / (double)Comparisons;
320+
}
321+
322+
public void AssertCollisionsLessThan(double fraction)
323+
{
324+
Assert.True(CollisionFraction < fraction, $"Expected {fraction} portion of collisions, but got {CollisionFraction} = {Collisions} / {Comparisons}");
325+
}
326+
}
300327

301328
[Fact]
302329
public static void GeneratedProductEqualsWorks()
303330
{
331+
CollisionCounter collisionCounter = new();
332+
304333
GenTwoBasic.Sample(
305334
example =>
306335
{
@@ -357,10 +386,13 @@ public static void GeneratedProductEqualsWorks()
357386
// hash code should not depend on the type of object.
358387
Assert.Equal(class1.GetHashCode(), record1.GetHashCode());
359388
Assert.Equal(record1.GetHashCode(), struct1.GetHashCode());
389+
390+
collisionCounter.Add(class1.GetHashCode() == class2.GetHashCode());
360391
}
361392
},
362393
iter: 10_000
363394
);
395+
collisionCounter.AssertCollisionsLessThan(0.05);
364396
}
365397

366398
[Type]
@@ -402,6 +434,8 @@ BasicDataRecord W
402434
[Fact]
403435
public static void GeneratedSumEqualsWorks()
404436
{
437+
CollisionCounter collisionCounter = new();
438+
405439
GenTwoBasicEnum.Sample(
406440
example =>
407441
{
@@ -433,10 +467,12 @@ public static void GeneratedSumEqualsWorks()
433467
Assert.False(example.e1 == example.e2);
434468
Assert.True(example.e1 != example.e2);
435469
Assert.NotEqual(example.e1.ToString(), example.e2.ToString());
470+
collisionCounter.Add(example.e1.GetHashCode() == example.e2.GetHashCode());
436471
}
437472
},
438473
iter: 10_000
439474
);
475+
collisionCounter.AssertCollisionsLessThan(0.05);
440476
}
441477

442478

@@ -465,6 +501,7 @@ public ContainsList(List<BasicEnum?>? theList)
465501
[Fact]
466502
public static void GeneratedListEqualsWorks()
467503
{
504+
CollisionCounter collisionCounter = new();
468505
GenTwoContainsList.Sample(
469506
example =>
470507
{
@@ -486,10 +523,12 @@ public static void GeneratedListEqualsWorks()
486523
Assert.False(example.e1 == example.e2);
487524
Assert.True(example.e1 != example.e2);
488525
Assert.NotEqual(example.e1.ToString(), example.e2.ToString());
526+
collisionCounter.Add(example.e1.GetHashCode() == example.e2.GetHashCode());
489527
}
490528
},
491529
iter: 10_000
492530
);
531+
collisionCounter.AssertCollisionsLessThan(0.05);
493532
}
494533

495534
[Type]
@@ -550,6 +589,7 @@ public static void GeneratedNestedListEqualsWorks()
550589
)
551590
)
552591
);
592+
CollisionCounter collisionCounter = new();
553593
GenTwoContainsNestedList.Sample(
554594
example =>
555595
{
@@ -569,10 +609,12 @@ public static void GeneratedNestedListEqualsWorks()
569609
Assert.False(example.e1 == example.e2);
570610
Assert.True(example.e1 != example.e2);
571611
Assert.NotEqual(example.e1.ToString(), example.e2.ToString());
612+
collisionCounter.Add(example.e1.GetHashCode() == example.e2.GetHashCode());
572613
}
573614
},
574615
iter: 10_000
575616
);
617+
collisionCounter.AssertCollisionsLessThan(0.05);
576618
}
577619

578620

0 commit comments

Comments
 (0)