Skip to content

Commit

Permalink
Improve support for xs:list (fixes #92)
Browse files Browse the repository at this point in the history
Improve tests
Fix base64 support in XmlSampleGenerator
  • Loading branch information
Michael Ganss committed Nov 30, 2018
1 parent ec95c6f commit 88995ae
Show file tree
Hide file tree
Showing 8 changed files with 596 additions and 91 deletions.
2 changes: 1 addition & 1 deletion XmlSampleGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,7 @@ public override string GenerateValue() {
return Convert.ToBase64String(enumValue as byte[]);
}
else {
return "base64Binary Content";
return "cnRjbGNyZW9scg==";
}
}
}
Expand Down
29 changes: 22 additions & 7 deletions XmlSchemaClassGenerator.Tests/XmlSchemaClassGenerator.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,27 @@
<ProjectReference Include="..\XmlSchemaClassGenerator\XmlSchemaClassGenerator.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.msbuild" Version="2.1.1" />
<PackageReference Include="coverlet.msbuild" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Glob.cs" Version="2.0.13" />
<PackageReference Include="Microsoft.Net.Compilers.netcore" Version="1.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="System.CodeDom" Version="4.5.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="xunit.runner.console" Version="2.4.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.extensibility.core" Version="2.4.0" />
<PackageReference Include="xunit.extensibility.execution" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.console" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.extensibility.core" Version="2.4.1" />
<PackageReference Include="xunit.extensibility.execution" Version="2.4.1" />
</ItemGroup>
<PropertyGroup>
<SonarQubeExclude>true</SonarQubeExclude>
Expand Down Expand Up @@ -425,6 +434,12 @@
<None Update="xsd\is24\search\shortlist-1.0.xsd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="xsd\list\list.xsd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="xsd\simple\simple.xsd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="xsd\ts-api\ts-api_2_8.xsd">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
68 changes: 58 additions & 10 deletions XmlSchemaClassGenerator.Tests/XmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@
using System.Xml.Schema;
using System.Xml.Serialization;
using Xunit;
using Xunit.Abstractions;

namespace XmlSchemaClassGenerator.Tests
{
[TestCaseOrderer("XmlSchemaClassGenerator.Tests.PriorityOrderer", "XmlSchemaClassGenerator.Tests")]
public class XmlTests
{
private readonly ITestOutputHelper Output;

public XmlTests(ITestOutputHelper output)
{
Output = output;
}

private IEnumerable<string> ConvertXml(string name, string xsd, Generator generatorPrototype = null)
{
var writer = new MemoryOutputWriter();
Expand Down Expand Up @@ -56,6 +64,8 @@ private IEnumerable<string> ConvertXml(string name, string xsd, Generator genera
const string IS24Pattern = @"xsd\is24\*\*.xsd";
const string IS24ImmoTransferPattern = @"xsd\is24immotransfer\is24immotransfer.xsd";
const string WadlPattern = @"xsd\wadl\*.xsd";
const string ListPattern = @"xsd\list\list.xsd";
const string SimplePattern = @"xsd\simple\simple.xsd";
const string ClientPattern = @"xsd\client\client.xsd";
const string IataPattern = @"xsd\iata\*.xsd";
const string TimePattern = @"xsd\time\time.xsd";
Expand Down Expand Up @@ -87,6 +97,22 @@ public void TestClient()
TestSamples("Client", ClientPattern);
}

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestList()
{
Compiler.Generate("List", ListPattern);
TestSamples("List", ListPattern);
}

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestSimple()
{
Compiler.Generate("Simple", SimplePattern);
TestSamples("Simple", SimplePattern);
}

[Fact, TestPriority(1)]
[UseCulture("en-US")]
public void TestIS24RestApi()
Expand Down Expand Up @@ -132,6 +158,16 @@ private void TestSamples(string name, string pattern)
DeserializeSampleXml(pattern, assembly);
}

private bool HandleValidationError(string xml, ValidationEventArgs e)
{
var line = xml.Split('\n')[e.Exception.LineNumber - 1].Substring(e.Exception.LinePosition - 1);
var severity = e.Severity == XmlSeverityType.Error ? "Error" : "Warning";
Output.WriteLine($"{severity} at line {e.Exception.LineNumber}, column {e.Exception.LinePosition}: {e.Message}");
Output.WriteLine(line);
return (e.Severity == XmlSeverityType.Error
&& !e.Message.Contains("The Pattern constraint failed")); // generator doesn't generate valid values where pattern restrictions exist, e.g. email
}

private void DeserializeSampleXml(string pattern, Assembly assembly)
{
var files = Glob.ExpandNames(pattern);
Expand All @@ -150,6 +186,8 @@ private void DeserializeSampleXml(string pattern, Assembly assembly)

set.Compile();

var anyValidXml = false;

foreach (var rootElement in set.GlobalElements.Values.Cast<XmlSchemaElement>().Where(e => !e.IsAbstract && !(e.ElementSchemaType is XmlSchemaSimpleType)))
{
var type = FindType(assembly, rootElement.QualifiedName);
Expand All @@ -162,6 +200,8 @@ private void DeserializeSampleXml(string pattern, Assembly assembly)
generator.WriteXml(xw);
var xml = sb.ToString();

File.WriteAllText("xml.xml", xml);

// validate serialized xml
var settings = new XmlReaderSettings
{
Expand All @@ -171,19 +211,21 @@ private void DeserializeSampleXml(string pattern, Assembly assembly)

var invalid = false;

settings.ValidationEventHandler += (s, e) =>
{
if (e.Severity == XmlSeverityType.Error)
invalid = true;
};
void validate(object s, ValidationEventArgs e)
{
if (HandleValidationError(xml, e)) invalid = true;
}

settings.ValidationEventHandler += validate;

var reader = XmlReader.Create(new StringReader(xml), settings);
while (reader.Read()) ;

settings.ValidationEventHandler -= validate;

// generated xml is not schema valid -> skip
if (invalid) continue;

File.WriteAllText("xml.xml", xml);
anyValidXml = true;

// deserialize from sample
var sr = new StringReader(xml);
Expand All @@ -194,21 +236,27 @@ private void DeserializeSampleXml(string pattern, Assembly assembly)

File.WriteAllText("xml2.xml", xml2);

settings.ValidationEventHandler += (s, e) =>
void validate2(object s, ValidationEventArgs e)
{
throw e.Exception;
if (HandleValidationError(xml2, e)) throw e.Exception;
};

settings.ValidationEventHandler += validate2;

reader = XmlReader.Create(new StringReader(xml2), settings);
while (reader.Read()) ;

settings.ValidationEventHandler -= validate2;

// deserialize again
sr = new StringReader(xml2);
var o2 = serializer.Deserialize(sr);

AssertEx.Equal(o, o2);
}
}

Assert.True(anyValidXml, "No valid generated XML for this test");
}

private Type FindType(Assembly assembly, XmlQualifiedName xmlQualifiedName)
Expand Down Expand Up @@ -406,7 +454,7 @@ public partial class Group_Name
/// <para xml:lang=""de"">Ruft den Text ab oder legt diesen fest.</para>
/// <para xml:lang=""en"">Gets or sets the text value.</para>
/// </summary>
[System.Xml.Serialization.XmlTextAttribute(DataType=""string"")]
[System.Xml.Serialization.XmlTextAttribute()]
public string Value { get; set; }
/// <summary>
Expand Down
67 changes: 67 additions & 0 deletions XmlSchemaClassGenerator.Tests/xsd/list/list.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://me.me" xmlns:my="http://me.me" elementFormDefault="unqualified">

<xs:simpleType name="enumType">
<xs:restriction base="xs:integer">
<xs:enumeration value="1" />
<xs:enumeration value="2" />
<xs:enumeration value="3" />
</xs:restriction>
</xs:simpleType>

<xs:simpleType name="enumTypeList">
<xs:restriction>
<xs:simpleType>
<xs:list itemType="my:enumType" />
</xs:simpleType>
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>

<xs:simpleType name="enumTypeList2">
<xs:list itemType="my:enumType" />
</xs:simpleType>

<xs:complexType name="myClass">
<xs:sequence>
<xs:element name="enumElem" type="my:enumTypeList" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="timeListElem" minOccurs="0">
<xs:simpleType>
<xs:list itemType="xs:time" />
</xs:simpleType>
</xs:element>
<xs:element name="hexElem" type="hexBinary" />
<xs:element name="base64ListElem">
<xs:simpleType>
<xs:list itemType="xs:base64Binary" />
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:attribute name="enumAttr" type="my:enumTypeList2"></xs:attribute>
<xs:attribute name="intListAttr">
<xs:simpleType>
<xs:list itemType="xs:integer" />
</xs:simpleType>
</xs:attribute>
<xs:attribute name="timeListAttr">
<xs:simpleType>
<xs:list itemType="xs:time" />
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base64Attr" type="base64Binary"></xs:attribute>
<xs:attribute name="hexAttr" type="hexBinary"></xs:attribute>
<xs:attribute name="base64ListAttr">
<xs:simpleType>
<xs:list itemType="xs:base64Binary" />
</xs:simpleType>
</xs:attribute>
<xs:attribute name="hexListAttr">
<xs:simpleType>
<xs:list itemType="xs:hexBinary" />
</xs:simpleType>
</xs:attribute>
</xs:complexType>

<xs:element name="myElement" type="my:myClass" />

</xs:schema>
Loading

0 comments on commit 88995ae

Please sign in to comment.