Skip to content

Commit c1545d1

Browse files
authored
Merge pull request #99 from rsdn/feature/connection-strings
+ Connection string parser/formatter class
2 parents 80ee81f + 18f58b5 commit c1545d1

File tree

10 files changed

+776
-43
lines changed

10 files changed

+776
-43
lines changed

CodeJam.Blocks.Tests/CodeJam.Blocks.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</PropertyGroup>
1414

1515
<!-- #region Targeting -->
16-
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
16+
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' OR '$(TargetFramework)' == 'net35' ">
1717
<Reference Include="System.ComponentModel.DataAnnotations" />
1818
</ItemGroup>
1919
<ItemGroup Condition=" '$(TargetFramework)' != 'net20' AND '$(TargetFramework)' != 'netcoreapp1.1' ">

CodeJam.Main.Tests/CodeJam.Main.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</PropertyGroup>
1515

1616
<!-- #region Targeting -->
17-
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
17+
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' OR '$(TargetFramework)' == 'net35' ">
1818
<Reference Include="System.ComponentModel.DataAnnotations" />
1919
</ItemGroup>
2020
<ItemGroup Condition=" '$(TargetFramework)' != 'net20' AND '$(TargetFramework)' != 'netcoreapp1.1' ">
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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+
}

CodeJam.Main/CodeJam.Main.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<PackageReference Include="Theraot.Core" Version="3.1.2" />
6969
</ItemGroup>
7070
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
71+
<Reference Include="System.ComponentModel.DataAnnotations" />
7172
<PackageReference Include="Theraot.Core" Version="3.1.2" />
7273
</ItemGroup>
7374
<ItemGroup Condition=" '$(TargetFramework)' == 'net20' ">
@@ -82,6 +83,8 @@
8283
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.5' ">
8384
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
8485
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
86+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
87+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
8588
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
8689
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
8790
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
@@ -93,6 +96,8 @@
9396
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
9497
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
9598
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
99+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
100+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
96101
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
97102
<PackageReference Include="System.Dynamic.Runtime" Version="4.3.0" />
98103
<PackageReference Include="System.Linq.Queryable" Version="4.3.0" />
@@ -110,6 +115,8 @@
110115
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.0' ">
111116
<PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
112117
<PackageReference Include="System.ComponentModel.EventBasedAsync" Version="4.3.0" />
118+
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
119+
<PackageReference Include="System.Data.Common" Version="4.3.0" />
113120
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
114121
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
115122
<PackageReference Include="Theraot.Core" Version="3.1.2" />

0 commit comments

Comments
 (0)