33using System ;
44using System . Collections . Generic ;
55using System . IO ;
6+ using System . Xml . Schema ;
7+ using System . Xml ;
8+ using System . Xml . Serialization ;
69
710namespace NUnit . Engine
811{
@@ -23,7 +26,7 @@ namespace NUnit.Engine
2326 /// tests in the reloaded assembly to match those originally loaded.
2427 /// </summary>
2528 [ Serializable ]
26- public class TestPackage
29+ public class TestPackage : IXmlSerializable
2730 {
2831 /// <summary>
2932 /// Construct a named TestPackage, specifying a file path for
@@ -37,8 +40,6 @@ public TestPackage(string filePath)
3740 if ( filePath != null )
3841 {
3942 FullName = Path . GetFullPath ( filePath ) ;
40- Settings = new Dictionary < string , object > ( ) ;
41- SubPackages = new List < TestPackage > ( ) ;
4243 }
4344 }
4445
@@ -49,16 +50,19 @@ public TestPackage(string filePath)
4950 public TestPackage ( IList < string > testFiles )
5051 {
5152 ID = GetNextID ( ) ;
52- SubPackages = new List < TestPackage > ( ) ;
53- Settings = new Dictionary < string , object > ( ) ;
5453
5554 foreach ( string testFile in testFiles )
5655 SubPackages . Add ( new TestPackage ( testFile ) ) ;
5756 }
5857
58+ /// <summary>
59+ /// Construct an empty TestPackage.
60+ /// </summary>
61+ public TestPackage ( ) { }
62+
5963 private static int _nextID = 0 ;
6064
61- private string GetNextID ( )
65+ private static string GetNextID ( )
6266 {
6367 return ( _nextID ++ ) . ToString ( ) ;
6468 }
@@ -75,10 +79,7 @@ private string GetNextID()
7579 /// <summary>
7680 /// Gets the name of the package
7781 /// </summary>
78- public string Name
79- {
80- get { return FullName == null ? null : Path . GetFileName ( FullName ) ; }
81- }
82+ public string Name => FullName == null ? null : Path . GetFileName ( FullName ) ;
8283
8384 /// <summary>
8485 /// Gets the path to the file containing tests. It may be
@@ -89,12 +90,12 @@ public string Name
8990 /// <summary>
9091 /// Gets the list of SubPackages contained in this package
9192 /// </summary>
92- public IList < TestPackage > SubPackages { get ; private set ; }
93+ public IList < TestPackage > SubPackages { get ; } = new List < TestPackage > ( ) ;
9394
9495 /// <summary>
9596 /// Gets the settings dictionary for this package.
9697 /// </summary>
97- public IDictionary < string , object > Settings { get ; private set ; }
98+ public IDictionary < string , object > Settings { get ; } = new Dictionary < string , object > ( ) ;
9899
99100 /// <summary>
100101 /// Add a subproject to the package.
@@ -139,5 +140,87 @@ public T GetSetting<T>(string name, T defaultSetting)
139140 ? ( T ) Settings [ name ]
140141 : defaultSetting ;
141142 }
143+
144+ #region IXmlSerializable Implementation
145+
146+ /// <inheritdoc />
147+ public XmlSchema GetSchema ( )
148+ {
149+ return null ;
150+ }
151+
152+ /// <inheritdoc />
153+ public void ReadXml ( XmlReader xmlReader )
154+ {
155+ ID = xmlReader . GetAttribute ( "id" ) ;
156+ FullName = xmlReader . GetAttribute ( "fullname" ) ;
157+ if ( ! xmlReader . IsEmptyElement )
158+ {
159+ while ( xmlReader . Read ( ) )
160+ {
161+ switch ( xmlReader . NodeType )
162+ {
163+ case XmlNodeType . Element :
164+ switch ( xmlReader . Name )
165+ {
166+ case "Settings" :
167+ // We don't use AddSettings, which copies settings downward.
168+ // Instead, each package handles it's own settings.
169+ while ( xmlReader . MoveToNextAttribute ( ) )
170+ Settings . Add ( xmlReader . Name , xmlReader . Value ) ;
171+ xmlReader . MoveToElement ( ) ;
172+ break ;
173+
174+ case "TestPackage" :
175+ TestPackage subPackage = new TestPackage ( ) ;
176+ subPackage . ReadXml ( xmlReader ) ;
177+ SubPackages . Add ( subPackage ) ;
178+ break ;
179+ }
180+ break ;
181+
182+ case XmlNodeType . EndElement :
183+ if ( xmlReader . Name == "TestPackage" )
184+ return ;
185+ break ;
186+
187+ default :
188+ throw new Exception ( "Unexpected EndElement: " + xmlReader . Name ) ;
189+ }
190+ }
191+
192+ throw new Exception ( "Invalid XML: TestPackage Element not terminated." ) ;
193+ }
194+ }
195+
196+ /// <inheritdoc />
197+ public void WriteXml ( XmlWriter xmlWriter )
198+ {
199+ // Write ID and FullName
200+ xmlWriter . WriteAttributeString ( "id" , ID ) ;
201+ if ( FullName != null )
202+ xmlWriter . WriteAttributeString ( "fullname" , FullName ) ;
203+
204+ // Write Settings
205+ if ( Settings . Count != 0 )
206+ {
207+ xmlWriter . WriteStartElement ( "Settings" ) ;
208+
209+ foreach ( KeyValuePair < string , object > setting in Settings )
210+ xmlWriter . WriteAttributeString ( setting . Key , setting . Value . ToString ( ) ) ;
211+
212+ xmlWriter . WriteEndElement ( ) ;
213+ }
214+
215+ // Write any SubPackages recursively
216+ foreach ( TestPackage subPackage in SubPackages )
217+ {
218+ xmlWriter . WriteStartElement ( "TestPackage" ) ;
219+ subPackage . WriteXml ( xmlWriter ) ;
220+ xmlWriter . WriteEndElement ( ) ;
221+ }
222+ }
142223 }
224+
225+ #endregion
143226}
0 commit comments