diff options
Diffstat (limited to 'OpenSim/Data/Tests/PropertyCompareConstraint.cs')
-rw-r--r-- | OpenSim/Data/Tests/PropertyCompareConstraint.cs | 229 |
1 files changed, 172 insertions, 57 deletions
diff --git a/OpenSim/Data/Tests/PropertyCompareConstraint.cs b/OpenSim/Data/Tests/PropertyCompareConstraint.cs index 678501e..06ca53e 100644 --- a/OpenSim/Data/Tests/PropertyCompareConstraint.cs +++ b/OpenSim/Data/Tests/PropertyCompareConstraint.cs | |||
@@ -1,3 +1,30 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
1 | using System; | 28 | using System; |
2 | using System.Collections; | 29 | using System.Collections; |
3 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
@@ -42,6 +69,28 @@ namespace OpenSim.Data.Tests | |||
42 | 69 | ||
43 | private bool ObjectCompare(object expected, object actual, Stack<string> propertyNames) | 70 | private bool ObjectCompare(object expected, object actual, Stack<string> propertyNames) |
44 | { | 71 | { |
72 | //If they are both null, they are equal | ||
73 | if (actual == null && expected == null) | ||
74 | return true; | ||
75 | |||
76 | //If only one is null, then they aren't | ||
77 | if (actual == null || expected == null) | ||
78 | { | ||
79 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | ||
80 | failingActual = actual; | ||
81 | failingExpected = expected; | ||
82 | return false; | ||
83 | } | ||
84 | |||
85 | //prevent loops... | ||
86 | if (propertyNames.Count > 50) | ||
87 | { | ||
88 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | ||
89 | failingActual = actual; | ||
90 | failingExpected = expected; | ||
91 | return false; | ||
92 | } | ||
93 | |||
45 | if (actual.GetType() != expected.GetType()) | 94 | if (actual.GetType() != expected.GetType()) |
46 | { | 95 | { |
47 | propertyNames.Push("GetType()"); | 96 | propertyNames.Push("GetType()"); |
@@ -52,7 +101,7 @@ namespace OpenSim.Data.Tests | |||
52 | return false; | 101 | return false; |
53 | } | 102 | } |
54 | 103 | ||
55 | if(actual.GetType() == typeof(Color)) | 104 | if (actual.GetType() == typeof(Color)) |
56 | { | 105 | { |
57 | Color actualColor = (Color) actual; | 106 | Color actualColor = (Color) actual; |
58 | Color expectedColor = (Color) expected; | 107 | Color expectedColor = (Color) expected; |
@@ -95,65 +144,69 @@ namespace OpenSim.Data.Tests | |||
95 | return true; | 144 | return true; |
96 | } | 145 | } |
97 | 146 | ||
98 | //Skip static properties. I had a nasty problem comparing colors because of all of the public static colors. | 147 | IComparable comp = actual as IComparable; |
99 | PropertyInfo[] properties = expected.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); | 148 | if (comp != null) |
100 | foreach (var property in properties) | ||
101 | { | 149 | { |
102 | if (ignores.Contains(property.Name)) | 150 | if (comp.CompareTo(expected) != 0) |
103 | continue; | 151 | { |
104 | 152 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | |
105 | object actualValue = property.GetValue(actual, null); | 153 | failingActual = actual; |
106 | object expectedValue = property.GetValue(expected, null); | 154 | failingExpected = expected; |
155 | return false; | ||
156 | } | ||
157 | return true; | ||
158 | } | ||
107 | 159 | ||
108 | //If they are both null, they are equal | 160 | //Now try the much more annoying IComparable<T> |
109 | if (actualValue == null && expectedValue == null) | 161 | Type icomparableInterface = actual.GetType().GetInterface("IComparable`1"); |
110 | continue; | 162 | if (icomparableInterface != null) |
163 | { | ||
164 | int result = (int)icomparableInterface.GetMethod("CompareTo").Invoke(actual, new[] { expected }); | ||
165 | if (result != 0) | ||
166 | { | ||
167 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | ||
168 | failingActual = actual; | ||
169 | failingExpected = expected; | ||
170 | return false; | ||
171 | } | ||
172 | return true; | ||
173 | } | ||
111 | 174 | ||
112 | //If only one is null, then they aren't | 175 | IEnumerable arr = actual as IEnumerable; |
113 | if (actualValue == null || expectedValue == null) | 176 | if (arr != null) |
177 | { | ||
178 | List<object> actualList = arr.Cast<object>().ToList(); | ||
179 | List<object> expectedList = ((IEnumerable)expected).Cast<object>().ToList(); | ||
180 | if (actualList.Count != expectedList.Count) | ||
114 | { | 181 | { |
115 | propertyNames.Push(property.Name); | 182 | propertyNames.Push("Count"); |
116 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | 183 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); |
184 | failingActual = actualList.Count; | ||
185 | failingExpected = expectedList.Count; | ||
117 | propertyNames.Pop(); | 186 | propertyNames.Pop(); |
118 | failingActual = actualValue; | ||
119 | failingExpected = expectedValue; | ||
120 | return false; | 187 | return false; |
121 | } | 188 | } |
122 | 189 | //actualList and expectedList should be the same size. | |
123 | IComparable comp = actualValue as IComparable; | 190 | for (int i = 0; i < actualList.Count; i++) |
124 | if (comp != null) | ||
125 | { | 191 | { |
126 | if (comp.CompareTo(expectedValue) != 0) | 192 | propertyNames.Push("[" + i + "]"); |
127 | { | 193 | if (!ObjectCompare(expectedList[i], actualList[i], propertyNames)) |
128 | propertyNames.Push(property.Name); | ||
129 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | ||
130 | propertyNames.Pop(); | ||
131 | failingActual = actualValue; | ||
132 | failingExpected = expectedValue; | ||
133 | return false; | 194 | return false; |
134 | } | 195 | propertyNames.Pop(); |
135 | continue; | ||
136 | } | 196 | } |
197 | //Everything seems okay... | ||
198 | return true; | ||
199 | } | ||
137 | 200 | ||
138 | IEnumerable arr = actualValue as IEnumerable; | 201 | //Skip static properties. I had a nasty problem comparing colors because of all of the public static colors. |
139 | if (arr != null) | 202 | PropertyInfo[] properties = expected.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); |
140 | { | 203 | foreach (var property in properties) |
141 | List<object> actualList = arr.Cast<object>().ToList(); | 204 | { |
142 | List<object> expectedList = ((IEnumerable)expectedValue).Cast<object>().ToList(); | 205 | if (ignores.Contains(property.Name)) |
143 | if (actualList.Count != expectedList.Count) | ||
144 | { | ||
145 | propertyNames.Push(property.Name); | ||
146 | propertyNames.Push("Count"); | ||
147 | failingPropertyName = string.Join(".", propertyNames.Reverse().ToArray()); | ||
148 | failingActual = actualList.Count; | ||
149 | failingExpected = expectedList.Count; | ||
150 | propertyNames.Pop(); | ||
151 | propertyNames.Pop(); | ||
152 | } | ||
153 | //Todo: A value-wise comparison of all of the values. | ||
154 | //Everything seems okay... | ||
155 | continue; | 206 | continue; |
156 | } | 207 | |
208 | object actualValue = property.GetValue(actual, null); | ||
209 | object expectedValue = property.GetValue(expected, null); | ||
157 | 210 | ||
158 | propertyNames.Push(property.Name); | 211 | propertyNames.Push(property.Name); |
159 | if (!ObjectCompare(expectedValue, actualValue, propertyNames)) | 212 | if (!ObjectCompare(expectedValue, actualValue, propertyNames)) |
@@ -196,15 +249,7 @@ namespace OpenSim.Data.Tests | |||
196 | { | 249 | { |
197 | //If the inside of the lambda is the access to x, we've hit the end of the chain. | 250 | //If the inside of the lambda is the access to x, we've hit the end of the chain. |
198 | // We should track by the fully scoped parameter name, but this is the first rev of doing this. | 251 | // We should track by the fully scoped parameter name, but this is the first rev of doing this. |
199 | if (((MemberExpression)express).Expression is ParameterExpression) | 252 | ignores.Add(((MemberExpression)express).Member.Name); |
200 | { | ||
201 | ignores.Add(((MemberExpression)express).Member.Name); | ||
202 | } | ||
203 | else | ||
204 | { | ||
205 | //Otherwise there could be more parameters inside... | ||
206 | PullApartExpression(((MemberExpression)express).Expression); | ||
207 | } | ||
208 | } | 253 | } |
209 | } | 254 | } |
210 | } | 255 | } |
@@ -243,7 +288,7 @@ namespace OpenSim.Data.Tests | |||
243 | { | 288 | { |
244 | HasInt actual = new HasInt { TheValue = 5 }; | 289 | HasInt actual = new HasInt { TheValue = 5 }; |
245 | HasInt expected = new HasInt { TheValue = 4 }; | 290 | HasInt expected = new HasInt { TheValue = 4 }; |
246 | var constraint = Constraints.PropertyCompareConstraint(expected).IgnoreProperty(x=>x.TheValue); | 291 | var constraint = Constraints.PropertyCompareConstraint(expected).IgnoreProperty(x => x.TheValue); |
247 | 292 | ||
248 | Assert.That(constraint.Matches(actual), Is.True); | 293 | Assert.That(constraint.Matches(actual), Is.True); |
249 | } | 294 | } |
@@ -285,6 +330,28 @@ namespace OpenSim.Data.Tests | |||
285 | } | 330 | } |
286 | 331 | ||
287 | [Test] | 332 | [Test] |
333 | public void UUIDShouldMatch() | ||
334 | { | ||
335 | UUID uuid1 = UUID.Random(); | ||
336 | UUID uuid2 = UUID.Parse(uuid1.ToString()); | ||
337 | |||
338 | var constraint = Constraints.PropertyCompareConstraint(uuid1); | ||
339 | |||
340 | Assert.That(constraint.Matches(uuid2), Is.True); | ||
341 | } | ||
342 | |||
343 | [Test] | ||
344 | public void UUIDShouldNotMatch() | ||
345 | { | ||
346 | UUID uuid1 = UUID.Random(); | ||
347 | UUID uuid2 = UUID.Random(); | ||
348 | |||
349 | var constraint = Constraints.PropertyCompareConstraint(uuid1); | ||
350 | |||
351 | Assert.That(constraint.Matches(uuid2), Is.False); | ||
352 | } | ||
353 | |||
354 | [Test] | ||
288 | public void TestColors() | 355 | public void TestColors() |
289 | { | 356 | { |
290 | Color actual = Color.Red; | 357 | Color actual = Color.Red; |
@@ -294,5 +361,53 @@ namespace OpenSim.Data.Tests | |||
294 | 361 | ||
295 | Assert.That(constraint.Matches(actual), Is.True); | 362 | Assert.That(constraint.Matches(actual), Is.True); |
296 | } | 363 | } |
364 | |||
365 | [Test] | ||
366 | public void ShouldCompareLists() | ||
367 | { | ||
368 | List<int> expected = new List<int> { 1, 2, 3 }; | ||
369 | List<int> actual = new List<int> { 1, 2, 3 }; | ||
370 | |||
371 | var constraint = Constraints.PropertyCompareConstraint(expected); | ||
372 | Assert.That(constraint.Matches(actual), Is.True); | ||
373 | } | ||
374 | |||
375 | |||
376 | [Test] | ||
377 | public void ShouldFailToCompareListsThatAreDifferent() | ||
378 | { | ||
379 | List<int> expected = new List<int> { 1, 2, 3 }; | ||
380 | List<int> actual = new List<int> { 1, 2, 4 }; | ||
381 | |||
382 | var constraint = Constraints.PropertyCompareConstraint(expected); | ||
383 | Assert.That(constraint.Matches(actual), Is.False); | ||
384 | } | ||
385 | |||
386 | [Test] | ||
387 | public void ShouldFailToCompareListsThatAreDifferentLengths() | ||
388 | { | ||
389 | List<int> expected = new List<int> { 1, 2, 3 }; | ||
390 | List<int> actual = new List<int> { 1, 2 }; | ||
391 | |||
392 | var constraint = Constraints.PropertyCompareConstraint(expected); | ||
393 | Assert.That(constraint.Matches(actual), Is.False); | ||
394 | } | ||
395 | |||
396 | public class Recursive | ||
397 | { | ||
398 | public Recursive Other { get; set; } | ||
399 | } | ||
400 | |||
401 | [Test] | ||
402 | public void ErrorsOutOnRecursive() | ||
403 | { | ||
404 | Recursive parent = new Recursive(); | ||
405 | Recursive child = new Recursive(); | ||
406 | parent.Other = child; | ||
407 | child.Other = parent; | ||
408 | |||
409 | var constraint = Constraints.PropertyCompareConstraint(child); | ||
410 | Assert.That(constraint.Matches(child), Is.False); | ||
411 | } | ||
297 | } | 412 | } |
298 | } \ No newline at end of file | 413 | } \ No newline at end of file |