22// The .NET Foundation licenses this file to you under the MIT license.
33
44using System . Collections . Generic ;
5+ using System . Collections . ObjectModel ;
56using System . Diagnostics ;
67using System . Linq ;
78using System . Reflection ;
@@ -11,14 +12,96 @@ namespace System.Collections.Tests
1112{
1213 public class DebugView_Tests
1314 {
14- public static IEnumerable < object [ ] > TestDebuggerAttributes_Inputs ( )
15+ private static IEnumerable < object [ ] > TestDebuggerAttributes_GenericDictionaries ( )
16+ {
17+ yield return new object [ ] { new Dictionary < int , string > ( ) , new KeyValuePair < string , string > [ 0 ] } ;
18+ yield return new object [ ] { new ReadOnlyDictionary < int , string > ( new Dictionary < int , string > ( ) ) , new KeyValuePair < string , string > [ 0 ] } ;
19+ yield return new object [ ] { new SortedDictionary < string , int > ( ) , new KeyValuePair < string , string > [ 0 ] } ;
20+ yield return new object [ ] { new SortedList < int , string > ( ) , new KeyValuePair < string , string > [ 0 ] } ;
21+
22+ yield return new object [ ] { new Dictionary < int , string > { { 1 , "One" } , { 2 , "Two" } } ,
23+ new KeyValuePair < string , string > [ ]
24+ {
25+ new ( "[1]" , "\" One\" " ) ,
26+ new ( "[2]" , "\" Two\" " ) ,
27+ }
28+ } ;
29+ yield return new object [ ] { new ReadOnlyDictionary < int , string > ( new Dictionary < int , string > { { 1 , "One" } , { 2 , "Two" } } ) ,
30+ new KeyValuePair < string , string > [ ]
31+ {
32+ new ( "[1]" , "\" One\" " ) ,
33+ new ( "[2]" , "\" Two\" " ) ,
34+ }
35+ } ;
36+ yield return new object [ ] { new SortedDictionary < string , int > { { "One" , 1 } , { "Two" , 2 } } ,
37+ new KeyValuePair < string , string > [ ]
38+ {
39+ new ( "[\" One\" ]" , "1" ) ,
40+ new ( "[\" Two\" ]" , "2" ) ,
41+ }
42+ } ;
43+ yield return new object [ ] { new SortedList < string , double > { { "One" , 1.0 } , { "Two" , 2.0 } } ,
44+ new KeyValuePair < string , string > [ ]
45+ {
46+ new ( "[\" One\" ]" , "1" ) ,
47+ new ( "[\" Two\" ]" , "2" ) ,
48+ }
49+ } ;
50+ }
51+
52+ private static IEnumerable < object [ ] > TestDebuggerAttributes_NonGenericDictionaries ( )
53+ {
54+ yield return new object [ ] { new Hashtable ( ) , new KeyValuePair < string , string > [ 0 ] } ;
55+ yield return new object [ ] { Hashtable . Synchronized ( new Hashtable ( ) ) , new KeyValuePair < string , string > [ 0 ] } ;
56+ yield return new object [ ] { new SortedList ( ) , new KeyValuePair < string , string > [ 0 ] } ;
57+ yield return new object [ ] { SortedList . Synchronized ( new SortedList ( ) ) , new KeyValuePair < string , string > [ 0 ] } ;
58+
59+ yield return new object [ ] { new Hashtable { { "a" , 1 } , { "b" , "B" } } ,
60+ new KeyValuePair < string , string > [ ]
61+ {
62+ new ( "[\" a\" ]" , "1" ) ,
63+ new ( "[\" b\" ]" , "\" B\" " ) ,
64+ }
65+ } ;
66+ yield return new object [ ] { Hashtable . Synchronized ( new Hashtable { { "a" , 1 } , { "b" , "B" } } ) ,
67+ new KeyValuePair < string , string > [ ]
68+ {
69+ new ( "[\" a\" ]" , "1" ) ,
70+ new ( "[\" b\" ]" , "\" B\" " ) ,
71+ }
72+ } ;
73+ yield return new object [ ] { new SortedList { { "a" , 1 } , { "b" , "B" } } ,
74+ new KeyValuePair < string , string > [ ]
75+ {
76+ new ( "[\" a\" ]" , "1" ) ,
77+ new ( "[\" b\" ]" , "\" B\" " ) ,
78+ }
79+ } ;
80+ yield return new object [ ] { SortedList . Synchronized ( new SortedList { { "a" , 1 } , { "b" , "B" } } ) ,
81+ new KeyValuePair < string , string > [ ]
82+ {
83+ new ( "[\" a\" ]" , "1" ) ,
84+ new ( "[\" b\" ]" , "\" B\" " ) ,
85+ }
86+ } ;
87+ #if ! NETFRAMEWORK // ListDictionaryInternal in .Net Framework is not annotated with debugger attributes.
88+ yield return new object [ ] { new Exception ( ) . Data , new KeyValuePair < string , string > [ 0 ] } ;
89+ yield return new object [ ] { new Exception { Data = { { "a" , 1 } , { "b" , "B" } } } . Data ,
90+ new KeyValuePair < string , string > [ ]
91+ {
92+ new ( "[\" a\" ]" , "1" ) ,
93+ new ( "[\" b\" ]" , "\" B\" " ) ,
94+ }
95+ } ;
96+ #endif
97+ }
98+
99+ private static IEnumerable < object [ ] > TestDebuggerAttributes_ListInputs ( )
15100 {
16- yield return new object [ ] { new Dictionary < int , string > ( ) } ;
17101 yield return new object [ ] { new HashSet < string > ( ) } ;
18102 yield return new object [ ] { new LinkedList < object > ( ) } ;
19103 yield return new object [ ] { new List < int > ( ) } ;
20104 yield return new object [ ] { new Queue < double > ( ) } ;
21- yield return new object [ ] { new SortedDictionary < string , int > ( ) } ;
22105 yield return new object [ ] { new SortedList < int , string > ( ) } ;
23106 yield return new object [ ] { new SortedSet < int > ( ) } ;
24107 yield return new object [ ] { new Stack < object > ( ) } ;
@@ -30,39 +113,83 @@ public static IEnumerable<object[]> TestDebuggerAttributes_Inputs()
30113 yield return new object [ ] { new SortedList < string , int > ( ) . Keys } ;
31114 yield return new object [ ] { new SortedList < float , long > ( ) . Values } ;
32115
33- yield return new object [ ] { new Dictionary < int , string > { { 1 , "One" } , { 2 , "Two" } } } ;
34- yield return new object [ ] { new HashSet < string > { "One" , "Two" } } ;
116+ yield return new object [ ] { new HashSet < string > { "One" , "Two" } } ;
35117
36- LinkedList < object > linkedList = new LinkedList < object > ( ) ;
118+ LinkedList < object > linkedList = new ( ) ;
37119 linkedList . AddFirst ( 1 ) ;
38120 linkedList . AddLast ( 2 ) ;
39121 yield return new object [ ] { linkedList } ;
40- yield return new object [ ] { new List < int > { 1 , 2 } } ;
122+ yield return new object [ ] { new List < int > { 1 , 2 } } ;
41123
42- Queue < double > queue = new Queue < double > ( ) ;
124+ Queue < double > queue = new ( ) ;
43125 queue . Enqueue ( 1 ) ;
44126 queue . Enqueue ( 2 ) ;
45127 yield return new object [ ] { queue } ;
46- yield return new object [ ] { new SortedDictionary < string , int > { { "One" , 1 } , { "Two" , 2 } } } ;
47- yield return new object [ ] { new SortedList < int , string > { { 1 , "One" } , { 2 , "Two" } } } ;
48- yield return new object [ ] { new SortedSet < int > { 1 , 2 } } ;
128+ yield return new object [ ] { new SortedSet < int > { 1 , 2 } } ;
49129
50- var stack = new Stack < object > ( ) ;
130+ Stack < object > stack = new ( ) ;
51131 stack . Push ( 1 ) ;
52132 stack . Push ( 2 ) ;
53133 yield return new object [ ] { stack } ;
54134
55- yield return new object [ ] { new Dictionary < double , float > { { 1.0 , 1.0f } , { 2.0 , 2.0f } } . Keys } ;
56- yield return new object [ ] { new Dictionary < float , double > { { 1.0f , 1.0 } , { 2.0f , 2.0 } } . Values } ;
57- yield return new object [ ] { new SortedDictionary < Guid , string > { { Guid . NewGuid ( ) , "One" } , { Guid . NewGuid ( ) , "Two" } } . Keys } ;
58- yield return new object [ ] { new SortedDictionary < long , Guid > { { 1L , Guid . NewGuid ( ) } , { 2L , Guid . NewGuid ( ) } } . Values } ;
59- yield return new object [ ] { new SortedList < string , int > { { "One" , 1 } , { "Two" , 2 } } . Keys } ;
60- yield return new object [ ] { new SortedList < float , long > { { 1f , 1L } , { 2f , 2L } } . Values } ;
135+ yield return new object [ ] { new SortedList < string , int > { { "One" , 1 } , { "Two" , 2 } } . Keys } ;
136+ yield return new object [ ] { new SortedList < float , long > { { 1f , 1L } , { 2f , 2L } } . Values } ;
137+
138+ yield return new object [ ] { new Dictionary < double , float > { { 1.0 , 1.0f } , { 2.0 , 2.0f } } . Keys } ;
139+ yield return new object [ ] { new Dictionary < float , double > { { 1.0f , 1.0 } , { 2.0f , 2.0 } } . Values } ;
140+ yield return new object [ ] { new SortedDictionary < Guid , string > { { Guid . NewGuid ( ) , "One" } , { Guid . NewGuid ( ) , "Two" } } . Keys } ;
141+ yield return new object [ ] { new SortedDictionary < long , Guid > { { 1L , Guid . NewGuid ( ) } , { 2L , Guid . NewGuid ( ) } } . Values } ;
142+ }
143+
144+ public static IEnumerable < object [ ] > TestDebuggerAttributes_InputsPresentedAsDictionary ( )
145+ {
146+ #if ! NETFRAMEWORK
147+ return TestDebuggerAttributes_NonGenericDictionaries ( )
148+ . Concat ( TestDebuggerAttributes_GenericDictionaries ( ) ) ;
149+ #else
150+ // In .Net Framework only non-generic dictionaries are displayed in a dictionary format by the debugger.
151+ return TestDebuggerAttributes_NonGenericDictionaries ( ) ;
152+ #endif
153+ }
154+
155+ public static IEnumerable < object [ ] > TestDebuggerAttributes_InputsPresentedAsList ( )
156+ {
157+ #if ! NETFRAMEWORK
158+ return TestDebuggerAttributes_ListInputs ( ) ;
159+ #else
160+ // In .Net Framework generic dictionaries are displayed in a list format by the debugger.
161+ return TestDebuggerAttributes_GenericDictionaries ( )
162+ . Select ( t => new [ ] { t [ 0 ] } )
163+ . Concat ( TestDebuggerAttributes_ListInputs ( ) ) ;
164+ #endif
165+ }
166+
167+ public static IEnumerable < object [ ] > TestDebuggerAttributes_Inputs ( )
168+ {
169+ return TestDebuggerAttributes_InputsPresentedAsDictionary ( )
170+ . Select ( t => new [ ] { t [ 0 ] } )
171+ . Concat ( TestDebuggerAttributes_InputsPresentedAsList ( ) ) ;
61172 }
62173
63174 [ ConditionalTheory ( typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsDebuggerTypeProxyAttributeSupported ) ) ]
64- [ MemberData ( nameof ( TestDebuggerAttributes_Inputs ) ) ]
65- public static void TestDebuggerAttributes ( object obj )
175+ [ MemberData ( nameof ( TestDebuggerAttributes_InputsPresentedAsDictionary ) ) ]
176+ public static void TestDebuggerAttributes_Dictionary ( IDictionary obj , KeyValuePair < string , string > [ ] expected )
177+ {
178+ DebuggerAttributes . ValidateDebuggerDisplayReferences ( obj ) ;
179+ DebuggerAttributeInfo info = DebuggerAttributes . ValidateDebuggerTypeProxyProperties ( obj ) ;
180+ PropertyInfo itemProperty = info . Properties . Single ( pr => pr . GetCustomAttribute < DebuggerBrowsableAttribute > ( ) . State == DebuggerBrowsableState . RootHidden ) ;
181+ Array itemArray = ( Array ) itemProperty . GetValue ( info . Instance ) ;
182+ List < KeyValuePair < string , string > > formatted = itemArray . Cast < object > ( )
183+ . Select ( DebuggerAttributes . ValidateFullyDebuggerDisplayReferences )
184+ . Select ( formattedResult => new KeyValuePair < string , string > ( formattedResult . Key , formattedResult . Value ) )
185+ . ToList ( ) ;
186+
187+ CollectionAsserts . EqualUnordered ( ( ICollection ) expected , formatted ) ;
188+ }
189+
190+ [ ConditionalTheory ( typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsDebuggerTypeProxyAttributeSupported ) ) ]
191+ [ MemberData ( nameof ( TestDebuggerAttributes_InputsPresentedAsList ) ) ]
192+ public static void TestDebuggerAttributes_List ( object obj )
66193 {
67194 DebuggerAttributes . ValidateDebuggerDisplayReferences ( obj ) ;
68195 DebuggerAttributeInfo info = DebuggerAttributes . ValidateDebuggerTypeProxyProperties ( obj ) ;
0 commit comments