Merge pull request #3091 from alexanderkyte/mobile_static_fix_mcs_tests
[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         public static readonly string EOL = Environment.NewLine;
39
40         void StandardizeXmlFormat(ref string xml)
41         {
42             XmlDocument doc = new XmlDocument();
43             doc.LoadXml(xml);
44             StringWriter sw = new StringWriter();
45             doc.Save(sw);
46             xml = sw.ToString();
47         }
48         
49         void GenerateTestData(out DataSet ds,
50                               out DataTable dtMainInDS,
51                               out DataTable dtChildInDS,
52                               out DataTable dtMain)
53         {
54             ds = new DataSet("MyDataSet");
55
56             // Create a primary table and populate it with some data.  Make a
57             // copy of the primary table and put it into the dataset.
58             dtMain = new DataTable("Main");
59             dtMain.Columns.Add(new DataColumn("ID", typeof(int)));
60             dtMain.Columns.Add(new DataColumn("Data", typeof(string)));
61             
62             DataRow row = dtMain.NewRow();
63             row["ID"] = 1;
64             row["Data"] = "One";
65             dtMain.Rows.Add(row);
66             
67             row = dtMain.NewRow();
68             row["ID"] = 2;
69             row["Data"] = "Two";
70             dtMain.Rows.Add(row);
71             
72             row = dtMain.NewRow();
73             row["ID"] = 3;
74             row["Data"] = "Three";
75             dtMain.Rows.Add(row);
76             
77             dtMainInDS = dtMain.Copy();
78             ds.Tables.Add(dtMainInDS);
79             
80             // Create a child table.  Make a copy of the child table and put
81             // it into the dataset.
82             dtChildInDS = new DataTable("Child");
83             dtChildInDS.Columns.Add(new DataColumn("ID", typeof(int)));
84             dtChildInDS.Columns.Add(new DataColumn("PID", typeof(int)));
85             dtChildInDS.Columns.Add(new DataColumn("ChildData", typeof(string)));
86             
87             row = dtChildInDS.NewRow();
88             row["ID"] = 1;
89             row["PID"] = 1;
90             row["ChildData"] = "Parent1Child1";
91             dtChildInDS.Rows.Add(row);
92             
93             row = dtChildInDS.NewRow();
94             row["ID"] = 2;
95             row["PID"] = 1;
96             row["ChildData"] = "Parent1Child2";
97             dtChildInDS.Rows.Add(row);
98             
99             row = dtChildInDS.NewRow();
100             row["ID"] = 3;
101             row["PID"] = 2;
102             row["ChildData"] = "Parent2Child3";
103             dtChildInDS.Rows.Add(row);
104             
105             ds.Tables.Add(dtChildInDS);
106             
107             // Set up the relation in the dataset.
108             ds.Relations.Add(new DataRelation("MainToChild",
109                                               dtMainInDS.Columns["ID"],
110                                               dtChildInDS.Columns["PID"]));
111         }
112         
113         [Test]
114         public void TestWriteXml()
115         {
116             DataSet ds;
117             DataTable dtMainInDS, dtChildInDS, dtMain;
118             
119             GenerateTestData(out ds,
120                              out dtMainInDS,
121                              out dtChildInDS,
122                              out dtMain);
123             
124             StringWriter sw = new StringWriter();
125             
126             // Get XML for DataSet writes.
127             sw.GetStringBuilder().Length = 0;
128             ds.WriteXml(sw);
129             string xmlDSNone = sw.ToString().Replace ("\n", EOL);
130             
131             sw.GetStringBuilder().Length = 0;
132             ds.WriteXml(sw, XmlWriteMode.DiffGram);
133             string xmlDSDiffGram = sw.ToString().Replace ("\n", EOL);
134
135             sw.GetStringBuilder().Length = 0;
136             ds.WriteXml(sw, XmlWriteMode.WriteSchema);
137             string xmlDSWriteSchema = sw.ToString();
138
139             // Get XML for recursive DataTable writes of the same data as in
140             // the DataSet.
141             sw.GetStringBuilder().Length = 0;
142             dtMainInDS.WriteXml(sw, true);
143             string xmlDTNone = sw.ToString();
144             
145             sw.GetStringBuilder().Length = 0;
146             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
147             string xmlDTDiffGram = sw.ToString();
148
149             sw.GetStringBuilder().Length = 0;
150             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
151             string xmlDTWriteSchema = sw.ToString();
152             
153             // The schema XML written by the DataTable call has an extra element
154             // in the element for the dataset schema definition.  We remove that
155             // extra attribute and then check to see if the rest of the xml is
156             // identical.
157             XmlDocument doc = new XmlDocument();
158             doc.LoadXml(xmlDTWriteSchema);
159             XmlNode node = doc.DocumentElement.FirstChild.FirstChild;
160             XmlAttribute a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
161             Assert.IsNotNull(a, "Test#01");
162             Assert.AreEqual("Main", a.Value, "Test#02");
163             
164             node.Attributes.Remove(a);
165             sw.GetStringBuilder().Length = 0;
166             doc.Save(sw);
167             xmlDTWriteSchema = sw.ToString();
168             
169             StandardizeXmlFormat(ref xmlDSWriteSchema);
170             
171             Assert.AreEqual(xmlDSNone, xmlDTNone, "Test#03");
172             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGram, "Test#04");
173             Assert.IsTrue (xmlDSWriteSchema.IndexOf ("UseCurrentLocale") > 0, "Test#05-premise1");
174             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchema, "Test#05");
175                                
176             // Now that we've tested writing tables (including children),
177             // we will go on to test the cases where the hierarchy flag
178             // is false.  For this, we will test one table inside the
179             // dataset and one table outside the dataset.
180             
181             // First, we fix our test DataSet to only have a single table
182             // with no relations.  Then, we go about comparing the XML.
183             // Get XML for DataSet writes.
184             ds.Tables[1].Constraints.Remove(ds.Tables[1].Constraints[0]);
185             ds.Tables[0].Constraints.Remove(ds.Tables[0].Constraints[0]);
186             ds.Tables[0].ChildRelations.Remove("MainToChild");
187             ds.Tables.Remove("Child");
188             
189             sw.GetStringBuilder().Length = 0;
190             ds.WriteXml(sw);
191             xmlDSNone = sw.ToString().Replace ("\n", EOL);
192             
193             sw.GetStringBuilder().Length = 0;
194             ds.WriteXml(sw, XmlWriteMode.DiffGram);
195             xmlDSDiffGram = sw.ToString().Replace ("\n", EOL);
196
197             sw.GetStringBuilder().Length = 0;
198             ds.WriteXml(sw, XmlWriteMode.WriteSchema);
199             xmlDSWriteSchema = sw.ToString();
200             
201             // Get all the DataTable.WriteXml results.
202             sw.GetStringBuilder().Length = 0;
203             dtMainInDS.WriteXml(sw);
204             string xmlDTNoneInDS = sw.ToString();
205             
206             sw.GetStringBuilder().Length = 0;
207             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram);
208             string xmlDTDiffGramInDS = sw.ToString();
209
210             sw.GetStringBuilder().Length = 0;
211             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema);
212             string xmlDTWriteSchemaInDS = sw.ToString();
213
214             sw.GetStringBuilder().Length = 0;
215             dtMain.WriteXml(sw);
216             string xmlDTNoneNoDS = sw.ToString();
217
218             sw.GetStringBuilder().Length = 0;
219             dtMain.WriteXml(sw, XmlWriteMode.DiffGram);
220             string xmlDTDiffGramNoDS = sw.ToString();
221
222             sw.GetStringBuilder().Length = 0;
223             dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
224             string xmlDTWriteSchemaNoDS = sw.ToString();
225             
226             Assert.AreEqual(xmlDSNone, xmlDTNoneInDS, "Test#06");
227
228             // The only difference between the xml output from inside the
229             // dataset and the xml output from outside the dataset is that
230             // there's a fake <DocumentElement> tag surrounding tbe table
231             // in the second case.  We replace it with the name of the
232             // dataset for testing purposes.
233             doc.LoadXml(xmlDTNoneNoDS);
234             Assert.AreEqual("DocumentElement", doc.DocumentElement.Name, "Test#07");
235             sw.GetStringBuilder().Length = 0;
236             doc.Save(sw);
237             xmlDTNoneNoDS = sw.ToString();
238             xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("<DocumentElement>", "<MyDataSet>");
239             xmlDTNoneNoDS = xmlDTNoneNoDS.Replace("</DocumentElement>", "</MyDataSet>");
240             
241             StandardizeXmlFormat(ref xmlDSNone);
242             
243             Assert.AreEqual(xmlDSNone, xmlDTNoneNoDS, "Test#08");
244             
245             // Now check the DiffGram.
246             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramInDS, "Test#09");
247             
248             doc.LoadXml(xmlDTDiffGramNoDS);
249             Assert.AreEqual("DocumentElement", doc.DocumentElement.FirstChild.Name, "Test#10");
250             xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("<DocumentElement>", "<MyDataSet>");
251             xmlDTDiffGramNoDS = xmlDTDiffGramNoDS.Replace("</DocumentElement>", "</MyDataSet>");
252
253             Assert.AreEqual(xmlDSDiffGram, xmlDTDiffGramNoDS, "Test#11");
254             
255             // Finally we check the WriteSchema version of the data.  First
256             // we remove the extra "msdata:MainDataTable" attribute from
257             // the schema declaration part of the DataTable xml.
258             doc = new XmlDocument();
259             doc.LoadXml(xmlDTWriteSchemaInDS);
260             node = doc.DocumentElement.FirstChild.FirstChild;
261             a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
262             Assert.IsNotNull(a, "Test#12");
263             Assert.AreEqual("Main", a.Value, "Test#13");
264             node.Attributes.Remove(a);
265             sw.GetStringBuilder().Length = 0;
266             doc.Save(sw);
267             xmlDTWriteSchemaInDS = sw.ToString();
268             
269             StandardizeXmlFormat(ref xmlDSWriteSchema);
270
271             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaInDS, "Test#14");
272             
273             // Remove the extra "msdata:MainDataTable" for the other test case.
274             // Also make sure we have "NewDataSet" in the appropriate locations.
275             doc = new XmlDocument();
276             doc.LoadXml(xmlDTWriteSchemaNoDS);
277             node = doc.DocumentElement.FirstChild.FirstChild;
278             a = (XmlAttribute)node.Attributes.GetNamedItem("msdata:MainDataTable");
279             Assert.IsNotNull(a, "Test#15");
280             Assert.AreEqual("Main", a.Value, "Test#16");
281             node.Attributes.Remove(a);
282             sw.GetStringBuilder().Length = 0;
283             doc.Save(sw);
284             
285             Assert.AreEqual("NewDataSet", doc.DocumentElement.Name, "Test#17");
286             Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.Attributes["id"].Value, "Test#18");
287             Assert.AreEqual("NewDataSet", doc.DocumentElement.FirstChild.FirstChild.Attributes["name"].Value, "Test#19");
288             
289             xmlDTWriteSchemaNoDS = sw.ToString();
290             
291             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("<NewDataSet>","<MyDataSet>");
292             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("</NewDataSet>","</MyDataSet>");
293             xmlDTWriteSchemaNoDS = xmlDTWriteSchemaNoDS.Replace("\"NewDataSet\"","\"MyDataSet\"");
294
295             Assert.AreEqual(xmlDSWriteSchema, xmlDTWriteSchemaNoDS, "Test#20");
296         }
297         
298         [Test]
299         public void TestReadXml()
300         {
301             // For reading, DataTable.ReadXml only supports reading in xml with
302             // the schema included.  This means that we can only read in XML
303             // that was generated with the WriteSchema flag.  
304             DataSet ds;
305             DataTable dtMainInDS, dtChildInDS, dtMain;
306             
307             GenerateTestData(out ds,
308                              out dtMainInDS,
309                              out dtChildInDS,
310                              out dtMain);
311             
312             StringWriter sw = new StringWriter();
313             
314             // Get XML for recursive DataTable writes of the same data as in
315             // the DataSet.
316             sw.GetStringBuilder().Length = 0;
317             dtMainInDS.WriteXml(sw, true);
318             string xmlDTNone = sw.ToString();
319             
320             sw.GetStringBuilder().Length = 0;
321             dtMainInDS.WriteXml(sw, XmlWriteMode.DiffGram, true);
322             string xmlDTDiffGram = sw.ToString();
323
324             sw.GetStringBuilder().Length = 0;
325             dtMainInDS.WriteXml(sw, XmlWriteMode.WriteSchema, true);
326             string xmlMultiTable = sw.ToString();
327             
328             sw.GetStringBuilder().Length = 0;
329             dtMain.WriteXml(sw, XmlWriteMode.WriteSchema);
330             string xmlSingleTable = sw.ToString();
331             
332             DataTable newdt = new DataTable();
333
334             try {
335                 newdt.ReadXml(new StringReader(xmlDTNone));
336                 Assert.Fail("Test#01");
337             } catch(InvalidOperationException) {
338                 // DataTable does not support schema inference from Xml.
339             }
340             
341             try {
342                 newdt.ReadXml(new StringReader(xmlDTDiffGram));
343                 Assert.Fail("Test#02");
344             } catch(InvalidOperationException) {
345                 // DataTable does not support schema inference from Xml.
346             }
347             
348             DataTable multiTable = new DataTable();
349             multiTable.ReadXml(new StringReader(xmlMultiTable));
350             // Do some simple checks to see if the main dataset was created
351             // and if there are relationships present.
352             Assert.AreEqual("MyDataSet", multiTable.DataSet.DataSetName, "Test#03");
353             Assert.AreEqual(1, multiTable.ChildRelations.Count, "Test#04");
354             Assert.AreEqual(1, multiTable.Constraints.Count, "Test#05");
355             // Write the table back out and check to see that the XML is
356             // the same as before.
357             sw.GetStringBuilder().Length = 0;
358             multiTable.WriteXml(sw, XmlWriteMode.WriteSchema, true);
359             string xmlMultiTableCheck = sw.ToString();
360             Assert.IsTrue (xmlMultiTable.IndexOf ("UseCurrentLocale") > 0, "Test#06-premise1");
361             Assert.IsTrue (xmlMultiTable.IndexOf ("keyref") > 0, "Test#06-premise2");
362             Assert.AreEqual(xmlMultiTable, xmlMultiTableCheck, "Test#06");
363             
364             DataTable singleTable = new DataTable();
365             singleTable.ReadXml(new StringReader(xmlSingleTable));
366             // Do some simple checks on the table.
367             Assert.IsNull(singleTable.DataSet, "Test#07");
368             Assert.AreEqual("Main", singleTable.TableName, "Test#08");
369             // Write the table out and check if it's the same.
370             sw.GetStringBuilder().Length = 0;
371             singleTable.WriteXml(sw, XmlWriteMode.WriteSchema);
372             string xmlSingleTableCheck = sw.ToString();
373             Assert.AreEqual(xmlSingleTable, xmlSingleTableCheck, "Test#09");
374         }
375     }
376 }