Bug 15572. Lookup KnownTypeCollection element types in MSSimpleNamespace
[mono.git] / mcs / class / System.ComponentModel.DataAnnotations / Test / System.ComponentModel.DataAnnotations / ValidatorTest.cs
1 //
2 // Authors:
3 //      Marek Habersack <grendel@twistedcode.net>
4 //
5 // Copyright (C) 2011 Novell, Inc. (http://novell.com/)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 // 
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 // 
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26 using System;
27 using System.Collections.Generic;
28 using System.ComponentModel.DataAnnotations;
29 using System.ComponentModel.Design;
30 using System.Text;
31
32 using NUnit.Framework;
33 using MonoTests.Common;
34
35 namespace MonoTests.System.ComponentModel.DataAnnotations
36 {
37 #if NET_4_0
38         [TestFixture]
39         public class ValidatorTest
40         {
41                 [Test]
42                 public void TryValidateObject_Object_ValidationContext_ICollection_01 ()
43                 {
44                         var dummy = new DummyNoAttributes ();
45                         var ctx = new ValidationContext (dummy, null, null);
46                         var results = new List<ValidationResult> ();
47
48                         AssertExtensions.Throws<ArgumentNullException> (() => {
49                                 Validator.TryValidateObject (null, ctx, results);
50                         }, "#A1-1");
51
52                         AssertExtensions.Throws<ArgumentNullException> (() => {
53                                 Validator.TryValidateObject (dummy, null, results);
54                         }, "#A1-2");
55
56                         bool valid = Validator.TryValidateObject (dummy, ctx, null);
57                         Assert.IsTrue (valid, "#A2-1");
58                         Assert.IsTrue (results.Count == 0, "#A2-2");
59                 }
60
61                 [Test]
62                 public void TryValidateObject_Object_ValidationContext_ICollection_02 ()
63                 {
64                         var dummy = new Dummy ();
65                         var ctx = new ValidationContext (dummy, null, null);
66                         var results = new List<ValidationResult> ();
67
68                         bool valid = Validator.TryValidateObject (dummy, ctx, results);
69                         Assert.IsTrue (valid, "#A1-1");
70                         Assert.AreEqual (0, results.Count, "#A1-2");
71
72                         dummy = new Dummy {
73                                 NameField = null
74                         };
75                         AssertExtensions.Throws<ArgumentException> (() => {
76                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
77                                 valid = Validator.TryValidateObject (dummy, ctx, results);
78                         }, "#A2");
79
80                         // Fields are ignored
81                         ctx = new ValidationContext (dummy, null, null);
82                         valid = Validator.TryValidateObject (dummy, ctx, results);
83                         Assert.IsTrue (valid, "#A3-1");
84                         Assert.AreEqual (0, results.Count, "#A3-2");
85
86                         // Required properties existence is validated
87                         dummy = new Dummy {
88                                 RequiredDummyField = null
89                         };
90                         ctx = new ValidationContext (dummy, null, null);
91                         valid = Validator.TryValidateObject (dummy, ctx, results);
92                         Assert.IsTrue (valid, "#A4-1");
93                         Assert.AreEqual (0, results.Count, "#A4-2");
94
95                         dummy = new Dummy {
96                                 RequiredDummyProperty = null
97                         };
98                         ctx = new ValidationContext (dummy, null, null);
99                         valid = Validator.TryValidateObject (dummy, ctx, results);
100                         Assert.IsFalse (valid, "#A5-1");
101                         Assert.AreEqual (1, results.Count, "#A5-2");
102
103                         results.Clear ();
104
105                         // validation attributes other than Required are ignored
106                         dummy = new Dummy {
107                                 NameProperty = null
108                         };
109                         ctx = new ValidationContext (dummy, null, null);
110                         valid = Validator.TryValidateObject (dummy, ctx, results);
111                         Assert.IsTrue (valid, "#A6-1");
112                         Assert.AreEqual (0, results.Count, "#A6-2");
113
114                         dummy = new Dummy {
115                                 MinMaxProperty = 0
116                         };
117                         ctx = new ValidationContext (dummy, null, null);
118                         valid = Validator.TryValidateObject (dummy, ctx, results);
119                         Assert.IsTrue (valid, "#A7-1");
120                         Assert.AreEqual (0, results.Count, "#A7-2");
121
122                         dummy = new Dummy {
123                                 FailValidation = true
124                         };
125                         ctx = new ValidationContext (dummy, null, null);
126                         valid = Validator.TryValidateObject (dummy, ctx, results);
127                         Assert.IsFalse (valid, "#A8-1");
128                         Assert.AreEqual (1, results.Count, "#A8-2");
129                 }
130
131                 [Test]
132                 public void TryValidateObject_Object_ValidationContext_ICollection_Bool_01 ()
133                 {
134                         var dummy = new DummyNoAttributes ();
135                         var ctx = new ValidationContext (dummy, null, null);
136                         var results = new List<ValidationResult> ();
137
138                         AssertExtensions.Throws<ArgumentNullException> (() => {
139                                 Validator.TryValidateObject (null, ctx, results, false);
140                         }, "#A1-1");
141
142                         AssertExtensions.Throws<ArgumentNullException> (() => {
143                                 Validator.TryValidateObject (dummy, null, results, false);
144                         }, "#A1-2");
145
146                         bool valid = Validator.TryValidateObject (dummy, ctx, null, false);
147                         Assert.IsTrue (valid, "#A2-1");
148                         Assert.IsTrue (results.Count == 0, "#A2-2");
149
150                         valid = Validator.TryValidateObject (dummy, ctx, null, true);
151                         Assert.IsTrue (valid, "#A3-1");
152                         Assert.IsTrue (results.Count == 0, "#A3-2");
153                 }
154
155                 [Test]
156                 public void TryValidateObject_Object_ValidationContext_ICollection_Bool_02 ()
157                 {
158                         var dummy = new Dummy ();
159                         var ctx = new ValidationContext (dummy, null, null);
160                         var results = new List<ValidationResult> ();
161
162                         bool valid = Validator.TryValidateObject (dummy, ctx, results, false);
163                         Assert.IsTrue (valid, "#A1-1");
164                         Assert.AreEqual (0, results.Count, "#A1-2");
165
166                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
167                         Assert.IsTrue (valid, "#A1-3");
168                         Assert.AreEqual (0, results.Count, "#A1-4");
169
170                         dummy = new Dummy {
171                                 NameField = null
172                         };
173                         AssertExtensions.Throws<ArgumentException> (() => {
174                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
175                                 valid = Validator.TryValidateObject (dummy, ctx, results, false);
176                         }, "#A2-1");
177
178                         AssertExtensions.Throws<ArgumentException> (() => {
179                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
180                                 valid = Validator.TryValidateObject (dummy, ctx, results, true);
181                         }, "#A2-2");
182
183                         // Fields are ignored
184                         ctx = new ValidationContext (dummy, null, null);
185                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
186                         Assert.IsTrue (valid, "#A3-1");
187                         Assert.AreEqual (0, results.Count, "#A3-2");
188
189                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
190                         Assert.IsTrue (valid, "#A3-3");
191                         Assert.AreEqual (0, results.Count, "#A3-4");
192
193                         dummy = new Dummy {
194                                 RequiredDummyField = null
195                         };
196                         ctx = new ValidationContext (dummy, null, null);
197                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
198                         Assert.IsTrue (valid, "#A4-1");
199                         Assert.AreEqual (0, results.Count, "#A4-2");
200
201                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
202                         Assert.IsTrue (valid, "#A4-3");
203                         Assert.AreEqual (0, results.Count, "#A4-4");
204
205                         // Required properties existence is validated
206                         dummy = new Dummy {
207                                 RequiredDummyProperty = null
208                         };
209                         ctx = new ValidationContext (dummy, null, null);
210                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
211                         Assert.IsFalse (valid, "#A5-1");
212                         Assert.AreEqual (1, results.Count, "#A5-2");
213                         results.Clear ();
214                         
215                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
216                         Assert.IsFalse (valid, "#A5-3");
217                         Assert.AreEqual (1, results.Count, "#A5-4");
218                         results.Clear ();
219
220                         dummy = new Dummy {
221                                 NameProperty = null
222                         };
223                         ctx = new ValidationContext (dummy, null, null);
224                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
225                         Assert.IsTrue (valid, "#A6-1");
226                         Assert.AreEqual (0, results.Count, "#A6-2");
227
228                         // NameProperty is null, that causes the StringLength validator to skip its tests
229                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
230                         Assert.IsTrue (valid, "#A6-3");
231                         Assert.AreEqual (0, results.Count, "#A6-4");
232
233                         dummy.NameProperty = "0";
234                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
235                         Assert.IsFalse (valid, "#A6-5");
236                         Assert.AreEqual (1, results.Count, "#A6-6");
237                         results.Clear ();
238
239                         dummy.NameProperty = "name too long (invalid value)";
240                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
241                         Assert.IsFalse (valid, "#A6-7");
242                         Assert.AreEqual (1, results.Count, "#A6-8");
243                         results.Clear ();
244
245                         dummy = new Dummy {
246                                 MinMaxProperty = 0
247                         };
248                         ctx = new ValidationContext (dummy, null, null);
249                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
250                         Assert.IsTrue (valid, "#A7-1");
251                         Assert.AreEqual (0, results.Count, "#A7-2");
252
253                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
254                         Assert.IsFalse (valid, "#A7-3");
255                         Assert.AreEqual (1, results.Count, "#A7-4");
256                         results.Clear ();
257
258                         dummy = new Dummy {
259                                 FailValidation = true
260                         };
261                         ctx = new ValidationContext (dummy, null, null);
262                         valid = Validator.TryValidateObject (dummy, ctx, results, false);
263                         Assert.IsFalse (valid, "#A8-1");
264                         Assert.AreEqual (1, results.Count, "#A8-2");
265                         results.Clear ();
266
267                         valid = Validator.TryValidateObject (dummy, ctx, results, true);
268                         Assert.IsFalse (valid, "#A8-3");
269                         Assert.AreEqual (1, results.Count, "#A8-4");
270                         results.Clear ();
271
272                         var dummy2 = new DummyWithException ();
273                         ctx = new ValidationContext (dummy2, null, null);
274                         AssertExtensions.Throws<ApplicationException> (() => {
275                                 Validator.TryValidateObject (dummy2, ctx, results, true);
276                         }, "#A9");
277                 }
278
279                 [Test]
280                 public void TryValidateProperty ()
281                 {
282                         var dummy = new DummyNoAttributes ();
283                         var ctx = new ValidationContext (dummy, null, null) {
284                                 MemberName = "NameProperty"
285                         };
286                         var results = new List<ValidationResult> ();
287
288                         AssertExtensions.Throws<ArgumentException> (() => {
289                                 // MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty:
290                                 // System.ArgumentException : The type 'DummyNoAttributes' does not contain a public property named 'NameProperty'.
291                                 // Parameter name: propertyName
292                                 //
293                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.TypeStoreItem.GetPropertyStoreItem(String propertyName)
294                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.GetPropertyType(ValidationContext validationContext)
295                                 // at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
296                                 // at MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidatorTest.cs:line 283
297
298                                 Validator.TryValidateProperty ("dummy", ctx, results);
299                         }, "#A1-1");
300                         Assert.AreEqual (0, results.Count, "#A1-2");
301
302                         AssertExtensions.Throws<ArgumentNullException> (() => {
303                                 Validator.TryValidateProperty ("dummy", null, results);
304                         }, "#A1-2");
305
306                         var dummy2 = new Dummy ();
307                         ctx = new ValidationContext (dummy2, null, null) {
308                                 MemberName = "NameProperty"
309                         };
310                         
311                         bool valid = Validator.TryValidateProperty (null, ctx, results);
312                         Assert.IsTrue (valid, "#A1-3");
313                         Assert.AreEqual (0, results.Count, "#A1-4");
314
315                         ctx = new ValidationContext (dummy2, null, null) {
316                                 MemberName = "MinMaxProperty"
317                         };
318
319                         AssertExtensions.Throws<ArgumentException> (() => {
320                                 Validator.TryValidateProperty (null, ctx, results);
321                         }, "#A1-5");
322
323                         ctx = new ValidationContext (dummy2, null, null);
324                         AssertExtensions.Throws<ArgumentNullException> (() => {
325                                 // MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty:
326                                 // System.ArgumentNullException : Value cannot be null.
327                                 // Parameter name: propertyName
328                                 //
329                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.TypeStoreItem.TryGetPropertyStoreItem(String propertyName, PropertyStoreItem& item)
330                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.TypeStoreItem.GetPropertyStoreItem(String propertyName)
331                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.GetPropertyType(ValidationContext validationContext)
332                                 // at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
333                                 // at MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidatorTest.cs:line 289
334
335                                 Validator.TryValidateProperty ("dummy", ctx, results);
336                         }, "#A2-1");
337                         Assert.AreEqual (0, results.Count, "#A2-2");
338
339                         ctx = new ValidationContext (dummy2, null, null) {
340                                 MemberName = String.Empty
341                         };
342
343                         AssertExtensions.Throws<ArgumentNullException> (() => {
344                                 // MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty:
345                                 // System.ArgumentNullException : Value cannot be null.
346                                 // Parameter name: propertyName
347                                 //
348                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.TypeStoreItem.TryGetPropertyStoreItem(String propertyName, PropertyStoreItem& item)
349                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.TypeStoreItem.GetPropertyStoreItem(String propertyName)
350                                 // at System.ComponentModel.DataAnnotations.ValidationAttributeStore.GetPropertyType(ValidationContext validationContext)
351                                 // at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
352                                 // at MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidatorTest.cs:line 289
353
354                                 Validator.TryValidateProperty ("dummy", ctx, results);
355                         }, "#A2-2");
356                         Assert.AreEqual (0, results.Count, "#A2-2");
357
358                         dummy2 = new Dummy ();
359                         ctx = new ValidationContext (dummy2, null, null) {
360                                 MemberName = "NameProperty"
361                         };
362
363                         AssertExtensions.Throws<ArgumentException> (() => {
364                                 // MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty:
365                                 // System.ArgumentException : The value for property 'NameProperty' must be of type 'System.String'.
366                                 // Parameter name: value
367                                 //
368                                 // at System.ComponentModel.DataAnnotations.Validator.EnsureValidPropertyType(String propertyName, Type propertyType, Object value)
369                                 // at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
370                                 // at MonoTests.System.ComponentModel.DataAnnotations.ValidatorTest.TryValidateProperty() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidatorTest.cs:line 315
371
372                                 Validator.TryValidateProperty (1234, ctx, results);
373                         }, "#A3-1");
374                         Assert.AreEqual (0, results.Count, "#A3-2");
375
376                         dummy2 = new Dummy ();
377                         ctx = new ValidationContext (dummy2, null, null) {
378                                 MemberName = "NameProperty"
379                         };
380                         
381                         valid = Validator.TryValidateProperty (String.Empty, ctx, results);
382                         Assert.IsFalse (valid, "#A4-1");
383                         Assert.AreEqual (1, results.Count, "#A4-2");
384                         results.Clear ();
385
386                         valid = Validator.TryValidateProperty ("this value is way too long", ctx, results);
387                         Assert.IsFalse (valid, "#A4-3");
388                         Assert.AreEqual (1, results.Count, "#A4-4");
389                         results.Clear ();
390
391                         valid = Validator.TryValidateProperty ("good value", ctx, results);
392                         Assert.IsTrue (valid, "#A4-5");
393                         Assert.AreEqual (0, results.Count, "#A4-6");
394
395                         dummy2 = new Dummy ();
396                         ctx = new ValidationContext (dummy2, null, null) {
397                                 MemberName = "CustomValidatedProperty"
398                         };
399
400                         valid = Validator.TryValidateProperty (String.Empty, ctx, results);
401                         Assert.IsFalse (valid, "#A5-1");
402                         Assert.AreEqual (1, results.Count, "#A5-2");
403                         results.Clear ();
404
405                         valid = Validator.TryValidateProperty ("fail", ctx, results);
406                         Assert.IsFalse (valid, "#A5-3");
407                         Assert.AreEqual (1, results.Count, "#A5-4");
408                         results.Clear ();
409
410                         valid = Validator.TryValidateProperty ("f", ctx, results);
411                         Assert.IsFalse (valid, "#A5-5");
412                         Assert.AreEqual (2, results.Count, "#A5-6");
413                         results.Clear ();
414
415                         valid = Validator.TryValidateProperty ("good value", ctx, results);
416                         Assert.IsTrue (valid, "#A5-7");
417                         Assert.AreEqual (0, results.Count, "#A5-8");
418                 }
419
420                 [Test]
421                 public void TryValidateValue_01 ()
422                 {
423                         var dummy = new DummyNoAttributes ();
424                         var ctx = new ValidationContext (dummy, null, null) {
425                                 MemberName = "NameProperty"
426                         };
427                         var results = new List<ValidationResult> ();
428                         var attributes = new List <ValidationAttribute> ();
429                         
430                         bool valid = Validator.TryValidateValue (null, ctx, results, attributes);
431                         Assert.IsTrue (valid, "#A1-1");
432                         Assert.AreEqual (0, results.Count, "#A1-2");
433
434                         AssertExtensions.Throws<ArgumentNullException> (() => {
435                                 Validator.TryValidateValue ("dummy", null, results, attributes);
436                         }, "#A2");
437
438                         valid = Validator.TryValidateValue ("dummy", ctx, null, attributes);
439                         Assert.IsTrue (valid, "#A3-1");
440                         Assert.AreEqual (0, results.Count, "#A3-2");
441
442                         AssertExtensions.Throws<ArgumentNullException> (() => {
443                                 Validator.TryValidateValue ("dummy", ctx, results, null);
444                         }, "#A4");
445                 }
446
447                 [Test]
448                 public void TryValidateValue_02 ()
449                 {
450                         var dummy = new DummyNoAttributes ();
451                         var ctx = new ValidationContext (dummy, null, null);
452                         var results = new List<ValidationResult> ();
453                         var log = new List<string> ();
454                         var attributes = new List<ValidationAttribute> () {
455                                 new StringLengthAttributePoker (10, log) {
456                                         MinimumLength = 2
457                                 },
458                                 new RequiredAttributePoker (log)
459                         };
460
461                         bool valid = Validator.TryValidateValue (null, ctx, results, attributes);
462                         Assert.IsFalse (valid, "#A1-1");
463                         Assert.AreEqual (1, results.Count, "#A1-2");
464                         Assert.AreEqual (1, log.Count, "#A1-3");
465                         Assert.IsTrue (log [0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A1-4");
466                         results.Clear ();
467                         log.Clear ();
468
469                         AssertExtensions.Throws<InvalidCastException> (() => {
470                                 // Thrown by StringValidatorAttribute
471                                 Validator.TryValidateValue (1234, ctx, results, attributes);
472                         }, "#A2-1");
473                         Assert.AreEqual (0, results.Count, "#A2-2");
474                         Assert.AreEqual (2, log.Count, "#A2-3");
475                         Assert.IsTrue (log[0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A2-4");
476                         Assert.IsTrue (log[1].StartsWith ("StringLengthAttributePoker.IsValid (object)"), "#A2-5");
477                         results.Clear ();
478                         log.Clear ();
479
480                         attributes.Add (new CustomValidationAttribute (typeof (ValidatorTest), "ValueValidationMethod"));
481                         attributes.Add (new CustomValidationAttribute (typeof (ValidatorTest), "ValueValidationMethod"));
482                         valid = Validator.TryValidateValue ("test", ctx, results, attributes);
483                         Assert.IsFalse (valid, "#A3-1");
484                         Assert.AreEqual (2, results.Count, "#A3-2");
485                         Assert.AreEqual (2, log.Count, "#A3-3");
486                         Assert.IsTrue (log[0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A3-4");
487                         Assert.IsTrue (log[1].StartsWith ("StringLengthAttributePoker.IsValid (object)"), "#A3-5");
488                         Assert.AreEqual ("ValueValidationMethod", results[0].ErrorMessage, "#A3-6");
489                         Assert.AreEqual ("ValueValidationMethod", results[1].ErrorMessage, "#A3-7");
490                         results.Clear ();
491                         log.Clear ();
492                         attributes.RemoveAt (2);
493                         attributes.RemoveAt (2);
494
495                         AssertExtensions.Throws<ArgumentNullException> (() => {
496                                 Validator.TryValidateValue ("dummy", null, results, attributes);
497                         }, "#B1");
498
499                         valid = Validator.TryValidateValue ("dummy", ctx, null, attributes);
500                         Assert.IsTrue (valid, "#B2-1");
501                         Assert.AreEqual (0, results.Count, "#B2-2");
502
503                         AssertExtensions.Throws<ArgumentNullException> (() => {
504                                 Validator.TryValidateValue ("dummy", ctx, results, null);
505                         }, "#B3");
506                 }
507
508                 [Test]
509                 public void ValidateObject_Object_ValidationContext_01 ()
510                 {
511                         var dummy = new DummyNoAttributes ();
512                         var ctx = new ValidationContext (dummy, null, null);
513                         
514                         AssertExtensions.Throws<ArgumentNullException> (() => {
515                                 Validator.ValidateObject (null, ctx);
516                         }, "#A1-1");
517
518                         AssertExtensions.Throws<ArgumentNullException> (() => {
519                                 Validator.ValidateObject (dummy, null);
520                         }, "#A1-2");
521
522                         try {
523                                 Validator.ValidateObject (dummy, ctx);
524                         } catch (Exception ex) {
525                                 Assert.Fail ("#A2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
526                         }
527                 }
528
529                 [Test]
530                 public void ValidateObject_Object_ValidationContext_02 ()
531                 {
532                         var dummy = new Dummy ();
533                         var ctx = new ValidationContext (dummy, null, null);
534
535                         try {
536                                 Validator.ValidateObject (dummy, ctx);
537                         } catch (Exception ex) {
538                                 Assert.Fail ("#A1 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
539                         }
540
541                         dummy = new Dummy {
542                                 NameField = null
543                         };
544                         AssertExtensions.Throws<ArgumentException> (() => {
545                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
546                                 Validator.ValidateObject (dummy, ctx);
547                         }, "#A2");
548
549                         // Fields are ignored
550                         ctx = new ValidationContext (dummy, null, null);
551                         try {
552                                 Validator.ValidateObject (dummy, ctx);
553                         }  catch (Exception ex) {
554                                 Assert.Fail ("#A3 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
555                         }
556                         
557                         dummy = new Dummy {
558                                 RequiredDummyField = null
559                         };
560                         ctx = new ValidationContext (dummy, null, null);
561                         try {
562                                 Validator.ValidateObject (dummy, ctx);
563                         } catch (Exception ex) {
564                                 Assert.Fail ("#A4 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
565                         }
566
567                         dummy = new Dummy {
568                                 RequiredDummyProperty = null
569                         };
570                         ctx = new ValidationContext (dummy, null, null);
571                         AssertExtensions.Throws<ValidationException> (() => {
572                                 Validator.ValidateObject (dummy, ctx);
573                         }, "#A5");
574
575                         // validation attributes other than Required are ignored
576                         dummy = new Dummy {
577                                 NameProperty = null
578                         };
579                         ctx = new ValidationContext (dummy, null, null);
580                         try {
581                                 Validator.ValidateObject (dummy, ctx);
582                         } catch (Exception ex) {
583                                 Assert.Fail ("#A6 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
584                         }
585                         
586                         dummy = new Dummy {
587                                 MinMaxProperty = 0
588                         };
589                         ctx = new ValidationContext (dummy, null, null);
590                         try {
591                                 Validator.ValidateObject (dummy, ctx);
592                         } catch (Exception ex) {
593                                 Assert.Fail ("#A7 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
594                         }
595
596                         dummy = new Dummy {
597                                 FailValidation = true
598                         };
599                         ctx = new ValidationContext (dummy, null, null);
600                         AssertExtensions.Throws<ValidationException> (() => {
601                                 Validator.ValidateObject (dummy, ctx);
602                         }, "#A8");
603
604                         var dummy2 = new DummyMultipleCustomValidators ();
605                         ctx = new ValidationContext (dummy2, null, null);
606                         try {
607                                 Validator.ValidateObject (dummy2, ctx);
608                         } catch (Exception ex) {
609                                 Assert.Fail ("#A9 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
610                         }
611                 }
612
613                 [Test]
614                 public void ValidateObject_Object_ValidationContext_Bool_01 ()
615                 {
616                         var dummy = new DummyNoAttributes ();
617                         var ctx = new ValidationContext (dummy, null, null);
618
619                         AssertExtensions.Throws<ArgumentNullException> (() => {
620                                 Validator.ValidateObject (null, ctx, false);
621                         }, "#A1-1");
622
623                         AssertExtensions.Throws<ArgumentNullException> (() => {
624                                 Validator.ValidateObject (dummy, null, false);
625                         }, "#A1-2");
626
627                         try {
628                                 Validator.ValidateObject (dummy, ctx, false);
629                         } catch (Exception ex) {
630                                 Assert.Fail ("#A2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
631                         }
632
633                         try {
634                                 Validator.ValidateObject (dummy, ctx, true);
635                         } catch (Exception ex) {
636                                 Assert.Fail ("#A3 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
637                         }
638                 }
639
640                 [Test]
641                 public void ValidateObject_Object_ValidationContext_Bool_02 ()
642                 {
643                         var dummy = new Dummy ();
644                         var ctx = new ValidationContext (dummy, null, null);
645
646                         try {
647                                 Validator.ValidateObject (dummy, ctx, false);
648                         } catch (Exception ex) {
649                                 Assert.Fail ("#A1 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
650                         }
651
652                         try {
653                                 Validator.ValidateObject (dummy, ctx, true);
654                         } catch (Exception ex) {
655                                 Assert.Fail ("#A2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
656                         }
657
658                         dummy = new Dummy {
659                                 NameField = null
660                         };
661                         AssertExtensions.Throws<ArgumentException> (() => {
662                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
663                                 Validator.ValidateObject (dummy, ctx, false);
664                         }, "#A3-1");
665
666                         AssertExtensions.Throws<ArgumentException> (() => {
667                                 // The instance provided must match the ObjectInstance on the ValidationContext supplied.
668                                 Validator.ValidateObject (dummy, ctx, true);
669                         }, "#A3-2");
670
671                         // Fields are ignored
672                         ctx = new ValidationContext (dummy, null, null);
673                         try {
674                                 Validator.ValidateObject (dummy, ctx, false);
675                         } catch (Exception ex) {
676                                 Assert.Fail ("#A4-1 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
677                         }
678
679                         try {
680                                 Validator.ValidateObject (dummy, ctx, true);
681                         } catch (Exception ex) {
682                                 Assert.Fail ("#A4-2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
683                         }
684
685                         dummy = new Dummy {
686                                 RequiredDummyField = null
687                         };
688                         ctx = new ValidationContext (dummy, null, null);
689                         try {
690                                 Validator.ValidateObject (dummy, ctx, false);
691                         } catch (Exception ex) {
692                                 Assert.Fail ("#A5-1 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
693                         }
694
695                         try {
696                                 Validator.ValidateObject (dummy, ctx, true);
697                         } catch (Exception ex) {
698                                 Assert.Fail ("#A5-2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
699                         }
700
701                         // Required properties existence is validated
702                         dummy = new Dummy {
703                                 RequiredDummyProperty = null
704                         };
705                         ctx = new ValidationContext (dummy, null, null);
706                         AssertExtensions.Throws<ValidationException> (() => {
707                                 Validator.ValidateObject (dummy, ctx, false);
708                         }, "#A6-1");
709
710                         AssertExtensions.Throws<ValidationException> (() => {
711                                 Validator.ValidateObject (dummy, ctx, true);
712                         }, "#A6-2");
713
714                         dummy = new Dummy {
715                                 NameProperty = null
716                         };
717                         ctx = new ValidationContext (dummy, null, null);
718                         try {
719                                 Validator.ValidateObject (dummy, ctx, false);
720                         } catch (Exception ex) {
721                                 Assert.Fail ("#A7 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
722                         }
723
724                         // NameProperty is null, that causes the StringLength validator to skip its tests
725                         try {
726                                 Validator.ValidateObject (dummy, ctx, true);
727                         } catch (Exception ex) {
728                                 Assert.Fail ("#A8 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
729                         }
730
731                         dummy.NameProperty = "0";
732                         AssertExtensions.Throws<ValidationException> (() => {
733                                 Validator.ValidateObject (dummy, ctx, true);
734                         }, "#A9");
735
736                         dummy.NameProperty = "name too long (invalid value)";
737                         AssertExtensions.Throws<ValidationException> (() => {
738                                 Validator.ValidateObject (dummy, ctx, true);
739                         }, "#A10");
740
741                         dummy = new Dummy {
742                                 MinMaxProperty = 0
743                         };
744                         ctx = new ValidationContext (dummy, null, null);
745                         try {
746                                 Validator.ValidateObject (dummy, ctx, false);
747                         } catch (Exception ex) {
748                                 Assert.Fail ("#A11 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
749                         }
750
751                         AssertExtensions.Throws<ValidationException> (() => {
752                                 Validator.ValidateObject (dummy, ctx, true);
753                         }, "#A12");
754
755                         dummy = new Dummy {
756                                 FailValidation = true
757                         };
758                         ctx = new ValidationContext (dummy, null, null);
759                         AssertExtensions.Throws<ValidationException> (() => {
760                                 Validator.ValidateObject (dummy, ctx, false);
761                         }, "#A13-1");
762
763                         AssertExtensions.Throws<ValidationException> (() => {
764                                 Validator.ValidateObject (dummy, ctx, true);
765                         }, "#A13-2");
766
767                         var dummy2 = new DummyWithException ();
768                         ctx = new ValidationContext (dummy2, null, null);
769                         AssertExtensions.Throws<ApplicationException> (() => {
770                                 Validator.ValidateObject (dummy2, ctx, true);
771                         }, "#A14");
772
773                         var dummy3 = new DummyMultipleCustomValidators ();
774                         ctx = new ValidationContext (dummy3, null, null);
775                         try {
776                                 Validator.ValidateObject (dummy3, ctx, false);
777                         } catch (Exception ex) {
778                                 Assert.Fail ("#A9 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
779                         }
780
781                         try {
782                                 Validator.ValidateObject (dummy3, ctx, true);
783                         } catch (ValidationException ex) {
784                                 Assert.AreEqual ("FirstPropertyValidationMethod", ex.Message, "#A10");
785                         } catch (Exception ex) {
786                                 Assert.Fail ("#A10 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
787                         }
788                 }
789
790                 [Test]
791                 public void ValidateProperty ()
792                 {
793                         var dummy = new DummyNoAttributes ();
794                         var ctx = new ValidationContext (dummy, null, null) {
795                                 MemberName = "NameProperty"
796                         };
797
798                         AssertExtensions.Throws<ArgumentException> (() => {
799                                 Validator.ValidateProperty ("dummy", ctx);
800                         }, "#A1-1");
801
802                         AssertExtensions.Throws<ArgumentNullException> (() => {
803                                 Validator.ValidateProperty ("dummy", null);
804                         }, "#A1-2");
805
806                         var dummy2 = new Dummy ();
807                         ctx = new ValidationContext (dummy2, null, null) {
808                                 MemberName = "NameProperty"
809                         };
810
811                         try {
812                                 Validator.ValidateProperty (null, ctx);
813                         } catch (Exception ex) {
814                                 Assert.Fail ("#A2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
815                         }
816
817                         ctx = new ValidationContext (dummy2, null, null) {
818                                 MemberName = "MinMaxProperty"
819                         };
820
821                         AssertExtensions.Throws<ArgumentException> (() => {
822                                 Validator.ValidateProperty (null, ctx);
823                         }, "#A3");
824
825                         ctx = new ValidationContext (dummy2, null, null);
826                         AssertExtensions.Throws<ArgumentNullException> (() => {
827                                 Validator.ValidateProperty ("dummy", ctx);
828                         }, "#A4");
829
830                         ctx = new ValidationContext (dummy2, null, null) {
831                                 MemberName = String.Empty
832                         };
833
834                         AssertExtensions.Throws<ArgumentNullException> (() => {
835                                 Validator.ValidateProperty ("dummy", ctx);
836                         }, "#A5");
837
838                         dummy2 = new Dummy ();
839                         ctx = new ValidationContext (dummy2, null, null) {
840                                 MemberName = "NameProperty"
841                         };
842
843                         AssertExtensions.Throws<ArgumentException> (() => {
844                                 Validator.ValidateProperty (1234, ctx);
845                         }, "#A6");
846
847                         dummy2 = new Dummy ();
848                         ctx = new ValidationContext (dummy2, null, null) {
849                                 MemberName = "NameProperty"
850                         };
851
852                         AssertExtensions.Throws<ValidationException> (() => {
853                                 Validator.ValidateProperty (String.Empty, ctx);
854                         }, "#A7");
855
856                         AssertExtensions.Throws<ValidationException> (() => {
857                                 Validator.ValidateProperty ("this value is way too long", ctx);
858                         }, "#A8");
859
860                         try {
861                                 Validator.ValidateProperty ("good value", ctx);
862                         } catch (Exception ex) {
863                                 Assert.Fail ("#A9 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
864                         }
865
866                         dummy2 = new Dummy ();
867                         ctx = new ValidationContext (dummy2, null, null) {
868                                 MemberName = "CustomValidatedProperty"
869                         };
870
871                         AssertExtensions.Throws<ValidationException> (() => {
872                                 Validator.ValidateProperty (String.Empty, ctx);
873                         }, "#A10");
874
875                         AssertExtensions.Throws<ValidationException> (() => {
876                                 Validator.ValidateProperty ("fail", ctx);
877                         }, "#A11");
878
879                         AssertExtensions.Throws<ValidationException> (() => {
880                                 Validator.ValidateProperty ("f", ctx);
881                         }, "#A12");
882
883                         try {
884                                 Validator.ValidateProperty ("good value", ctx);
885                         } catch (Exception ex) {
886                                 Assert.Fail ("#A13 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
887                         }
888                 }
889
890                 [Test]
891                 public void ValidateValue_01 ()
892                 {
893                         var dummy = new DummyNoAttributes ();
894                         var ctx = new ValidationContext (dummy, null, null) {
895                                 MemberName = "NameProperty"
896                         };
897                         var attributes = new List<ValidationAttribute> ();
898
899                         try {
900                                 Validator.ValidateValue (null, ctx, attributes);
901                         } catch (Exception ex) {
902                                 Assert.Fail ("#A1 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
903                         }
904
905                         AssertExtensions.Throws<ArgumentNullException> (() => {
906                                 Validator.ValidateValue ("dummy", null, attributes);
907                         }, "#A2");
908
909                         try {
910                                 Validator.ValidateValue ("dummy", ctx, attributes);
911                         } catch (Exception ex) {
912                                 Assert.Fail ("#A3 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
913                         }
914
915                         AssertExtensions.Throws<ArgumentNullException> (() => {
916                                 Validator.ValidateValue ("dummy", ctx, null);
917                         }, "#A4");
918                 }
919
920                 [Test]
921                 public void ValidateValue_02 ()
922                 {
923                         var dummy = new DummyNoAttributes ();
924                         var ctx = new ValidationContext (dummy, null, null);
925                         var log = new List<string> ();
926                         var attributes = new List<ValidationAttribute> () {
927                                 new StringLengthAttributePoker (10, log) {
928                                         MinimumLength = 2
929                                 },
930                                 new RequiredAttributePoker (log)
931                         };
932
933                         AssertExtensions.Throws<ValidationException> (() => {
934                                 Validator.ValidateValue (null, ctx, attributes);
935                         }, "#A1-1");
936                         Assert.AreEqual (1, log.Count, "#A1-2");
937                         Assert.IsTrue (log[0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A1-3");
938                         log.Clear ();
939
940                         AssertExtensions.Throws<InvalidCastException> (() => {
941                                 // Thrown by StringValidatorAttribute
942                                 Validator.ValidateValue (1234, ctx, attributes);
943                         }, "#A2-1");;
944                         Assert.AreEqual (2, log.Count, "#A2-2");
945                         Assert.IsTrue (log[0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A2-3");
946                         Assert.IsTrue (log[1].StartsWith ("StringLengthAttributePoker.IsValid (object)"), "#A2-4");
947                         log.Clear ();
948
949                         attributes.Add (new CustomValidationAttribute (typeof (ValidatorTest), "ValueValidationMethod"));
950                         attributes.Add (new CustomValidationAttribute (typeof (ValidatorTest), "ValueValidationMethod"));
951                         AssertExtensions.Throws<ValidationException> (() => {
952                                 Validator.ValidateValue ("test", ctx, attributes);
953                         }, "#A3-1");
954                         Assert.AreEqual (2, log.Count, "#A3-2");
955                         Assert.IsTrue (log[0].StartsWith ("RequiredAttributePoker.IsValid (object)"), "#A3-3");
956                         Assert.IsTrue (log[1].StartsWith ("StringLengthAttributePoker.IsValid (object)"), "#A3-4");
957                         log.Clear ();
958                         attributes.RemoveAt (2);
959                         attributes.RemoveAt (2);
960
961                         AssertExtensions.Throws<ArgumentNullException> (() => {
962                                 Validator.ValidateValue ("dummy", null, attributes);
963                         }, "#B1");
964
965                         try {
966                                 Validator.ValidateValue ("dummy", ctx, attributes);
967                         } catch (Exception ex) {
968                                 Assert.Fail ("#B2 (exception {0} thrown: {1})", ex.GetType (), ex.Message);
969                         }
970
971                         AssertExtensions.Throws<ArgumentNullException> (() => {
972                                 Validator.ValidateValue ("dummy", ctx, null);
973                         }, "#B3");
974                 }
975
976                 public static ValidationResult DummyValidationMethod (object o)
977                 {
978                         var dummy = o as Dummy;
979                         if (dummy == null)
980                                 return new ValidationResult ("Invalid DummyValidationMethod input - broken test?");
981
982                         if (dummy.FailValidation)
983                                 return new ValidationResult ("Dummy validation failed.");
984                         return ValidationResult.Success;
985                 }
986
987                 public static ValidationResult CustomValidatedPropertyValidationMethod (object o)
988                 {
989                         var dummy = o as string;
990                         if (dummy != null && (dummy == "f" || dummy == "fail"))
991                                 return new ValidationResult ("Dummy.CustomValidatedProperty validation failed.");
992                         return ValidationResult.Success;
993                 }
994
995                 public static ValidationResult ValidationMethodException (object o)
996                 {
997                         throw new ApplicationException ("SNAFU");
998                 }
999
1000                 public static ValidationResult ValueValidationMethod (object o, ValidationContext validationContext)
1001                 {
1002                         return new ValidationResult ("ValueValidationMethod");
1003                 }
1004
1005                 public static ValidationResult FirstPropertyValidationMethod (object o, ValidationContext validationContext)
1006                 {
1007                         return new ValidationResult ("FirstPropertyValidationMethod");
1008                 }
1009
1010                 public static ValidationResult SecondPropertyValidationMethod (object o, ValidationContext validationContext)
1011                 {
1012                         return new ValidationResult ("SecondPropertyValidationMethod");
1013                 }
1014
1015                 public class RequiredAttributePoker : RequiredAttribute
1016                 {
1017                         List <string> log;
1018
1019                         public RequiredAttributePoker (List<string> log)
1020                         {
1021                                 if (log == null)
1022                                         throw new ArgumentNullException ("log");
1023                                 this.log = log;
1024                         }
1025
1026                         public override bool IsValid (object value)
1027                         {
1028                                 log.Add ("RequiredAttributePoker.IsValid (object)");
1029                                 return base.IsValid (value);
1030                         }
1031                 }
1032
1033                 public class StringLengthAttributePoker : StringLengthAttribute
1034                 {
1035                         List <string> log;
1036
1037                         public StringLengthAttributePoker (int maximumLength, List<string> log)
1038                                 : base (maximumLength)
1039                         {
1040                                 if (log == null)
1041                                         throw new ArgumentNullException ("log");
1042                                 this.log = log;
1043                         }
1044
1045                         public override bool IsValid (object value)
1046                         {
1047                                 log.Add ("StringLengthAttributePoker.IsValid (object)");
1048                                 return base.IsValid (value);
1049                         }
1050                 }
1051
1052                 class DummyNoAttributes
1053                 { }
1054
1055                 [CustomValidation (typeof (ValidatorTest), "DummyValidationMethod")]
1056                 class Dummy
1057                 {
1058                         [StringLength (10, MinimumLength=2)]
1059                         public string NameField;
1060
1061                         [Required]
1062                         public DummyNoAttributes RequiredDummyField;
1063
1064                         [StringLength (10, MinimumLength = 2)]
1065                         public string NameProperty { get; set; }
1066
1067                         [Required]
1068                         public DummyNoAttributes RequiredDummyProperty { get; set; }
1069                         
1070                         [global::System.ComponentModel.DataAnnotations.RangeAttribute ((int)1, (int)10)]
1071                         public int MinMaxProperty { get; set; }
1072
1073                         [StringLength (10, MinimumLength = 2)]
1074                         [CustomValidation (typeof (ValidatorTest), "CustomValidatedPropertyValidationMethod")]
1075                         public string CustomValidatedProperty { get; set; }
1076
1077                         [CustomValidation (typeof (ValidatorTest), "CustomValidatedPropertyValidationMethod")]
1078                         [StringLength (10, MinimumLength = 2)]
1079                         public string AnotherCustomValidatedProperty { get; set; }
1080
1081                         public bool FailValidation { get; set; }
1082
1083                         public Dummy ()
1084                         {
1085                                 NameField = "name";
1086                                 NameProperty = "name";
1087                                 RequiredDummyField = new DummyNoAttributes ();
1088                                 RequiredDummyProperty = new DummyNoAttributes ();
1089                                 MinMaxProperty = 5;
1090                                 AnotherCustomValidatedProperty = "I'm valid";
1091                         }
1092                 }
1093
1094                 class DummyWithException
1095                 {
1096                         [CustomValidation (typeof (ValidatorTest), "ValidationMethodException")]
1097                         public string AnotherCustomValidatedProperty { get; set; }
1098                 }
1099
1100                 class DummyForValueValidation
1101                 {
1102                         public string DummyNoAttributes;
1103
1104                         public DummyForValueValidation ()
1105                         {
1106                                 this.DummyNoAttributes = "I am valid";
1107                         }
1108                 }
1109
1110                 class DummyMultipleCustomValidators
1111                 {
1112                         [CustomValidation (typeof (ValidatorTest), "FirstPropertyValidationMethod")]
1113                         public string FirstProperty { get; set; }
1114
1115                         [CustomValidation (typeof (ValidatorTest), "SecondPropertyValidationMethod")]
1116                         public string SecondProperty { get; set; }
1117                 }
1118         }
1119 #endif
1120 }