1+ using System ;
2+ using System . ComponentModel ;
3+ using System . ComponentModel . DataAnnotations ;
4+ using System . Diagnostics . CodeAnalysis ;
5+ using System . Linq ;
6+
7+ using JetBrains . Annotations ;
8+
9+ using NUnit . Framework ;
10+
11+ using static NUnit . Framework . Assert ;
12+
13+ namespace CodeJam . ConnectionStrings
14+ {
15+ [ SuppressMessage ( "ReSharper" , "ObjectCreationAsStatement" ) ]
16+ public class ConnectionStringTests
17+ {
18+ private static readonly DateTimeOffset _defaultDateTimeOffset = new DateTimeOffset (
19+ new DateTime ( 2010 , 11 , 12 ) ,
20+ TimeSpan . Zero ) ;
21+
22+ public class BaseConnectionString : ConnectionStringBase
23+ {
24+ public BaseConnectionString ( string connectionString ) : base ( connectionString ) { }
25+
26+ #if NET35_OR_GREATER || TARGETS_NETCOREAPP
27+ [ Required ]
28+ #endif
29+ public string RequiredValue
30+ {
31+ get => TryGetValue ( nameof ( RequiredValue ) ) ;
32+ set => SetValue ( nameof ( RequiredValue ) , value ) ;
33+ }
34+
35+ public bool BooleanValue
36+ {
37+ get => TryGetBooleanValue ( nameof ( BooleanValue ) ) ;
38+ set => SetValue ( nameof ( BooleanValue ) , value ) ;
39+ }
40+
41+ public int ? Int32Value
42+ {
43+ get => TryGetInt32Value ( nameof ( Int32Value ) ) ;
44+ set => SetValue ( nameof ( Int32Value ) , value ) ;
45+ }
46+ }
47+
48+ public class DerivedConnectionString : BaseConnectionString
49+ {
50+ public DerivedConnectionString ( string connectionString ) : base ( connectionString ) { }
51+
52+ public new string RequiredValue
53+ {
54+ get => TryGetValue ( nameof ( RequiredValue ) ) ;
55+ set => SetValue ( nameof ( RequiredValue ) , value ) ;
56+ }
57+
58+ // Never filled. Used to test roundtrip scenario
59+ [ UsedImplicitly ]
60+ public string OptionalValue
61+ {
62+ get => TryGetValue ( nameof ( OptionalValue ) ) ;
63+ set => SetValue ( nameof ( OptionalValue ) , value ) ;
64+ }
65+
66+ public DateTimeOffset ? DateTimeOffsetValue
67+ {
68+ get => TryGetDateTimeOffsetValue ( nameof ( DateTimeOffsetValue ) ) ;
69+ set => SetValue ( nameof ( DateTimeOffsetValue ) , value ) ;
70+ }
71+ }
72+
73+ public class NonBrowsableConnectionString : BaseConnectionString
74+ {
75+ public NonBrowsableConnectionString ( string connectionString ) : base ( connectionString ) { }
76+
77+ [ Browsable ( false ) ]
78+ public new string RequiredValue
79+ {
80+ get => TryGetValue ( nameof ( RequiredValue ) ) ;
81+ set => SetValue ( nameof ( RequiredValue ) , value ) ;
82+ }
83+ }
84+
85+ [ Test ]
86+ public void TestConnectionStringValidation ( )
87+ {
88+ DoesNotThrow ( ( ) => new BaseConnectionString ( null ) ) ;
89+ DoesNotThrow ( ( ) => new BaseConnectionString ( "" ) ) ;
90+ DoesNotThrow ( ( ) => new BaseConnectionString ( "requiredValue=aaa" ) ) ;
91+ DoesNotThrow ( ( ) => new BaseConnectionString ( "RequiredValue=aaa;IgnoredValue=123" ) ) ;
92+ DoesNotThrow ( ( ) => new BaseConnectionString ( "" ) { ConnectionString = null } ) ;
93+ DoesNotThrow ( ( ) => new BaseConnectionString ( "" ) { ConnectionString = "" } ) ;
94+ DoesNotThrow ( ( ) => new BaseConnectionString ( "" ) { ConnectionString = "requiredValue=aaa" } ) ;
95+ DoesNotThrow ( ( ) => new BaseConnectionString ( "" ) { ConnectionString = "RequiredValue=aaa;IgnoredValue=123" } ) ;
96+
97+ #if NET35_OR_GREATER || TARGETS_NETCOREAPP
98+ var ex = Throws < ArgumentException > ( ( ) => new BaseConnectionString ( "IgnoredValue=123" ) ) ;
99+ That ( ex . Message , Does . Contain ( nameof ( BaseConnectionString . RequiredValue ) ) ) ;
100+ ex = Throws < ArgumentException > (
101+ ( ) => new BaseConnectionString ( "" )
102+ {
103+ ConnectionString = "IgnoredValue = 123"
104+ } ) ;
105+ That ( ex . Message , Does . Contain ( nameof ( BaseConnectionString . RequiredValue ) ) ) ;
106+ #else
107+ DoesNotThrow ( ( ) => new BaseConnectionString ( "IgnoredValue=123" ) ) ;
108+ DoesNotThrow (
109+ ( ) => new BaseConnectionString ( "" )
110+ {
111+ ConnectionString = "IgnoredValue = 123"
112+ } ) ; ;
113+ #endif
114+ }
115+
116+ [ Test ]
117+ public void TestConnectionStringValidationOverride ( )
118+ {
119+ DoesNotThrow ( ( ) => new DerivedConnectionString ( "IgnoredValue=123" ) ) ;
120+ DoesNotThrow (
121+ ( ) => new DerivedConnectionString ( "" )
122+ {
123+ ConnectionString = "IgnoredValue=123"
124+ } ) ;
125+ }
126+
127+ [ Test ]
128+ public void TestGetProperties ( )
129+ {
130+ var x = new BaseConnectionString ( "requiredValue=aaa" ) ;
131+ AreEqual ( x . RequiredValue , "aaa" ) ;
132+ AreEqual ( x . BooleanValue , false ) ;
133+ AreEqual ( x . Int32Value , null ) ;
134+
135+ IsTrue ( x . ContainsKey ( nameof ( x . RequiredValue ) ) ) ;
136+ IsTrue ( x . TryGetValue ( nameof ( x . RequiredValue ) , out _ ) ) ;
137+ AreEqual ( x [ nameof ( x . RequiredValue ) ] , "aaa" ) ;
138+
139+ x = new BaseConnectionString ( "requiredValue='aa; a'" ) ;
140+ AreEqual ( x . RequiredValue , "aa; a" ) ;
141+
142+ x = new BaseConnectionString ( "requiredValue=\" aa; a\" " ) ;
143+ AreEqual ( x . RequiredValue , "aa; a" ) ;
144+
145+ // test for input string format
146+ x = new BaseConnectionString ( @"
147+ RequiredValue=""aaa"" ;
148+ BooleanValue=true;
149+ Int32Value = 112" ) ;
150+ AreEqual ( x . RequiredValue , "aaa" ) ;
151+ AreEqual ( x . BooleanValue , true ) ;
152+ AreEqual ( x . Int32Value , 112 ) ;
153+ }
154+
155+ [ Test ]
156+ public void TestGetPropertiesDerived ( )
157+ {
158+ var x = new DerivedConnectionString ( "IgnoredValue=aaa" ) ;
159+ AreEqual ( x . RequiredValue , null ) ;
160+ AreEqual ( x . OptionalValue , null ) ;
161+ AreEqual ( x . BooleanValue , false ) ;
162+ AreEqual ( x . Int32Value , null ) ;
163+ AreEqual ( x . DateTimeOffsetValue , null ) ;
164+
165+ x = new DerivedConnectionString ( "DateTimeOffsetValue=2010-11-12Z" ) ;
166+ AreEqual ( x . DateTimeOffsetValue , _defaultDateTimeOffset ) ;
167+ }
168+
169+ [ Test ]
170+ public void TestPropertiesRoundtrip ( )
171+ {
172+ var x = new DerivedConnectionString ( "" )
173+ {
174+ RequiredValue = "A; B=C'\" " ,
175+ BooleanValue = true ,
176+ Int32Value = - 1024 ,
177+ DateTimeOffsetValue = _defaultDateTimeOffset
178+ } ;
179+
180+ var s = x . ToString ( ) ;
181+ AreEqual (
182+ s ,
183+ @"RequiredValue=""A; B=C'"""""";BooleanValue=True;Int32Value=-1024;DateTimeOffsetValue=""11/12/2010 00:00:00 +00:00""" ) ;
184+
185+ var x2 = new DerivedConnectionString ( s ) ;
186+ AreEqual ( x2 . RequiredValue , x . RequiredValue ) ;
187+ AreEqual ( x2 . BooleanValue , x . BooleanValue ) ;
188+ AreEqual ( x2 . Int32Value , x . Int32Value ) ;
189+ AreEqual ( x2 . DateTimeOffsetValue , x . DateTimeOffsetValue ) ;
190+
191+ AreEqual ( s , x2 . ToString ( ) ) ;
192+ IsTrue ( x . EquivalentTo ( x2 ) ) ;
193+ AreEqual ( x . OrderBy ( p => p . Key ) , x2 . OrderBy ( p => p . Key ) ) ;
194+ }
195+
196+ [ Test ]
197+ public void TestIgnoredProperties ( )
198+ {
199+ var x = new DerivedConnectionString ( "" ) ;
200+ IsFalse ( x . ContainsKey ( "IgnoredValue" ) ) ;
201+ IsFalse ( x . TryGetValue ( "IgnoredValue" , out var ignored ) ) ;
202+ IsNull ( ignored ) ;
203+ var ex = Throws < ArgumentException > ( ( ) => x [ "IgnoredValue" ] . ToString ( ) ) ;
204+ That ( ex . Message , Does . Contain ( "IgnoredValue" ) ) ;
205+
206+ x = new DerivedConnectionString ( "IgnoredValue=123" ) ;
207+ IsFalse ( x . ContainsKey ( "IgnoredValue" ) ) ;
208+ IsFalse ( x . TryGetValue ( "IgnoredValue" , out ignored ) ) ;
209+ IsNull ( ignored ) ;
210+ ex = Throws < ArgumentException > ( ( ) => x [ "IgnoredValue" ] . ToString ( ) ) ;
211+ That ( ex . Message , Does . Contain ( "IgnoredValue" ) ) ;
212+ }
213+
214+ [ Test ]
215+ public void TestInvalidProperties ( )
216+ {
217+ var x = new DerivedConnectionString ( @"BooleanValue=aaa;Int32Value=bbb;DateTimeOffsetValue=ccc" ) ;
218+ Throws < FormatException > ( ( ) => x . BooleanValue . ToString ( ) ) ;
219+ Throws < FormatException > ( ( ) => x . Int32Value ? . ToString ( ) ) ;
220+ Throws < FormatException > ( ( ) => x . DateTimeOffsetValue ? . ToString ( ) ) ;
221+ }
222+
223+ [ Test ]
224+ public void TestNonBrowsableProperties ( )
225+ {
226+ var x = new NonBrowsableConnectionString ( "" )
227+ {
228+ RequiredValue = "A" ,
229+ BooleanValue = true ,
230+ Int32Value = - 1024
231+ } ;
232+
233+ var s = x . GetBrowsableConnectionString ( true ) ;
234+ AreEqual ( s , @"RequiredValue=...;BooleanValue=True;Int32Value=-1024" ) ;
235+
236+ var x2 = new NonBrowsableConnectionString ( s ) ;
237+ AreEqual ( x2 . RequiredValue , "..." ) ;
238+ AreEqual ( x2 . BooleanValue , x . BooleanValue ) ;
239+ AreEqual ( x2 . Int32Value , x . Int32Value ) ;
240+ AreEqual ( s , x2 . ToString ( ) ) ;
241+ IsFalse ( x . EquivalentTo ( x2 ) ) ;
242+ AreNotEqual ( x . ToArray ( ) , x2 . ToArray ( ) ) ;
243+
244+ s = x . GetBrowsableConnectionString ( false ) ;
245+ AreEqual ( s , @"BooleanValue=True;Int32Value=-1024" ) ;
246+
247+ x2 = new NonBrowsableConnectionString ( s ) ;
248+ AreEqual ( x2 . RequiredValue , null ) ;
249+ AreEqual ( x2 . BooleanValue , x . BooleanValue ) ;
250+ AreEqual ( x2 . Int32Value , x . Int32Value ) ;
251+ AreEqual ( s , x2 . ToString ( ) ) ;
252+ IsFalse ( x . EquivalentTo ( x2 ) ) ;
253+ AreNotEqual ( x . ToArray ( ) , x2 . ToArray ( ) ) ;
254+ }
255+ }
256+ }
0 commit comments