Merge pull request #3585 from lateralusX/jlorenss/win-counter-warning
[mono.git] / mcs / class / System.Data / Test / System.Data / DataTableReadWriteXmlTest.cs
1 // Author:
2 //   Patrick Earl <mono@patearl.net>
3 //
4 // Copyright (c) 2006
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25
26 using System;
27 using System.Data;
28 using System.IO;
29 using System.Text.RegularExpressions;
30 using System.Xml;
31 using NUnit.Framework; 
32
33 namespace MonoTests.System.Data
34 {
35     [TestFixture]
36     public class DataTableReadWriteXmlTest
37     {
38
39         void StandardizeXmlFormat(ref string xml)
40         {
41             XmlDocument doc = new XmlDocument();
42             doc.LoadXml(xml);
43             StringWriter sw = new StringWriter();
44             doc.Save(sw);
45             xml = sw.ToString();
46         }
47         
48         void GenerateTestData(out DataSet ds,
49                               out DataTable dtMainInDS,
50                               out DataTable dtChildInDS,
51                               out DataTable dtMain)
52         {
53             ds = new DataSet("MyDataSet");
54
55             // Create a primary table and populate it with some data.  Make a
56             // copy of the primary table and put it into the dataset.
57             dtMain = new DataTable("Main");
58             dtMain.Columns.Add(new DataColumn("ID", typeof(int)));
59             dtMain.Columns.Add(new DataColumn("Data", typeof(string)));
60             
61             DataRow row = dtMain.NewRow();
62             row["ID"] = 1;
63             row["Data"] = "One";
64             dtMain.Rows.Add(row);
65             
66             row = dtMain.NewRow();
67             row["ID"] = 2;
68             row["Data"] = "Two";
69             dtMain.Rows.Add(row);
70             
71             row = dtMain.NewRow();
72             row["ID"] = 3;
73             row["Data"] = "Three";
74             dtMain.Rows.Add(row);
75             
76             dtMainInDS = dtMain.Copy();
77             ds.Tables.Add(dtMainInDS);
78             
79             // Create a child table.  Make a copy of the child table and put
80             // it into the dataset.
81             dtChildInDS = new DataTable("Child");
82             dtChildInDS.Columns.Add(new DataColumn("ID", typeof(int)));
83             dtChildInDS.Columns.Add(new DataColumn("PID", typeof(int)));
84             dtChildInDS.Columns.Add(new DataColumn("ChildData", typeof(string)));
85             
86             row = dtChildInDS.NewRow();
87             row["ID"] = 1;
88             row["PID"] = 1;
89             row["ChildData"] = "Parent1Child1";
90             dtChildInDS.Rows.Add(row);
91             
92             row = dtChildInDS.NewRow();
93             row["ID"] = 2;
94             row["PID"] = 1;
95             row["ChildData"] = "Parent1Child2";
96             dtChildInDS.Rows.Add(row);
97             
98             row = dtChildInDS.NewRow();
99             row["ID"] = 3;
100             row["PID"] = 2;
101             row["ChildData"] = "Parent2Child3";
102             dtChildInDS.Rows.Add(row);
103             
104             ds.Tables.Add(dtChildInDS);
105             
106             // Set up the relation in the dataset.
107             ds.Relations.Add(new DataRelation("MainToChild",
108                                               dtMainInDS.Columns["ID"],
109                                               dtChildInDS.Columns["PID"]));
110         }
111         
112         [Test]
113         public void TestWriteXml()
114         {
115             DataSet ds;
116             DataTable dtMainInDS, dtChildInDS, dtMain;
117             
118             GenerateTestData(out ds,
119                              out dtMainInDS,
120                              out dtChildInDS,
121                              out dtMain);
122             
123             StringWriter sw = new StringWriter();
124             
125             // Get XML for DataSet writes.
126             sw.GetStringBuilder().Length = 0;
127             ds.WriteXml(sw);
128             string xmlDSNone = sw.ToString();
129             
130             sw.GetStringBuilder().Length = 0;
131             ds.WriteXml(sw, XmlWriteMode.DiffGram);
132             string xmlDSDiffGram = sw.ToString();
133
134             sw.GetStringBuilder().Length = 0;
135             ds.WriteXml(sw, XmlWriteMode.WriteSchema);
136             string xmlDSWriteSchema = sw.ToString();
137
138             // Get XML for recursive DataTable writes of the same data as in
139             // the DataSet.
140             sw.GetStringBuilder().Length = 0;
141             dtMainInDS.WriteXml(sw, true);
142             string xmlDTNone = sw.ToString();
143             
144             sw.GetStringBuilder().Length = 0;
145             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
146             string xmlDTDiffGram = sw.ToString();
147
148             sw.GetStringBuilder().Length = 0;
149             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
150             string xmlDTWriteSchema = sw.ToString();
151             
152             // The schema XML written by the DataTable call has an extra element
153             // in the element for the dataset schema definition.  We remove that
154             // extra attribute and then check to see if the rest of the xml is
155             // identical.
156             XmlDocument doc = new XmlDocument();
157             doc.LoadXml(xmlDTWriteSchema);
158             XmlNode node = doc.DocumentElement.FirstChild.FirstChild;
159             XmlAttribute a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
160             Assert.IsNotNull(a, "Test#01");
161             Assert.AreEqual("Main", a.Value, "Test#02");
162             
163             node.Attributes.Remove(a);
164             sw.GetStringBuilder().Length = 0;
165             doc.Save(sw);
166             xmlDTWriteSchema = sw.ToString();
167             
168             StandardizeXmlFormat(ref xmlDSWriteSchema);
169             
170             Assert.AreEqual(xmlDSNone, xmlDTNone, "Test#03");
171             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGram, "Test#04");
172             Assert.IsTrue (xmlDSWriteSchema.IndexOf ("UseCurrentLocale") > 0, "Test#05-premise1");
173             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchema, "Test#05");
174                                
175             // Now that we've tested writing tables (including children),
176             // we will go on to test the cases where the hierarchy flag
177             // is false.  For this, we will test one table inside the
178             // dataset and one table outside the dataset.
179             
180             // First, we fix our test DataSet to only have a single table
181             // with no relations.  Then, we go about comparing the XML.
182             // Get XML for DataSet writes.
183             ds.Tables[1].Constraints.Remove(ds.Tables[1].Constraints[0]);
184             ds.Tables[0].Constraints.Remove(ds.Tables[0].Constraints[0]);
185             ds.Tables[0].ChildRelations.Remove("MainToChild");
186             ds.Tables.Remove("Child");
187             
188             sw.GetStringBuilder().Length = 0;
189             ds.WriteXml(sw);
190             xmlDSNone = sw.ToString();
191             
192             sw.GetStringBuilder().Length = 0;
193             ds.WriteXml(sw, XmlWriteMode.DiffGram);
194             xmlDSDiffGram = sw.ToString();
195
196             sw.GetStringBuilder().Length = 0;
197             ds.WriteXml(sw, XmlWriteMode.WriteSchema);
198             xmlDSWriteSchema = sw.ToString();
199             
200             // Get all the DataTable.WriteXml results.
201             sw.GetStringBuilder().Length = 0;
202             dtMainInDS.WriteXml(sw);
203             string xmlDTNoneInDS = sw.ToString();
204             
205             sw.GetStringBuilder().Length = 0;
206             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram);
207             string xmlDTDiffGramInDS = sw.ToString();
208
209             sw.GetStringBuilder().Length = 0;
210             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema);
211             string xmlDTWriteSchemaInDS = sw.ToString();
212
213             sw.GetStringBuilder().Length = 0;
214             dtMain.WriteXml(sw);
215             string xmlDTNoneNoDS = sw.ToString();
216
217             sw.GetStringBuilder().Length = 0;
218             dtMain.WriteXml(sw, XmlWriteMode.DiffGram);
219             string xmlDTDiffGramNoDS = sw.ToString();
220
221             sw.GetStringBuilder().Length = 0;
222             dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
223             string xmlDTWriteSchemaNoDS = sw.ToString();
224             
225             Assert.AreEqual(xmlDSNone, xmlDTNoneInDS, "Test#06");
226
227             // The only difference between the xml output from inside the
228             // dataset and the xml output from outside the dataset is that
229             // there's a fake <DocumentElement> tag surrounding tbe table
230             // in the second case.  We replace it with the name of the
231             // dataset for testing purposes.
232             doc.LoadXml(xmlDTNoneNoDS);
233             Assert.AreEqual("DocumentElement", doc.DocumentElement.Name, "Test#07");
234             sw.GetStringBuilder().Length = 0;
235             doc.Save(sw);
236             xmlDTNoneNoDS = sw.ToString();
237             xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("<DocumentElement>", "<MyDataSet>");
238             xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("</DocumentElement>", "</MyDataSet>");
239             
240             StandardizeXmlFormat(ref xmlDSNone);
241             
242             Assert.AreEqual(xmlDSNone, xmlDTNoneNoDS, "Test#08");
243             
244             // Now check the DiffGram.
245             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramInDS, "Test#09");
246             
247             doc.LoadXml(xmlDTDiffGramNoDS);
248             Assert.AreEqual("DocumentElement", doc.DocumentElement.FirstChild.Name, "Test#10");
249             xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("<DocumentElement>", "<MyDataSet>");
250             xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("</DocumentElement>", "</MyDataSet>");
251
252             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramNoDS, "Test#11");
253             
254             // Finally we check the WriteSchema version of the data.  First
255             // we remove the extra "msdata:MainDataTable" attribute from
256             // the schema declaration part of the DataTable xml.
257             doc = new XmlDocument();
258             doc.LoadXml(xmlDTWriteSchemaInDS);
259             node = doc.DocumentElement.FirstChild.FirstChild;
260             a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
261             Assert.IsNotNull(a, "Test#12");
262             Assert.AreEqual("Main", a.Value, "Test#13");
263             node.Attributes.Remove(a);
264             sw.GetStringBuilder().Length = 0;
265             doc.Save(sw);
266             xmlDTWriteSchemaInDS = sw.ToString();
267             
268             StandardizeXmlFormat(ref xmlDSWriteSchema);
269
270             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaInDS, "Test#14");
271             
272             // Remove the extra "msdata:MainDataTable" for the other test case.
273             // Also make sure we have "NewDataSet" in the appropriate locations.
274             doc = new XmlDocument();
275             doc.LoadXml(xmlDTWriteSchemaNoDS);
276             node = doc.DocumentElement.FirstChild.FirstChild;
277             a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
278             Assert.IsNotNull(a, "Test#15");
279             Assert.AreEqual("Main", a.Value, "Test#16");
280             node.Attributes.Remove(a);
281             sw.GetStringBuilder().Length = 0;
282             doc.Save(sw);
283             
284             Assert.AreEqual("NewDataSet", doc.DocumentElement.Name, "Test#17");
285             Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.Attributes["id"].Value, "Test#18");
286             Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.FirstChild.Attributes["name"].Value, "Test#19");
287             
288             xmlDTWriteSchemaNoDS = sw.ToString();
289             
290             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("<NewDataSet>","<MyDataSet>");
291             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("</NewDataSet>","</MyDataSet>");
292             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("\"NewDataSet\"","\"MyDataSet\"");
293
294             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaNoDS, "Test#20");
295         }
296         
297         [Test]
298         public void TestReadXml()
299         {
300             // For reading, DataTable.ReadXml only supports reading in xml with
301             // the schema included.  This means that we can only read in XML
302             // that was generated with the WriteSchema flag.  
303             DataSet ds;
304             DataTable dtMainInDS, dtChildInDS, dtMain;
305             
306             GenerateTestData(out ds,
307                              out dtMainInDS,
308                              out dtChildInDS,
309                              out dtMain);
310             
311             StringWriter sw = new StringWriter();
312             
313             // Get XML for recursive DataTable writes of the same data as in
314             // the DataSet.
315             sw.GetStringBuilder().Length = 0;
316             dtMainInDS.WriteXml(sw, true);
317             string xmlDTNone = sw.ToString();
318             
319             sw.GetStringBuilder().Length = 0;
320             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
321             string xmlDTDiffGram = sw.ToString();
322
323             sw.GetStringBuilder().Length = 0;
324             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
325             string xmlMultiTable = sw.ToString();
326             
327             sw.GetStringBuilder().Length = 0;
328             dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
329             string xmlSingleTable = sw.ToString();
330             
331             DataTable newdt = new DataTable();
332
333             try {
334                 newdt.ReadXml(new StringReader(xmlDTNone));
335                 Assert.Fail("Test#01");
336             } catch(InvalidOperationException) {
337                 // DataTable does not support schema inference from Xml.
338             }
339             
340             try {
341                 newdt.ReadXml(new StringReader(xmlDTDiffGram));
342                 Assert.Fail("Test#02");
343             } catch(InvalidOperationException) {
344                 // DataTable does not support schema inference from Xml.
345             }
346             
347             DataTable multiTable = new DataTable();
348             multiTable.ReadXml(new StringReader(xmlMultiTable));
349             // Do some simple checks to see if the main dataset was created
350             // and if there are relationships present.
351             Assert.AreEqual("MyDataSet", multiTable.DataSet.DataSetName, "Test#03");
352             Assert.AreEqual(1, multiTable.ChildRelations.Count, "Test#04");
353             Assert.AreEqual(1, multiTable.Constraints.Count, "Test#05");
354             // Write the table back out and check to see that the XML is
355             // the same as before.
356             sw.GetStringBuilder().Length = 0;
357             multiTable.WriteXml(sw, XmlWriteMode.WriteSchema, true);
358             string xmlMultiTableCheck = sw.ToString();
359             Assert.IsTrue (xmlMultiTable.IndexOf ("UseCurrentLocale") > 0, "Test#06-premise1");
360             Assert.IsTrue (xmlMultiTable.IndexOf ("keyref") > 0, "Test#06-premise2");
361             Assert.AreEqual(xmlMultiTable, xmlMultiTableCheck, "Test#06");
362             
363             DataTable singleTable = new DataTable();
364             singleTable.ReadXml(new StringReader(xmlSingleTable));
365             // Do some simple checks on the table.
366             Assert.IsNull(singleTable.DataSet, "Test#07");
367             Assert.AreEqual("Main", singleTable.TableName, "Test#08");
368             // Write the table out and check if it's the same.
369             sw.GetStringBuilder().Length = 0;
370             singleTable.WriteXml(sw, XmlWriteMode.WriteSchema);
371             string xmlSingleTableCheck = sw.ToString();
372             Assert.AreEqual(xmlSingleTable, xmlSingleTableCheck, "Test#09");
373         }
374     }
375 }