@@ -11,6 +11,8 @@ public class StreamExtensionsTests
1111 private const string LF = "\n " ;
1212 private const string CRLF = "\r \n " ;
1313
14+ #region Dictionary
15+
1416 [ Fact ]
1517 public void StreamExtensions_ReadDictionary_EmptyString_ReturnsEmptyDictionary ( )
1618 {
@@ -31,9 +33,9 @@ public void StreamExtensions_ReadDictionary_TerminatedLF_ReturnsDictionary()
3133
3234 Assert . NotNull ( output ) ;
3335 Assert . Equal ( 3 , output . Count ) ;
34- Assert . Contains ( KeyValuePair . Create ( "a ", "1" ) , output ) ;
35- Assert . Contains ( KeyValuePair . Create ( "b ", "2" ) , output ) ;
36- Assert . Contains ( KeyValuePair . Create ( "c ", "3" ) , output ) ;
36+ AssertDictionary ( "1 ", "a" , output ) ;
37+ AssertDictionary ( "2 ", "b" , output ) ;
38+ AssertDictionary ( "3 ", "c" , output ) ;
3739 }
3840
3941 [ Fact ]
@@ -45,9 +47,9 @@ public void StreamExtensions_ReadDictionary_TerminatedCRLF_ReturnsDictionary()
4547
4648 Assert . NotNull ( output ) ;
4749 Assert . Equal ( 3 , output . Count ) ;
48- Assert . Contains ( KeyValuePair . Create ( "a ", "1" ) , output ) ;
49- Assert . Contains ( KeyValuePair . Create ( "b ", "2" ) , output ) ;
50- Assert . Contains ( KeyValuePair . Create ( "c ", "3" ) , output ) ;
50+ AssertDictionary ( "1 ", "a" , output ) ;
51+ AssertDictionary ( "2 ", "b" , output ) ;
52+ AssertDictionary ( "3 ", "c" , output ) ;
5153 }
5254
5355 [ Fact ]
@@ -59,8 +61,8 @@ public void StreamExtensions_ReadDictionary_CaseSensitive_ReturnsDictionaryWithM
5961
6062 Assert . NotNull ( output ) ;
6163 Assert . Equal ( 2 , output . Count ) ;
62- Assert . Contains ( KeyValuePair . Create ( "a ", "1" ) , output ) ;
63- Assert . Contains ( KeyValuePair . Create ( "A ", "2" ) , output ) ;
64+ AssertDictionary ( "1 ", "a" , output ) ;
65+ AssertDictionary ( "2 ", "A" , output ) ;
6466 }
6567
6668 [ Fact ]
@@ -72,7 +74,7 @@ public void StreamExtensions_ReadDictionary_CaseInsensitive_ReturnsDictionaryWit
7274
7375 Assert . NotNull ( output ) ;
7476 Assert . Equal ( 1 , output . Count ) ;
75- Assert . Contains ( KeyValuePair . Create ( "a ", "2" ) , output ) ;
77+ AssertDictionary ( "2 ", "a" , output ) ;
7678 }
7779
7880 [ Fact ]
@@ -84,9 +86,9 @@ public void StreamExtensions_ReadDictionary_Spaces_ReturnsCorrectKeysAndValues()
8486
8587 Assert . NotNull ( output ) ;
8688 Assert . Equal ( 3 , output . Count ) ;
87- Assert . Contains ( KeyValuePair . Create ( "key a ", "value 1" ) , output ) ;
88- Assert . Contains ( KeyValuePair . Create ( " key b ", " 2 " ) , output ) ;
89- Assert . Contains ( KeyValuePair . Create ( "key \t c \t ", "\t 3 \t " ) , output ) ;
89+ AssertDictionary ( "value 1 ", "key a" , output ) ;
90+ AssertDictionary ( " 2 ", " key b " , output ) ;
91+ AssertDictionary ( " \t 3 \t ", "key \t c \t " , output ) ;
9092 }
9193
9294 [ Fact ]
@@ -98,9 +100,9 @@ public void StreamExtensions_ReadDictionary_EqualsInValues_ReturnsCorrectKeysAnd
98100
99101 Assert . NotNull ( output ) ;
100102 Assert . Equal ( 3 , output . Count ) ;
101- Assert . Contains ( KeyValuePair . Create ( "a ", "value=1" ) , output ) ;
102- Assert . Contains ( KeyValuePair . Create ( "b ", "value=2" ) , output ) ;
103- Assert . Contains ( KeyValuePair . Create ( "c ", "value=3" ) , output ) ;
103+ AssertDictionary ( "value=1 ", "a" , output ) ;
104+ AssertDictionary ( "value=2 ", "b" , output ) ;
105+ AssertDictionary ( "value=3 ", "c" , output ) ;
104106 }
105107
106108 [ Fact ]
@@ -183,11 +185,204 @@ public void StreamExtensions_WriteDictionary_TextWriterCRLF_EntriesWithSpaces_Wr
183185 Assert . Equal ( "key a=value 1\r \n key b = value 2 \r \n \t value\t c\t =\t 3\t \r \n \r \n " , output ) ;
184186 }
185187
188+ #endregion
189+
190+ #region MultiDictionary
191+
192+ [ Fact ]
193+ public void StreamExtensions_ReadMultiDictionary_EmptyString_ReturnsEmptyDictionary ( )
194+ {
195+ string input = string . Empty ;
196+
197+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
198+
199+ Assert . NotNull ( output ) ;
200+ Assert . Equal ( 0 , output . Count ) ;
201+ }
202+
203+ [ Fact ]
204+ public void StreamExtensions_ReadMultiDictionary_TerminatedLF_ReturnsDictionary ( )
205+ {
206+ string input = "a=1\n b=2\n c=3\n \n " ;
207+
208+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
209+
210+ Assert . NotNull ( output ) ;
211+ Assert . Equal ( 3 , output . Count ) ;
212+
213+ AssertMultiDictionary ( new [ ] { "1" } , "a" , output ) ;
214+ AssertMultiDictionary ( new [ ] { "2" } , "b" , output ) ;
215+ AssertMultiDictionary ( new [ ] { "3" } , "c" , output ) ;
216+ }
217+
218+ [ Fact ]
219+ public void StreamExtensions_ReadMultiDictionary_TerminatedCRLF_ReturnsDictionary ( )
220+ {
221+ string input = "a=1\r \n b=2\r \n c=3\r \n \r \n " ;
222+
223+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
224+
225+ Assert . NotNull ( output ) ;
226+ Assert . Equal ( 3 , output . Count ) ;
227+ AssertMultiDictionary ( new [ ] { "1" } , "a" , output ) ;
228+ AssertMultiDictionary ( new [ ] { "2" } , "b" , output ) ;
229+ AssertMultiDictionary ( new [ ] { "3" } , "c" , output ) ;
230+ }
231+
232+ [ Fact ]
233+ public void StreamExtensions_ReadMultiDictionary_CaseSensitive_ReturnsDictionaryWithMultipleEntries ( )
234+ {
235+ string input = "a=1\n A=2\n \n " ;
236+
237+ var output = ReadStringStream ( input , x => StreamExtensions . ReadMultiDictionary ( x , StringComparer . Ordinal ) ) ;
238+
239+ Assert . NotNull ( output ) ;
240+ Assert . Equal ( 2 , output . Count ) ;
241+ AssertMultiDictionary ( new [ ] { "1" } , "a" , output ) ;
242+ AssertMultiDictionary ( new [ ] { "2" } , "A" , output ) ;
243+ }
244+
245+ [ Fact ]
246+ public void StreamExtensions_ReadMultiDictionary_CaseInsensitive_ReturnsDictionaryWithLastValue ( )
247+ {
248+ string input = "a=1\n A=2\n \n " ;
249+
250+ var output = ReadStringStream ( input , x => StreamExtensions . ReadMultiDictionary ( x , StringComparer . OrdinalIgnoreCase ) ) ;
251+
252+ Assert . NotNull ( output ) ;
253+ Assert . Equal ( 1 , output . Count ) ;
254+ AssertMultiDictionary ( new [ ] { "2" } , "a" , output ) ;
255+ }
256+
257+ [ Fact ]
258+ public void StreamExtensions_ReadMultiDictionary_Spaces_ReturnsCorrectKeysAndValues ( )
259+ {
260+ string input = "key a=value 1\n key b = 2 \n key\t c\t =\t 3\t \n \n " ;
261+
262+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
263+
264+ Assert . NotNull ( output ) ;
265+ Assert . Equal ( 3 , output . Count ) ;
266+
267+ AssertMultiDictionary ( new [ ] { "value 1" } , "key a" , output ) ;
268+ AssertMultiDictionary ( new [ ] { " 2 " } , " key b " , output ) ;
269+ AssertMultiDictionary ( new [ ] { "\t 3\t " } , "key\t c\t " , output ) ;
270+ }
271+
272+ [ Fact ]
273+ public void StreamExtensions_ReadMultiDictionary_EqualsInValues_ReturnsCorrectKeysAndValues ( )
274+ {
275+ string input = "a=value=1\n b=value=2\n c=value=3\n \n " ;
276+
277+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
278+
279+ Assert . NotNull ( output ) ;
280+ Assert . Equal ( 3 , output . Count ) ;
281+ AssertMultiDictionary ( new [ ] { "value=1" } , "a" , output ) ;
282+ AssertMultiDictionary ( new [ ] { "value=2" } , "b" , output ) ;
283+ AssertMultiDictionary ( new [ ] { "value=3" } , "c" , output ) ;
284+ }
285+
286+ [ Fact ]
287+ public void StreamExtensions_ReadMultiDictionary_MultiValue_ReturnsDictionary ( )
288+ {
289+ string input = "odd[]=1\n even[]=2\n even[]=4\n odd[]=3\n \n " ;
290+
291+ var output = ReadStringStream ( input , StreamExtensions . ReadMultiDictionary ) ;
292+
293+ Assert . NotNull ( output ) ;
294+ Assert . Equal ( 2 , output . Count ) ;
295+ AssertMultiDictionary ( new [ ] { "1" , "3" } , "odd" , output ) ;
296+ AssertMultiDictionary ( new [ ] { "2" , "4" } , "even" , output ) ;
297+ }
298+
299+ [ Fact ]
300+ public void StreamExtensions_WriteDictionary_TextWriterLF_EmptyMultiDictionary_WritesLineLF ( )
301+ {
302+ var input = new Dictionary < string , IList < string > > ( ) ;
303+
304+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : LF ) ;
305+
306+ Assert . Equal ( LF , output ) ;
307+ }
308+
309+ [ Fact ]
310+ public void StreamExtensions_WriteDictionary_TextWriterCRLF_EmptyMultiDictionary_WritesLineCRLF ( )
311+ {
312+ var input = new Dictionary < string , IList < string > > ( ) ;
313+
314+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : CRLF ) ;
315+
316+ Assert . Equal ( CRLF , output ) ;
317+ }
318+
319+ [ Fact ]
320+ public void StreamExtensions_WriteDictionary_TextWriterLF_MultiEntries_WritesKVPListsAndLF ( )
321+ {
322+ var input = new Dictionary < string , IList < string > >
323+ {
324+ [ "a" ] = new [ ] { "1" , "2" , "3" } ,
325+ [ "b" ] = new [ ] { "4" , "5" , } ,
326+ [ "c" ] = new [ ] { "6" }
327+ } ;
328+
329+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : LF ) ;
330+
331+ Assert . Equal ( "a[]=1\n a[]=2\n a[]=3\n b[]=4\n b[]=5\n c=6\n \n " , output ) ;
332+ }
333+
334+ [ Fact ]
335+ public void StreamExtensions_WriteDictionary_TextWriterCRLF_MultiEntries_WritesKVPListsAndCRLF ( )
336+ {
337+ var input = new Dictionary < string , IList < string > >
338+ {
339+ [ "a" ] = new [ ] { "1" , "2" , "3" } ,
340+ [ "b" ] = new [ ] { "4" , "5" , } ,
341+ [ "c" ] = new [ ] { "6" }
342+ } ;
343+
344+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : CRLF ) ;
345+
346+ Assert . Equal ( "a[]=1\r \n a[]=2\r \n a[]=3\r \n b[]=4\r \n b[]=5\r \n c=6\r \n \r \n " , output ) ;
347+ }
348+
349+ [ Fact ]
350+ public void StreamExtensions_WriteDictionary_NoMultiEntries_WritesKVPsAndLF ( )
351+ {
352+ var input = new Dictionary < string , IList < string > >
353+ {
354+ [ "a" ] = new [ ] { "1" } ,
355+ [ "b" ] = new [ ] { "2" } ,
356+ [ "c" ] = new [ ] { "3" }
357+ } ;
358+
359+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : LF ) ;
360+
361+ Assert . Equal ( "a=1\n b=2\n c=3\n \n " , output ) ;
362+ }
363+
364+ [ Fact ]
365+ public void StreamExtensions_WriteDictionary_MultiEntriesWithEmpty_WritesKVPListsAndLF ( )
366+ {
367+ var input = new Dictionary < string , IList < string > >
368+ {
369+ [ "a" ] = new [ ] { "1" , "2" , "" , "3" , "4" } ,
370+ [ "b" ] = new [ ] { "5" } ,
371+ [ "c" ] = new [ ] { "6" , "7" , "" }
372+ } ;
373+
374+ string output = WriteStringStream ( input , StreamExtensions . WriteDictionary , newLine : LF ) ;
375+
376+ Assert . Equal ( "a[]=3\n a[]=4\n b=5\n \n " , output ) ;
377+ }
378+
379+ #endregion
380+
186381 #region Helpers
187382
188- private static IDictionary < string , string > ReadStringStream ( string input , Func < TextReader , IDictionary < string , string > > func )
383+ private static T ReadStringStream < T > ( string input , Func < TextReader , T > func )
189384 {
190- IDictionary < string , string > output ;
385+ T output ;
191386 using ( var reader = new StringReader ( input ) )
192387 {
193388 output = func ( reader ) ;
@@ -196,7 +391,7 @@ private static IDictionary<string, string> ReadStringStream(string input, Func<T
196391 return output ;
197392 }
198393
199- private static string WriteStringStream ( IDictionary < string , string > input , Action < TextWriter , IDictionary < string , string > > action , string newLine )
394+ private static string WriteStringStream < T > ( T input , Action < TextWriter , T > action , string newLine )
200395 {
201396 var output = new StringBuilder ( ) ;
202397 using ( var writer = new StringWriter ( output ) { NewLine = newLine } )
@@ -207,6 +402,20 @@ private static string WriteStringStream(IDictionary<string, string> input, Actio
207402 return output . ToString ( ) ;
208403 }
209404
405+ private static void AssertDictionary ( string expectedValue , string key , IDictionary < string , string > dict )
406+ {
407+ Assert . True ( dict . TryGetValue ( key , out string actualValue ) ) ;
408+ Assert . Equal ( expectedValue , actualValue ) ;
409+ }
410+
411+ private static void AssertMultiDictionary ( IList < string > expectedValues ,
412+ string key ,
413+ IDictionary < string , IList < string > > dict )
414+ {
415+ Assert . True ( dict . TryGetValue ( key , out IList < string > actualValues ) ) ;
416+ Assert . Equal ( expectedValues , actualValues ) ;
417+ }
418+
210419 #endregion
211420 }
212421}
0 commit comments