Merge pull request #1196 from tritao/master
[mono.git] / mcs / class / System.XML / Test / System.Xml.Serialization / XmlSchemaImporterTests.cs
index 99537662f1acfb5f702838aa16badf548155a5cf..fe4838cb2e9d8184999494e9a45d2809f8550f8f 100644 (file)
@@ -3,24 +3,50 @@
 //
 // Author:
 //   Gert Driesen (drieseng@users.sourceforge.net)
+//   Atsushi Enomoto (atsushi@ximian.com)
 //
-// (C) 2005 Novell
+// (C) 2005 Gert Driesen
+// Copyright (C) 2006-2007 Novell, Inc.
 // 
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.CodeDom;
+using System.CodeDom.Compiler;
 using System.Collections;
 using System.Globalization;
 using System.IO;
 using System.Xml;
 using System.Xml.Schema;
 using System.Xml.Serialization;
-
+#if !MOBILE
+using Microsoft.CSharp;
+#endif
 using NUnit.Framework;
 
 using MonoTests.System.Xml.TestClasses;
 
-namespace MonoTests.System.XmlSerialization
+namespace MonoTests.System.Xml.Serialization
 {
        [TestFixture]
        public class XmlSchemaImporterTests
@@ -866,6 +892,8 @@ namespace MonoTests.System.XmlSerialization
                        Assert.AreEqual ("UInt16", map.TypeName, "#6");
                }
 
+#if !MOBILE
+
                [Test]
                public void ImportTypeMapping_EnumSimpleContent ()
                {
@@ -945,6 +973,86 @@ namespace MonoTests.System.XmlSerialization
                        Assert.AreEqual ("System.Int32", field.Type.BaseType, "#B2");
 #endif
                }
+
+               XmlSchemaImporter CreateSchemaImporter (string xsd)
+               {
+                       XmlSchemas s = new XmlSchemas ();
+                       XmlReader r = new XmlTextReader (xsd, XmlNodeType.Document, null);
+                       s.Add (XmlSchema.Read (r, null));
+                       return new XmlSchemaImporter (s);
+               }
+
+               [Test]
+               public void ImportTypeMapping_NullableField ()
+               {
+                       string xsd = @"
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='Root'>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name='Bar' nillable='true' type='xs:int' />
+      </xs:sequence>
+      <xs:attribute name='A' use='optional' type='xs:int' />
+    </xs:complexType>
+  </xs:element>
+</xs:schema>";
+                       XmlSchemaImporter imp = CreateSchemaImporter (xsd);
+                       XmlTypeMapping map = imp.ImportTypeMapping (new XmlQualifiedName ("Root"));
+                       CodeNamespace cns = ExportCode (map);
+#if NET_2_0
+                       CodeMemberProperty p = (CodeMemberProperty) FindMember (FindType (cns, "Root"), "Bar");
+                       Assert.AreEqual (1, p.Type.TypeArguments.Count, "2.0 #1");
+                       Assert.AreEqual ("System.Int32", p.Type.TypeArguments [0].BaseType, "2.0 #2");
+#else
+                       CodeMemberField f = (CodeMemberField) FindMember (FindType (cns, "Root"), "Bar");
+                       Assert.AreEqual ("System.Int32", f.Type.BaseType, "1.x #1");
+#endif
+               }
+
+               [Test]
+               public void ImportMembersMapping_NullableField ()
+               {
+                       string xsd = @"
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='Root'>
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name='Bar' nillable='true' type='xs:int' />
+        <xs:element name='Baz' type='xs:int' />
+      </xs:sequence>
+      <xs:attribute name='A' use='optional' type='xs:int' />
+    </xs:complexType>
+  </xs:element>
+</xs:schema>";
+                       XmlSchemaImporter imp = CreateSchemaImporter (xsd);
+                       XmlMembersMapping map = imp.ImportMembersMapping (new XmlQualifiedName ("Root"));
+                       Assert.AreEqual (3, map.Count, "#1");
+                       XmlMemberMapping bar = map [0];
+                       Assert.AreEqual ("Bar", bar.ElementName, "#2-1");
+                       Assert.IsFalse (bar.CheckSpecified, "#2-2");
+                       XmlMemberMapping baz = map [1];
+                       Assert.AreEqual ("Baz", baz.ElementName, "#3-1");
+                       Assert.IsFalse (baz.CheckSpecified, "#3-2");
+                       XmlMemberMapping a = map [2];
+                       Assert.AreEqual ("A", a.ElementName, "#4-1"); // ... element name?
+                       Assert.IsTrue (a.CheckSpecified, "#4-2");
+
+#if NET_2_0
+                       Assert.IsNull (map.TypeName, "#4-3"); // null at this state
+                       Assert.IsNull (map.TypeNamespace, "#4-4"); // null at this state
+
+                       CodeDomProvider p = new Microsoft.CSharp.CSharpCodeProvider ();
+                       Assert.AreEqual ("System.Nullable`1[System.Int32]", bar.GenerateTypeName (p), "#5-1");
+                       Assert.AreEqual ("System.Int32", baz.GenerateTypeName (p), "#5-2");
+
+                       var table = new Hashtable ();
+                       var exp = new XmlCodeExporter (new CodeNamespace ("foobar"), null, p, CodeGenerationOptions.None, table);
+                       exp.ExportMembersMapping (map);
+                       Assert.AreEqual (null, map.TypeName, "#5-3"); // filled after ExportExportMembersMapping().
+                       Assert.AreEqual (null, map.TypeNamespace, "#5-4"); // filled after ExportMembersMapping().
+                       // table contains some internal stuff that does not make sense in any public API.
+#endif
+               }
                
                CodeNamespace ExportCode (XmlTypeMapping map)
                {
@@ -970,28 +1078,170 @@ namespace MonoTests.System.XmlSerialization
                        return null;
                }
 
-               private static XmlSchemas ExportType (Type type)
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void ImportTypeMappingNonExistent ()
                {
-                       XmlReflectionImporter ri = new XmlReflectionImporter ("NS" + type.Name);
-                       XmlSchemas schemas = new XmlSchemas ();
-                       XmlSchemaExporter sx = new XmlSchemaExporter (schemas);
-                       XmlTypeMapping tm = ri.ImportTypeMapping (type);
-                       sx.ExportTypeMapping (tm);
-                       return schemas;
+                       XmlSchemas xss = new XmlSchemas ();
+                       xss.Add (new XmlSchema ());
+                       XmlSchemaImporter imp = new XmlSchemaImporter (xss);
+                       imp.ImportTypeMapping (new XmlQualifiedName ("foo"));
+               }
+
+               [Test]
+               public void AnyTypeTopLevelElementImportsAllComplexTypes ()
+               {
+                       string xsd = @"
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='Root' type='xs:anyType' />
+  <xs:complexType name='FooType'>
+    <xs:sequence>
+      <xs:element name='Child1' type='xs:string' />
+      <xs:element name='Child2' type='xs:string' />
+      <xs:element name='Child3' type='xs:string' />
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name='BarType' />
+</xs:schema>";
+                       XmlSchemas xss = new XmlSchemas ();
+                       xss.Add (XmlSchema.Read (new XmlTextReader (new StringReader (xsd)), null));
+                       XmlSchemaImporter imp = new XmlSchemaImporter (xss);
+                       CodeNamespace cns = new CodeNamespace ();
+                       XmlCodeExporter exp = new XmlCodeExporter (cns);
+                       exp.ExportTypeMapping (imp.ImportTypeMapping (new XmlQualifiedName ("Root")));
+                       bool foo = false, bar = false;
+                       foreach (CodeTypeDeclaration td in cns.Types) {
+                               if (td.Name == "FooType")
+                                       foo = true;
+                               else if (td.Name == "BarType")
+                                       bar = true;
+                       }
+                       Assert.IsTrue (foo, "FooType not found");
+                       Assert.IsTrue (bar, "BarType not found");
+               }
+
+               [Test]
+               public void DefaultTypeTopLevelElementImportsAllComplexTypes ()
+               {
+                       string xsd = @"
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='Root' />
+  <xs:complexType name='FooType'>
+    <xs:sequence>
+      <xs:element name='Child1' type='xs:string' />
+      <xs:element name='Child2' type='xs:string' />
+      <xs:element name='Child3' type='xs:string' />
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name='BarType' />
+</xs:schema>";
+                       XmlSchemas xss = new XmlSchemas ();
+                       xss.Add (XmlSchema.Read (new XmlTextReader (new StringReader (xsd)), null));
+                       XmlSchemaImporter imp = new XmlSchemaImporter (xss);
+                       CodeNamespace cns = new CodeNamespace ();
+                       XmlCodeExporter exp = new XmlCodeExporter (cns);
+                       exp.ExportTypeMapping (imp.ImportTypeMapping (new XmlQualifiedName ("Root")));
+                       bool foo = false, bar = false;
+                       foreach (CodeTypeDeclaration td in cns.Types) {
+                               if (td.Name == "FooType")
+                                       foo = true;
+                               else if (td.Name == "BarType")
+                                       bar = true;
+                       }
+                       Assert.IsTrue (foo, "FooType not found");
+                       Assert.IsTrue (bar, "BarType not found");
+               }
+
+               [Test]
+               public void ImportComplexDerivationByExtension ()
+               {
+                       string xsd = @"<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='Root' type='DerivedType' />
+  <xs:complexType name='DerivedType'>
+    <xs:complexContent>
+      <xs:extension base='BaseType'>
+        <xs:attribute name='Foo' type='xs:string' />
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name='BaseType'>
+    <xs:attribute name='Foo' type='xs:string' />
+  </xs:complexType>
+</xs:schema>";
+                       XmlSchemaImporter imp = CreateImporter (xsd);
+                       CodeNamespace cns = new CodeNamespace ();
+                       XmlCodeExporter exp = new XmlCodeExporter (cns);
+                       exp.ExportTypeMapping (imp.ImportTypeMapping (new XmlQualifiedName ("Root")));
                }
 
+               [Test]
+               public void ImportSimpleSchemaType ()
+               {
+                       string xsd = @"
+<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>
+  <xs:element name='a' type='b' />
+  <xs:simpleType name='b'>
+    <xs:restriction base='xs:string'>
+      <xs:enumeration value='v1'/>
+      <xs:enumeration value='v2'/>
+      <xs:enumeration value='v3'/>
+    </xs:restriction>
+  </xs:simpleType>
+</xs:schema>";
+                       XmlSchemaImporter imp = CreateImporter (xsd);
+                       XmlTypeMapping tm = imp.ImportTypeMapping (new XmlQualifiedName ("a"));
+                       Assert.AreEqual ("a", tm.ElementName, "#1");
+                       Assert.AreEqual ("b", tm.TypeName, "#2");
+               }
+
+               [Test]
+               public void ImportWildcardElementAsClass ()
+               {
+                       var xss = new XmlSchemas ();
+                       xss.Add (XmlSchema.Read (XmlReader.Create ("Test/XmlFiles/xsd/670945-1.xsd"), null));
+                       xss.Add (XmlSchema.Read (XmlReader.Create ("Test/XmlFiles/xsd/670945-2.xsd"), null));
+                       var imp = new XmlSchemaImporter (xss);
+                       var xtm = imp.ImportSchemaType (new XmlQualifiedName ("SystemDateTime", "http://www.onvif.org/ver10/schema"));
+                       var cns = new CodeNamespace ();
+                       var exp = new XmlCodeExporter (cns);
+                       exp.ExportTypeMapping (xtm);
+                       var sw = new StringWriter ();
+                       new CSharpCodeProvider ().GenerateCodeFromNamespace (cns, sw, null);
+                       Assert.IsTrue (sw.ToString ().IndexOf ("class SystemDateTimeExtension") > 0, "#1");
+               }
+
+               XmlSchemaImporter CreateImporter (params string [] schemaXmlStrings)
+               {
+                       XmlSchemas xss = new XmlSchemas ();
+                       foreach (string xsd in schemaXmlStrings)
+                               xss.Add (XmlSchema.Read (new XmlTextReader (new StringReader (xsd)), null));
+                       return new XmlSchemaImporter (xss);
+               }
+
+#endif
+
                private static ArrayList GetXmlQualifiedNames (XmlSchemas schemas)
                {
                        ArrayList qnames = new ArrayList ();
-
+                       
                        foreach (XmlSchema schema in schemas) {
                                if (!schema.IsCompiled) schema.Compile (null);
                                foreach (XmlSchemaObject ob in schema.Items)
                                        if (ob is XmlSchemaElement)
                                                qnames.Add (((XmlSchemaElement) ob).QualifiedName);
                        }
-
+                       
                        return qnames;
                }
+
+               private static XmlSchemas ExportType (Type type)
+               {
+                       XmlReflectionImporter ri = new XmlReflectionImporter ("NS" + type.Name);
+                       XmlSchemas schemas = new XmlSchemas ();
+                       XmlSchemaExporter sx = new XmlSchemaExporter (schemas);
+                       XmlTypeMapping tm = ri.ImportTypeMapping (type);
+                       sx.ExportTypeMapping (tm);
+                       return schemas;
+               }
        }
 }