|
| 1 | +// User code can reach Counter.Current from parallel work inside one test, so the |
| 2 | +// value caches have to survive concurrent access |
| 3 | +public class CounterConcurrencyTests |
| 4 | +{ |
| 5 | + [Fact] |
| 6 | + public void ConcurrentGuids() |
| 7 | + { |
| 8 | + using var counter = Counter.Start(); |
| 9 | + |
| 10 | + var guids = Enumerable.Range(0, 500) |
| 11 | + .Select(_ => Guid.NewGuid()) |
| 12 | + .ToList(); |
| 13 | + |
| 14 | + var names = new ConcurrentBag<string>(); |
| 15 | + Parallel.ForEach(guids, guid => names.Add(counter.NextString(guid))); |
| 16 | + |
| 17 | + // one name per distinct input, and no name handed out twice |
| 18 | + Assert.Equal(guids.Count, names.Distinct().Count()); |
| 19 | + |
| 20 | + // and the same input keeps the name it was given |
| 21 | + foreach (var guid in guids) |
| 22 | + { |
| 23 | + Assert.Contains(counter.NextString(guid), names); |
| 24 | + } |
| 25 | + |
| 26 | + Assert.Equal(guids.Count, names.Distinct().Count()); |
| 27 | + } |
| 28 | + |
| 29 | + [Fact] |
| 30 | + public void ConcurrentNumericIds() |
| 31 | + { |
| 32 | + using var counter = Counter.Start(); |
| 33 | + |
| 34 | + var ids = Enumerable.Range(0, 500) |
| 35 | + .Select(_ => (long) _) |
| 36 | + .ToList(); |
| 37 | + |
| 38 | + var names = new ConcurrentBag<string>(); |
| 39 | + Parallel.ForEach(ids, id => names.Add(counter.NextNumericIdString("TheEntity", id))); |
| 40 | + |
| 41 | + Assert.Equal(ids.Count, names.Distinct().Count()); |
| 42 | + |
| 43 | + foreach (var id in ids) |
| 44 | + { |
| 45 | + Assert.Contains(counter.NextNumericIdString("TheEntity", id), names); |
| 46 | + } |
| 47 | + |
| 48 | + Assert.Equal(ids.Count, names.Distinct().Count()); |
| 49 | + } |
| 50 | +} |
0 commit comments