public async Task SpillIntoOverflowBuffer() { // All but the first row of the table will be overflow buffers var st = new StringTableTestHarness(StringTable.MaxNumByteBuffers - 1); var guidSize = Guid.NewGuid().ToString("X").Length; // Make sure that we fill the first bucket and spill into the overflows int repetitions = (int)(1.25 * (StringTable.BytesPerBuffer / guidSize)); for (var i = 0; i < repetitions; i++) { st.AddString(Guid.NewGuid().ToString("X")); } var lastId = st.AddString(Guid.NewGuid().ToString("X")); var bufferNum = (lastId.Value >> StringTable.BytesPerBufferBits) & StringTable.NumByteBuffersMask; Assert.Equal(1, bufferNum); // Spilled into the first overflow buffer await st.RunCommonTestsAsync(); // Add more strings -- if the rows were regular buffers we would fill the second row // and go into the third, but with the overflow buffers we have increased capacity for (var i = 0; i < repetitions; i++) { st.AddString(Guid.NewGuid().ToString("X")); } lastId = st.AddString(Guid.NewGuid().ToString("X")); bufferNum = (lastId.Value >> StringTable.BytesPerBufferBits) & StringTable.NumByteBuffersMask; Assert.Equal(1, bufferNum); // We are still filling the first overflow buffer }
public Task Serialization() { var st = new StringTableTestHarness(); var string1 = "asdf"; var string2 = "jkl"; var stringId1 = st.AddString(string1); var stringId2 = st.AddString(string2); return(st.RunCommonTestsAsync()); }
public Task Serialization(bool includeOverflowBuffers) { var st = new StringTableTestHarness(includeOverflowBuffers ? 3 : 0); var string1 = "asdf"; var string2 = "jkl"; var stringId1 = st.AddString(string1); var stringId2 = st.AddString(string2); return(st.RunCommonTestsAsync()); }
public Task Match() { var harness = new StringTableTestHarness(); var st = harness.StringTable; StringId id1 = harness.AddString("Hello"); StringId id2 = harness.AddString("Goodbye"); StringId id3 = harness.AddString("hello"); StringId id4 = harness.AddString("goodBYE"); StringId id5 = harness.AddString("HELLOX"); StringId id6 = harness.AddString("HEL"); XAssert.AreNotEqual(id1, id3); XAssert.AreNotEqual(id1, id5); XAssert.AreNotEqual(id1, id6); XAssert.AreNotEqual(id5, id6); XAssert.AreNotEqual(id2, id4); // different length, different character sizes StringId ascii = st.AddString("abc"); XAssert.IsFalse(st.CaseInsensitiveEquals(ascii, st.AddString("\u1234\u1234"))); XAssert.IsTrue(st.CaseInsensitiveEquals(ascii, st.AddString("abc"))); XAssert.IsFalse(st.Equals("\u1234\u1234", ascii)); XAssert.IsTrue(st.Equals("abc", ascii)); // same length, different character sizes ascii = st.AddString("abc"); XAssert.IsFalse(st.CaseInsensitiveEquals(ascii, st.AddString("\u1234\u1234\u1234"))); XAssert.IsTrue(st.CaseInsensitiveEquals(ascii, st.AddString("abc"))); XAssert.IsFalse(st.Equals("\u1234\u1234\u1234", ascii)); XAssert.IsTrue(st.Equals("abc", ascii)); // different length, different character sizes StringId utf16 = st.AddString("\u1234\u1234"); XAssert.IsFalse(st.CaseInsensitiveEquals(utf16, st.AddString("abc"))); XAssert.IsTrue(st.CaseInsensitiveEquals(utf16, st.AddString("\u1234\u1234"))); XAssert.IsFalse(st.Equals("abc", utf16)); XAssert.IsTrue(st.Equals("\u1234\u1234", utf16)); // same length, different character sizes utf16 = st.AddString("\u1234\u1234"); XAssert.IsFalse(st.CaseInsensitiveEquals(utf16, st.AddString("ab"))); XAssert.IsTrue(st.CaseInsensitiveEquals(utf16, st.AddString("\u1234\u1234"))); XAssert.IsFalse(st.Equals("ab", utf16)); XAssert.IsTrue(st.Equals("\u1234\u1234", utf16)); return(harness.RunCommonTestsAsync()); }
public Task Serialization(bool includeOverflowBuffers, bool useDeflateStream) { var st = new StringTableTestHarness(includeOverflowBuffers ? 3 : 0, useDeflateStream); // Adding a lot of strings to check a weird case that was happening with deflated strings in .NET6. int count = 10_000; for (int i = 0; i < count; i++) { var guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray()); st.AddString(guid); } return(st.RunCommonTestsAsync()); }
public async Task CharMix() { var harness = new StringTableTestHarness(); var st = harness.StringTable; // make sure all characters are handled properly var map = new Dictionary <StringId, string>(); var sb = new StringBuilder(3000000); // zip through small sizes for (int i = 0; i < 65535; i++) { sb.Length = 0; sb.Append((char)i, (i % 255) + 1); string str = sb.ToString(); StringId sd = harness.AddString(str); map.Add(sd, str); } await harness.RunCommonTestsAsync(); for (int i = 0; i < 2; i++) { // make sure all the right strings come out var buf = new char[65535]; foreach (StringId sd in map.Keys) { // get the actual string we kept string str = map[sd]; // does the table report the right length? int length = st.GetLength(sd); XAssert.AreEqual(str.Length, length); // extract the chars from the table st.CopyString(sd, buf, 0); // make sure we got all the characters out that we should have for (int j = 0; j < str.Length; j++) { XAssert.AreEqual(str[j], buf[j]); } } // make sure the same behavior occurs after freezing st.Freeze(); } }
public Task BigStrings() { var harness = new StringTableTestHarness(); var st = harness.StringTable; var s1 = new string('x', StringTable.BytesPerBuffer - 1); var s2 = new string('y', StringTable.BytesPerBuffer); var s3 = new string('z', StringTable.BytesPerBuffer + 1); StringId id1 = harness.AddString(s1); StringId id2 = harness.AddString(s2); StringId id3 = harness.AddString(s3); harness.AddString(s3 + "繙"); XAssert.AreEqual(s1.Length, st.GetLength(id1)); XAssert.AreEqual(s2.Length, st.GetLength(id2)); XAssert.AreEqual(s3.Length, st.GetLength(id3)); var buf = new char[StringTable.BytesPerBuffer + 1]; st.CopyString(id1, buf, 0); for (int j = 0; j < s1.Length; j++) { XAssert.AreEqual(s1[j], buf[j]); } st.CopyString(id2, buf, 0); for (int j = 0; j < s2.Length; j++) { XAssert.AreEqual(s2[j], buf[j]); } st.CopyString(id3, buf, 0); for (int j = 0; j < s3.Length; j++) { XAssert.AreEqual(s3[j], buf[j]); } XAssert.IsTrue(st.CaseInsensitiveEquals(id1, st.AddString(s1))); XAssert.IsTrue(st.CaseInsensitiveEquals(id2, st.AddString(s2))); XAssert.IsTrue(st.CaseInsensitiveEquals(id3, st.AddString(s3))); XAssert.IsTrue(st.Equals(s1, id1)); XAssert.IsTrue(st.Equals(s2, id2)); XAssert.IsTrue(st.Equals(s3, id3)); XAssert.IsFalse(st.CaseInsensitiveEquals(id1, st.AddString(s2))); XAssert.IsFalse(st.CaseInsensitiveEquals(id1, st.AddString(s3))); XAssert.IsFalse(st.CaseInsensitiveEquals(id2, st.AddString(s1))); XAssert.IsFalse(st.CaseInsensitiveEquals(id2, st.AddString(s3))); XAssert.IsFalse(st.CaseInsensitiveEquals(id3, st.AddString(s1))); XAssert.IsFalse(st.CaseInsensitiveEquals(id3, st.AddString(s2))); XAssert.IsFalse(st.Equals(s2, id1)); XAssert.IsFalse(st.Equals(s3, id1)); XAssert.IsFalse(st.Equals(s1, id2)); XAssert.IsFalse(st.Equals(s3, id2)); XAssert.IsFalse(st.Equals(s1, id3)); XAssert.IsFalse(st.Equals(s2, id3)); return(harness.RunCommonTestsAsync()); }
public async Task SizeMixParallel(bool asciiOnly) { var harness = new StringTableTestHarness(); var st = harness.StringTable; ConcurrentDictionary <StringId, string> map = new ConcurrentDictionary <StringId, string>(); var sb = new StringBuilder(3000000); var strings = new BlockingCollection <string>(); var stringIds = new BlockingCollection <StringId>(); var createStringsTask = Task.Run(() => { // zip through small sizes for (int i = 0; i < 3000; i++) { sb.Length = 0; sb.Append(asciiOnly ? 'x' : '建', i); string str = sb.ToString(); strings.Add(str); } // now use increasingly large amounts, including exceeding the size of a single buffer's worth for (int i = 0; i < 100; i++) { sb.Length = 0; sb.Append('x', i * 10000); string str = sb.ToString(); } strings.CompleteAdding(); }); var validateStringsTask = Task.Run(() => { for (int i = 0; i < 2; i++) { // make sure all the right strings come out int startBias = 0; var buf = new char[4000000]; foreach (StringId sd in stringIds.GetConsumingEnumerable()) { // get the actual string we kept string str = map[sd]; // does the table report the right length? int length = st.GetLength(sd); XAssert.AreEqual(str.Length, length); // put sentinel bytes in the char buffer, extract the string from the table, and check the sentinels if (startBias > 0) { buf[startBias - 1] = (char)42; } buf[startBias + length] = (char)31415; st.CopyString(sd, buf, startBias); if (startBias > 0) { XAssert.AreEqual(42, buf[startBias - 1]); } XAssert.AreEqual(31415, buf[startBias + length]); // make sure we got all the characters out that we should have for (int j = 0; j < str.Length; j++) { XAssert.AreEqual(str[j], buf[startBias + j]); } startBias++; } // make sure the same behavior occurs after freezing st.Freeze(); } }); Parallel.ForEach(strings.GetConsumingEnumerable(), str => { StringId sd = st.AddString(str); map.TryAdd(sd, str); stringIds.Add(sd); }); stringIds.CompleteAdding(); await createStringsTask; await validateStringsTask; }