1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2017 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using NUnit.Framework;
34 using System.Collections.Generic;
35 using System.Linq;
36 using static Google.Protobuf.Collections.ProtobufEqualityComparers;
37 
38 namespace Google.Protobuf.Collections
39 {
40     public class ProtobufEqualityComparersTest
41     {
42         private static readonly double[] doubles =
43         {
44             0,
45             1,
46             1.5,
47             -1.5,
48             double.PositiveInfinity,
49             double.NegativeInfinity,
50             // Three different types of NaN...
51             SampleNaNs.Regular,
52             SampleNaNs.SignallingFlipped,
53             SampleNaNs.PayloadFlipped
54         };
55 
56         [Test]
GetEqualityComparer_Default()57         public void GetEqualityComparer_Default()
58         {
59             // It's more pain than it's worth to try to parameterize these tests.
60             Assert.AreSame(EqualityComparer<object>.Default, GetEqualityComparer<object>());
61             Assert.AreSame(EqualityComparer<string>.Default, GetEqualityComparer<string>());
62             Assert.AreSame(EqualityComparer<int>.Default, GetEqualityComparer<int>());
63             Assert.AreSame(EqualityComparer<int?>.Default, GetEqualityComparer<int?>());
64         }
65 
66         [Test]
GetEqualityComparer_NotDefault()67         public void GetEqualityComparer_NotDefault()
68         {
69             // It's more pain than it's worth to try to parameterize these tests.
70             Assert.AreSame(BitwiseDoubleEqualityComparer, GetEqualityComparer<double>());
71             Assert.AreSame(BitwiseSingleEqualityComparer, GetEqualityComparer<float>());
72             Assert.AreSame(BitwiseNullableDoubleEqualityComparer, GetEqualityComparer<double?>());
73             Assert.AreSame(BitwiseNullableSingleEqualityComparer, GetEqualityComparer<float?>());
74         }
75 
76         [Test]
DoubleComparisons()77         public void DoubleComparisons()
78         {
79             ValidateEqualityComparer(BitwiseDoubleEqualityComparer, doubles);
80         }
81 
82         [Test]
NullableDoubleComparisons()83         public void NullableDoubleComparisons()
84         {
85             ValidateEqualityComparer(BitwiseNullableDoubleEqualityComparer, doubles.Select(d => (double?) d).Concat(new double?[] { null }));
86         }
87 
88         [Test]
SingleComparisons()89         public void SingleComparisons()
90         {
91             ValidateEqualityComparer(BitwiseSingleEqualityComparer, doubles.Select(d => (float) d));
92         }
93 
94         [Test]
NullableSingleComparisons()95         public void NullableSingleComparisons()
96         {
97             ValidateEqualityComparer(BitwiseNullableSingleEqualityComparer, doubles.Select(d => (float?) d).Concat(new float?[] { null }));
98         }
99 
ValidateEqualityComparer(EqualityComparer<T> comparer, IEnumerable<T> values)100         private static void ValidateEqualityComparer<T>(EqualityComparer<T> comparer, IEnumerable<T> values)
101         {
102             var array = values.ToArray();
103             // Each value should be equal to itself, but not to any other value.
104             for (int i = 0; i < array.Length; i++)
105             {
106                 for (int j = 0; j < array.Length; j++)
107                 {
108                     if (i == j)
109                     {
110                         Assert.IsTrue(comparer.Equals(array[i], array[j]),
111                             "{0} should be equal to itself", array[i], array[j]);
112                     }
113                     else
114                     {
115                         Assert.IsFalse(comparer.Equals(array[i], array[j]),
116                             "{0} and {1} should not be equal", array[i], array[j]);
117                         Assert.AreNotEqual(comparer.GetHashCode(array[i]), comparer.GetHashCode(array[j]),
118                             "Hash codes for {0} and {1} should not be equal", array[i], array[j]);
119                     }
120                 }
121             }
122         }
123     }
124 }
125