public void AffineHash_Hash_Distributes_Byte_Array()
        {
            Random               random = AffineHashTests.Random();
            AffineHash           target = new AffineHash(random);
            IEnumerable <byte[]> values = AffineHashTests.RandomByteArrays(random, 101, 10000);

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_Char()
        {
            Random             random = AffineHashTests.Random();
            AffineHash         target = new AffineHash(random);
            IEnumerable <char> values = Enumerable.Range(char.MinValue, char.MaxValue - char.MinValue + 1)
                                        .Select(n => (char)n);

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_Byte()
        {
            Random             random = AffineHashTests.Random();
            AffineHash         target = new AffineHash(random);
            IEnumerable <byte> values = Enumerable.Range(byte.MinValue, byte.MaxValue - byte.MinValue + 1)
                                        .Select(n => (byte)n);

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_UInt16()
        {
            Random               random = AffineHashTests.Random();
            AffineHash           target = new AffineHash(random);
            IEnumerable <ushort> values = Enumerable.Range(ushort.MinValue, ushort.MaxValue - ushort.MinValue + 1)
                                          .Select(n => (ushort)n);

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_UInt64()
        {
            Random              random = AffineHashTests.Random();
            AffineHash          target = new AffineHash(random);
            IEnumerable <ulong> values = AffineHashTests.RandomByteArrays(random, sizeof(ulong), 10000)
                                         .Select(b => BitConverter.ToUInt64(b, 0));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_String()
        {
            Random               random = AffineHashTests.Random();
            AffineHash           target = new AffineHash(random);
            IEnumerable <string> values = AffineHashTests.RandomCharArrays(random, 101, 10000)
                                          .Select(b => new string(b));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_Single()
        {
            Random              random = AffineHashTests.Random();
            AffineHash          target = new AffineHash(random);
            IEnumerable <float> values = AffineHashTests.RandomByteArrays(random, sizeof(float), 10000)
                                         .Select(b => BitConverter.ToSingle(b, 0));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_Guid()
        {
            Random             random = AffineHashTests.Random();
            AffineHash         target = new AffineHash(random);
            IEnumerable <Guid> values = AffineHashTests.RandomByteArrays(random, 16, 10000)
                                        .Select(b => new Guid(b));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_Decimal()
        {
            Random                random = AffineHashTests.Random();
            AffineHash            target = new AffineHash(random);
            IEnumerable <decimal> values = Enumerable.Range(0, 10000)
                                           .Select(n => new decimal(random.Next(), random.Next(), random.Next(), random.NextDouble() > 0.5D, (byte)random.Next(29)));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Distributes_DateTimeOffset()
        {
            Random     random = AffineHashTests.Random();
            AffineHash target = new AffineHash(random);
            IEnumerable <DateTimeOffset> values = AffineHashTests.RandomByteArrays(random, sizeof(ulong), 10000)
                                                  .Select(b => new DateTimeOffset((long)(BitConverter.ToUInt64(b, 0) % (ulong)DateTime.MaxValue.Ticks), TimeSpan.FromMinutes(random.Next(-840, 840))));

            AffineHashTests.AssertHashDistribution(target, values);
        }
        public void AffineHash_Hash_Matches_Identical_String_Segments()
        {
            Random     random   = AffineHashTests.Random();
            AffineHash target   = new AffineHash(random);
            string     value    = "TestTest";
            int        expected = target.GetHashCode(value, 0, 4);
            int        actual   = target.GetHashCode(value, 4, 4);

            Assert.AreEqual(expected, actual);
        }
        public void AffineHash_Hash_Matches_Identical_Char_Array_Segments()
        {
            Random     random = AffineHashTests.Random();
            AffineHash target = new AffineHash(random);

            char[] value    = { 'T', 'e', 's', 't', 'T', 'e', 's', 't' };
            int    expected = target.GetHashCode(value, 0, 4);
            int    actual   = target.GetHashCode(value, 4, 4);

            Assert.AreEqual(expected, actual);
        }
        public void AffineHash_Hash_Matches_Identical_Byte_Array_Segments()
        {
            Random     random = AffineHashTests.Random();
            AffineHash target = new AffineHash(random);

            byte[] value    = { 0, 1, 2, 3, 0, 1, 2, 3 };
            int    expected = target.GetHashCode(value, 0, 4);
            int    actual   = target.GetHashCode(value, 4, 4);

            Assert.AreEqual(expected, actual);
        }
        /// <summary>
        /// Generates random character arrays for test data.
        /// </summary>
        /// <param name="random">The random number generator to use.</param>
        /// <param name="length">The length of each character array.</param>
        /// <param name="count">The total number of character arrays to generate.</param>
        /// <returns>A list of random character arrays.</returns>
        private static IEnumerable <char[]> RandomCharArrays(Random random, int length, int count)
        {
            char[] buffer = new char[length];
            foreach (byte[] bytes in AffineHashTests.RandomByteArrays(random, length * sizeof(char), count))
            {
                int o = 0;
                for (int i = 0; i < buffer.Length; i++)
                {
                    buffer[i] = BitConverter.ToChar(bytes, o);
                    o        += sizeof(char);
                }

                yield return(buffer);
            }
        }
        public void AffineHash_Hash_Rejects_Invalid_Arguments()
        {
            var cases = new[]
            {
                new { arguments = new object[] { null }, types = new Type[] { typeof(byte[]) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { null }, types = new Type[] { typeof(char[]) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { null }, types = new Type[] { typeof(string) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { null, 0, 0 }, types = new Type[] { typeof(byte[]), typeof(int), typeof(int) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { null, 0, 0 }, types = new Type[] { typeof(char[]), typeof(int), typeof(int) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { null, 0, 0 }, types = new Type[] { typeof(string), typeof(int), typeof(int) }, expected = typeof(ArgumentNullException) },
                new { arguments = new object[] { new byte[10], -1, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new byte[10], 10, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new byte[10], 5, -1 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new byte[10], 5, 6 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new char[10], -1, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new char[10], 10, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new char[10], 5, -1 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { new char[10], 5, 6 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { "1234567890", -1, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { "1234567890", 10, 5 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { "1234567890", 5, -1 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
                new { arguments = new object[] { "1234567890", 5, 6 }, types = (Type[])null, expected = typeof(ArgumentOutOfRangeException) },
            };
            AffineHash target = new AffineHash(1L, 0L);

            for (int i = 0; i < cases.Length; i++)
            {
                var      c      = cases[i];
                Type[]   types  = c.types ?? c.arguments.Select(a => a.GetType()).ToArray();
                Delegate method = AffineHashTests.HashDelegate(target, types);
                try
                {
                    object result = method.DynamicInvoke(c.arguments);
                    Assert.Fail("index: {0}, return: {1}", i, result);
                }
                catch (TargetInvocationException ex)
                {
                    Assert.AreEqual(c.expected, ex.InnerException.GetType(), "index: {0}", i);
                }
                catch (Exception ex)
                {
                    Assert.Fail("index: {0}, exception: {1}", i, ex);
                }
            }
        }
        /// <summary>
        /// Asserts that the distribution of hash values is uniform for a given set of data.
        /// </summary>
        /// <typeparam name="T">The type of data to hash.</typeparam>
        /// <param name="target">The target hash algorithm.</param>
        /// <param name="values">The values to hash.</param>
        private static void AssertHashDistribution <T>(AffineHash target, IEnumerable <T> values)
        {
            Distribution        distribution = new Distribution();
            Dictionary <int, T> hashes       = new Dictionary <int, T>();
            Func <T, int>       method       = (Func <T, int>)AffineHashTests.HashDelegate(target, typeof(T));

            foreach (T value in values)
            {
                int hash = method(value);
                distribution.Observe(hash);
                if (hashes.ContainsKey(hash))
                {
                    Assert.Fail("scale:{0}, shift:{1}, hash:{2}, original:{3}, collision:{4}", target.Scale, target.Shift, hash, hashes[hash], value);
                }
                else
                {
                    hashes.Add(hash, value);
                }
            }

            double ks = distribution.Finish();

            Assert.IsTrue(ks < 0.1D, "scale:{0}, shift:{1}, ks:{2}", target.Scale, target.Shift, ks);
        }