2 // ValidationAttributeTest.cs
5 // Marek Habersack <mhabersack@novell.com>
7 // Copyright (C) 2010 Novell, Inc. (http://novell.com/)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.ComponentModel.DataAnnotations;
33 using NUnit.Framework;
34 using MonoTests.Common;
36 namespace MonoTests.System.ComponentModel.DataAnnotations
39 public class ValidationAttributeTest
41 const string TEST_ERROR_MESSAGE = "Test Error Message";
42 string ErrorMessageAccessor ()
44 return TEST_ERROR_MESSAGE;
48 public void Constructor ()
50 var attr = new ValidateFooAttribute ();
52 Assert.IsNull (attr.ErrorMessage, "#A1");
53 Assert.IsNull (attr.ErrorMessageResourceName, "#A2");
54 Assert.IsNull (attr.ErrorMessageResourceType, "#A3");
55 Assert.IsNotNull (attr.GetErrorMessageString (), "#A4");
59 public void Constructor_Func ()
61 var attr = new ValidateFooAttribute (ErrorMessageAccessor);
63 Assert.IsNull (attr.ErrorMessage, "#A1");
64 Assert.IsNull (attr.ErrorMessageResourceName, "#A2");
65 Assert.IsNull (attr.ErrorMessageResourceType, "#A3");
66 Assert.IsNotNull (attr.GetErrorMessageString (), "#A4");
67 Assert.AreEqual (TEST_ERROR_MESSAGE, attr.GetErrorMessageString (), "#A4");
71 public void Constructor_String ()
73 var attr = new ValidateFooAttribute ("Another Test Error Message");
75 Assert.IsNull (attr.ErrorMessage, "#A1");
76 Assert.IsNull (attr.ErrorMessageResourceName, "#A2");
77 Assert.IsNull (attr.ErrorMessageResourceType, "#A3");
78 Assert.IsNotNull (attr.GetErrorMessageString (), "#A4");
79 Assert.IsNotNull (attr.GetErrorMessageString (), "#A4-1");
80 Assert.AreEqual ("Another Test Error Message", attr.GetErrorMessageString (), "#A4-2");
84 public void ErrorMessage ()
86 var attr = new ValidateFooAttribute ();
88 Assert.IsNull (attr.ErrorMessage, "#A1");
90 attr.ErrorMessage = "Test";
91 Assert.AreEqual ("Test", attr.ErrorMessage, "#A2");
92 attr.ErrorMessage = String.Empty;
93 Assert.AreEqual (String.Empty, attr.ErrorMessage, "#A3");
95 attr.ErrorMessage = null;
96 Assert.IsNull (attr.ErrorMessage, "#A4");
101 public void ErrorMessageResourceName ()
103 var attr = new ValidateFooAttribute ();
105 Assert.IsNull (attr.ErrorMessageResourceName, "#A1");
107 attr.ErrorMessageResourceName = "Test";
108 Assert.IsNotNull (attr.ErrorMessageResourceName, "#A2-1");
109 Assert.AreEqual ("Test", attr.ErrorMessageResourceName, "#A2-2");
110 attr.ErrorMessageResourceName = String.Empty;
111 Assert.IsNotNull (attr.ErrorMessageResourceName, "#A3-1");
112 Assert.AreEqual (String.Empty, attr.ErrorMessageResourceName, "#A3-2");
114 attr.ErrorMessageResourceName = null;
115 Assert.IsNull (attr.ErrorMessageResourceName, "#A3-1");
119 public void ErrorMessageResourceType ()
121 var attr = new ValidateFooAttribute ();
123 Assert.IsNull (attr.ErrorMessageResourceType, "#A1");
125 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
126 Assert.IsNotNull (attr.ErrorMessageResourceType, "#A2-1");
127 Assert.AreEqual (typeof (FooErrorMessageProvider), attr.ErrorMessageResourceType, "#A2-2");
131 public void ErrorMessageString ()
133 var attr = new ValidateFooAttribute ();
135 Assert.IsNotNull (attr.GetErrorMessageString (), "#A1-1");
136 Assert.IsTrue (attr.GetErrorMessageString ().Length > 0, "#A1-2");
138 attr = new ValidateFooAttribute ();
139 attr.ErrorMessageResourceName = "TestResource";
141 attr.GetErrorMessageString ();
142 Assert.Fail ("#A2-1");
143 } catch (InvalidOperationException) {
146 attr = new ValidateFooAttribute ();
147 attr.ErrorMessageResourceName = String.Empty;
149 attr.GetErrorMessageString ();
150 Assert.Fail ("#A2-1");
151 } catch (InvalidOperationException) {
155 attr = new ValidateFooAttribute ();
156 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
157 attr.ErrorMessageResourceName = null;
160 attr.GetErrorMessageString ();
161 Assert.Fail ("#A3-1");
162 } catch (InvalidOperationException) {
166 attr = new ValidateFooAttribute ();
167 attr.ErrorMessageResourceName = String.Empty;
168 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
170 string s = attr.GetErrorMessageString ();
171 Assert.Fail ("#A3-2");
172 } catch (InvalidOperationException) {
176 attr = new ValidateFooAttribute ();
177 attr.ErrorMessageResourceName = "NoSuchProperty";
178 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
180 attr.GetErrorMessageString ();
182 } catch (InvalidOperationException) {
186 attr = new ValidateFooAttribute ();
187 attr.ErrorMessageResourceName = "ErrorProperty2";
188 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
190 attr.GetErrorMessageString ();
192 } catch (InvalidOperationException) {
196 attr = new ValidateFooAttribute ();
197 attr.ErrorMessageResourceName = "ErrorProperty3";
198 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
200 attr.GetErrorMessageString ();
202 } catch (InvalidOperationException) {
206 attr = new ValidateFooAttribute ();
207 attr.ErrorMessageResourceName = "ErrorProperty4";
208 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
210 attr.GetErrorMessageString ();
212 } catch (InvalidOperationException) {
216 attr = new ValidateFooAttribute ();
217 attr.ErrorMessageResourceName = "ErrorProperty5";
218 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
220 attr.GetErrorMessageString ();
222 } catch (InvalidOperationException) {
226 attr = new ValidateFooAttribute ();
227 attr.ErrorMessageResourceName = "ErrorField1";
228 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
230 attr.GetErrorMessageString ();
232 } catch (InvalidOperationException) {
236 attr = new ValidateFooAttribute ();
237 attr.ErrorMessageResourceName = "ErrorField2";
238 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
240 attr.GetErrorMessageString ();
242 } catch (InvalidOperationException) {
246 attr = new ValidateFooAttribute ();
247 attr.ErrorMessageResourceName = "ErrorProperty1";
248 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
249 Assert.IsNotNull (attr.GetErrorMessageString (), "#C1-1");
250 Assert.AreEqual ("Error Message 1", attr.GetErrorMessageString (), "#C1-2");
252 attr = new ValidateFooAttribute (ErrorMessageAccessor);
253 Assert.IsNotNull (attr.GetErrorMessageString (), "#D1-1");
254 Assert.AreEqual (TEST_ERROR_MESSAGE, attr.GetErrorMessageString (), "#D1-2");
256 attr = new ValidateFooAttribute ();
257 attr.ErrorMessageResourceName = "ErrorProperty1";
258 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
259 Assert.IsNotNull (attr.GetErrorMessageString (), "#D1-3");
260 Assert.AreEqual ("Error Message 1", attr.GetErrorMessageString (), "#D1-4");
261 attr.ErrorMessage = "Test Message";
263 attr.GetErrorMessageString ();
265 } catch (InvalidOperationException) {
271 public void FormatErrorMessage ()
273 var attr = new ValidateFooAttribute ();
275 Assert.IsNotNull (attr.FormatErrorMessage ("SomeField"), "#A1-1");
276 Assert.AreEqual ("The field SomeField is invalid.", attr.FormatErrorMessage ("SomeField"), "#A1-2");
278 attr.ErrorMessage = "Test: {0}";
279 Assert.IsNotNull (attr.FormatErrorMessage ("SomeField"), "#A2-1");
280 Assert.AreEqual ("Test: SomeField", attr.FormatErrorMessage ("SomeField"), "#A2-2");
281 attr.ErrorMessage = null;
282 attr.ErrorMessageResourceName = "ErrorProperty1";
283 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
284 Assert.IsNotNull (attr.FormatErrorMessage ("SomeField"), "#B1-1");
285 Assert.AreEqual ("Error Message 1", attr.FormatErrorMessage ("SomeField"), "#B1-2");
286 attr.ErrorMessageResourceName = "ErrorProperty6";
287 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
288 Assert.IsNotNull (attr.FormatErrorMessage ("SomeField"), "#B2-1");
289 Assert.AreEqual ("Error Message 6: SomeField", attr.FormatErrorMessage ("SomeField"), "#B2-2");
290 attr.ErrorMessageResourceName = "ErrorProperty6";
291 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
292 Assert.IsNotNull (attr.FormatErrorMessage ("SomeField"), "#B3-1");
293 Assert.AreEqual ("Error Message 6: ", attr.FormatErrorMessage (null), "#B3-2");
296 public void GetValidationResult ()
298 var attr = new ValidateBarAttribute ();
301 attr.GetValidationResult ("stuff", null);
303 } catch (ArgumentNullException) {
307 var vc = new ValidationContext ("stuff", null, null);
308 vc.DisplayName = "MyStuff";
309 var vr = attr.GetValidationResult ("stuff", vc);
310 Assert.IsNull (vr, "#A2");
312 vr = attr.GetValidationResult (null, vc);
313 Assert.IsNotNull(vr, "#A3-1");
314 Assert.IsNotNull (vr.ErrorMessage, "#A3-2");
315 Assert.AreEqual ("The field MyStuff is invalid.", vr.ErrorMessage, "#A3-3");
317 attr.ErrorMessage = "My Error Message: {0}";
318 vr = attr.GetValidationResult (null, vc);
319 Assert.IsNotNull (vr, "#A4-1");
320 Assert.IsNotNull (vr.ErrorMessage, "#A4-2");
321 Assert.AreEqual ("My Error Message: MyStuff", vr.ErrorMessage, "#A4-3");
323 attr.ErrorMessage = null;
324 attr.ErrorMessageResourceName = "ErrorProperty1";
325 attr.ErrorMessageResourceType = typeof (FooErrorMessageProvider);
326 vr = attr.GetValidationResult (null, vc);
327 Assert.IsNotNull (vr, "#A5-1");
328 Assert.IsNotNull (vr.ErrorMessage, "#A5-2");
329 Assert.AreEqual ("Error Message 1", vr.ErrorMessage, "#A5-3");
331 attr.ErrorMessage = "My Error Message: {0}";
332 attr.ErrorMessageResourceName = null;
333 attr.ErrorMessageResourceType = null;
334 vr = attr.GetValidationResult (null, vc);
335 Assert.IsNotNull (vr, "#A6-1");
336 Assert.IsNotNull (vr.MemberNames, "#A6-2");
338 foreach (string s in vr.MemberNames)
340 Assert.AreEqual (0, count, "#A6-3");
341 Assert.AreEqual ("My Error Message: MyStuff", vr.ErrorMessage, "#A6-4");
343 attr.ValidationResultErrorMessage = "My VR message";
344 vr = attr.GetValidationResult (null, vc);
345 Assert.IsNotNull (vr, "#A7-1");
346 Assert.AreEqual ("My VR message", vr.ErrorMessage, "#A7-2");
350 public void IsValid_Object ()
352 var attr = new ValidateFooAttribute ();
354 AssertExtensions.Throws <NotImplementedException> (() => {
355 // It calls IsValid (object, validationContext) which throws the NIEX, but when that overload is called directly, there's
358 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext)
359 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value)
360 // at MonoTests.System.ComponentModel.DataAnnotations.ValidationAttributeTest.IsValid_Object() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 450
364 AssertExtensions.Throws <NotImplementedException> (() => {
365 attr.IsValid ("stuff");
370 public void IsValid_Object_ValidationContext ()
372 var attr = new ValidateBarAttribute ();
374 AssertExtensions.Throws <NullReferenceException> (() => {
375 attr.CallIsValid (null, null);
378 var vc = new ValidationContext ("stuff", null, null);
379 var vr = attr.CallIsValid (null, vc);
380 Assert.IsNotNull (vr, "#A2-1");
381 Assert.IsNotNull (vr.ErrorMessage, "#A2-2");
382 Assert.AreEqual ("The field String is invalid.", vr.ErrorMessage, "#A2-3");
383 Assert.IsNotNull (vr.MemberNames, "#A2-4");
386 foreach (string s in vr.MemberNames)
388 Assert.AreEqual (0, count, "#A2-5");
390 vc.MemberName = "SomeMember";
391 vr = attr.CallIsValid (null, vc);
392 Assert.IsNotNull (vr, "#A3-1");
393 Assert.IsNotNull (vr.ErrorMessage, "#A3-2");
394 Assert.AreEqual ("The field String is invalid.", vr.ErrorMessage, "#A3-3");
395 Assert.IsNotNull (vr.MemberNames, "#A3-4");
397 var list = new List <string> ();
398 foreach (string s in vr.MemberNames)
400 Assert.AreEqual (1, list.Count, "#A3-5");
401 Assert.AreEqual ("SomeMember", list [0], "#A3-6");
405 public void IsValid_Object_ValidationContext_CrossCallsWithNIEX ()
407 var attr = new ValidateSomethingAttribute ();
409 AssertExtensions.Throws<NotImplementedException> (() => {
410 // Thrown from the IsValid (object, ValidationContext) overload!
412 // MonoTests.System.ComponentModel.DataAnnotations.ValidationAttributeTest.IsValid_Object_ValidationContext_02:
413 // System.NotImplementedException : IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context).
415 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext)
416 // at MonoTests.System.ComponentModel.DataAnnotations.ValidateSomethingAttribute.IsValid(Object value) in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 639
417 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext)
418 // at MonoTests.System.ComponentModel.DataAnnotations.ValidateSomethingAttribute.IsValid(Object value) in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 639
419 // at MonoTests.System.ComponentModel.DataAnnotations.ValidationAttributeTest.IsValid_Object_ValidationContext_02() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 514
420 attr.IsValid ("stuff");
423 AssertExtensions.Throws<NotImplementedException> (() => {
424 // And this one is thrown from the IsValid (object) overload!
426 // MonoTests.System.ComponentModel.DataAnnotations.ValidationAttributeTest.IsValid_Object_ValidationContext_CrossCallsWithNIEX:
427 // System.NotImplementedException : IsValid(object value) has not been implemented by this class. The preferred entry point is GetValidationResult() and classes should override IsValid(object value, ValidationContext context).
429 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value)
430 // at MonoTests.System.ComponentModel.DataAnnotations.ValidateSomethingAttribute.IsValid(Object value, ValidationContext validationContext) in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 660
431 // at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value)
432 // at MonoTests.System.ComponentModel.DataAnnotations.ValidateSomethingAttribute.IsValid(Object value, ValidationContext validationContext) in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 660
433 // at MonoTests.System.ComponentModel.DataAnnotations.ValidateSomethingAttribute.CallIsValid(Object value, ValidationContext validationContext) in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 667
434 // at MonoTests.System.ComponentModel.DataAnnotations.ValidationAttributeTest.IsValid_Object_ValidationContext_CrossCallsWithNIEX() in C:\Users\grendel\Documents\Visual Studio 2010\Projects\System.Web.Test\System.Web.Test\System.ComponentModel.DataAnnotations\ValidationAttributeTest.cs:line 530
436 attr.CallIsValid ("stuff", null);
440 public void Validate_Object_ValidationContext ()
442 var attr = new ValidateBazAttribute ();
445 attr.Validate ("stuff", (ValidationContext) null);
447 } catch (ArgumentNullException) {
451 var vc = new ValidationContext ("stuff", null, null);
453 attr.Validate (null, vc);
454 Assert.Fail ("#A2-1");
455 } catch (ValidationException) {
458 Assert.AreEqual (3, attr.Calls.Count, "#A2-1");
459 Assert.AreEqual ("ValidationResult IsValid (object value, ValidationContext validationContext)", attr.Calls [0], "#A2-2");
460 Assert.AreEqual ("bool IsValid (object value)", attr.Calls [1], "#A2-3");
461 Assert.AreEqual ("string FormatErrorMessage (string name)", attr.Calls [2], "#A2-4");
464 public void Validate_Object_String ()
466 var attr = new ValidateBazAttribute ();
469 attr.Validate (null, (string) null);
471 } catch (ValidationException) {
475 Assert.AreEqual (2, attr.Calls.Count, "#A2-1");
476 Assert.AreEqual ("bool IsValid (object value)", attr.Calls [0], "#A2-2");
477 Assert.AreEqual ("string FormatErrorMessage (string name)", attr.Calls [1], "#A2-3");
481 class ValidateFooAttribute : ValidationAttribute
483 public ValidateFooAttribute ()
487 public ValidateFooAttribute (Func<string> errorMessageAccessor)
488 : base (errorMessageAccessor)
491 public ValidateFooAttribute (string errorMessage)
492 : base (errorMessage)
495 public string GetErrorMessageString ()
497 return ErrorMessageString;
501 class ValidateBarAttribute : ValidateFooAttribute
503 public string ValidationResultErrorMessage
509 public override bool IsValid (object value)
511 return value != null;
513 protected override ValidationResult IsValid (object value, ValidationContext validationContext)
515 if (!IsValid (value))
516 return new ValidationResult (ValidationResultErrorMessage);
520 public ValidationResult CallIsValid (object value, ValidationContext validationContext)
522 return base.IsValid (value, validationContext);
526 class ValidateBazAttribute : ValidateBarAttribute
528 public readonly List<string> Calls = new List<string> ();
530 public override bool IsValid (object value)
532 Calls.Add ("bool IsValid (object value)");
533 return base.IsValid (value);
535 protected override ValidationResult IsValid (object value, ValidationContext validationContext)
537 Calls.Add ("ValidationResult IsValid (object value, ValidationContext validationContext)");
538 return base.IsValid (value, validationContext);
540 public override string FormatErrorMessage (string name)
542 Calls.Add ("string FormatErrorMessage (string name)");
543 return base.FormatErrorMessage (name);
546 class ValidateSomethingAttribute : ValidationAttribute
548 public override bool IsValid (object value)
550 return base.IsValid (value, null) == ValidationResult.Success;
553 protected override ValidationResult IsValid (object value, ValidationContext validationContext)
555 if (base.IsValid (value))
556 return ValidationResult.Success;
557 return new ValidationResult ("failed to validate in base class");
560 public ValidationResult CallIsValid (object value, ValidationContext validationContext)
562 return IsValid (value, validationContext);
565 class FooErrorMessageProvider
567 public static string ErrorProperty1
569 get { return "Error Message 1"; }
572 public static int ErrorProperty2
577 public string ErrorProperty3
579 get { return "Error Message 2"; }
582 protected static string ErrorProperty4
584 get { return "Error Message 3"; }
587 public static string ErrorProperty5
592 public static string ErrorProperty6
594 get { return "Error Message 6: {0}"; }
597 public string ErrorField1 = "Error Message 4";
598 public static string ErrorField2 = "Error Message 5";