public void TestHtmlExample() { var schema = new Schema(TestHelper.GetSimpleHTMLSchema()); var document = TestHelper.StreamParseString(@" (html [ (head) (body [ (p ""string"") (img {src ""file.png""}) (img {src ""file2.png"" title ""file 2""}) (p ""other string"") (img {title ""other order"" src ""file3.png""}) ]) ]) " , schema); Assert.IsTrue(schema.Validate(document)); }
public void TestExceptions() { const string NOT_HERE = "Should've thrown an Exception instead of ending up here."; var d = TestHelper.ParseString("(node {a 0} [1 2])"); try { new Schema(d); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema must be a (schema) node.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element (literal-element {type ""number""})} (invalid-node-type))")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Invalid schema type description.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element (literal-element {type ""type""})})")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Literal element references an undeclared type 'ud:type'", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (node-type {name ""type""})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Literal element references non-literal type.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (node-element {name ""n"" type ""type""})}) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Node element references an undeclared type 'ud:type'", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (node-element {name ""n"" type ""type""})} (literal-type {name ""type"" base-type ""number""})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Node element references non-node type.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element 1})")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema element description must be a node.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element (list [1 2])})")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema list description must have exactly one element description.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element (unknown)})")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Invalid schema element description.", e.Message); } try { new Schema(TestHelper.ParseString(@"(schema {top-element (literal-element {type ""type""})} 1)")); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema type description must be a node.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions 1})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema condition description must be a node.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions (condition [1 2])})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema condition description must have exactly one value.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions (condition 1)})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema condition description must be a string.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions (one-of-conditions)})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema one-of-conditions description must have at least one value.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions (all-of-conditions 1)})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("All of schema all-of-conditions description values must be nodes.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""type""})} (literal-type {name ""type"" conditions (c)})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Invalid schema condition description.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (not-attribute) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema attribute description must be an (attribute) node.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (attribute [1 2]) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Schema attribute description must have exactly one element description.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (attribute (literal-element {type ""number""})) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'name' expected, but not found.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (attribute {name true} (literal-element {type ""number""})) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'name' expected to be a string.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (attribute {name ""n""} (literal-element {type ""number""})) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'required' expected, but not found.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""number""})} (node-type {name ""type""} [ (attribute {name ""n"" required 1} (literal-element {type ""number""})) ])) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'required' expected to be a boolean value.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (list {min true} (literal-element {type ""number""}))}) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'min' expected to be a number.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (list {min 1.1} (literal-element {type ""number""}))}) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Attribute 'min' expected to be an integer.", e.Message); } // schema type exceptions try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""ud""})} (literal-type {name ""ud"" base-type ""unknown""})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Unknown built-in type 'unknown' used in literal-type description.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""ud""})} (literal-type {name ""ud"" base-type ""unknown"" conditions (condition ""=5]/[=1"")})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Invalid condition '=5]/[=1'.", e.Message); } try { new Schema(TestHelper.ParseString(@" (schema {top-element (literal-element {type ""ud""})} (literal-type {name ""ud"" base-type ""unknown"" conditions (condition ""]"")})) " )); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Invalid condition ']'.", e.Message); } // validate partial var schema = new Schema(TestHelper.GetSimpleHTMLSchema()); try { TestHelper.StreamParseString(@" (html [ (head) (body [ (p ""string"") (img {src ""file.png""}) (img {src ""file2.png"" title ""file 2""}) (not-one-of-permitted) (p ""other string"") (img {title ""other order"" src ""file3.png""}) ]) ]) " , schema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Document already does not match the schema:\nElement \'/html/body#1/not-one-of-permitted#3\' does not match neither of allowed options even partially:\n\tElement \'/html/body#1/not-one-of-permitted#3\' must be a (p) node.\n\tElement \'/html/body#1/not-one-of-permitted#3\' must be a (img) node.\n", e.Message); } try { TestHelper.StreamParseString(@" (html [ (head) ]) " , schema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nA sequence of 2 elements expected, 1 element(s) found.", e.Message); } try { TestHelper.StreamParseString(@" (html [ (head) (body) (f**k) ]) " , schema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Document already does not match the schema:\nA sequence of 2 elements expected, more (3) elements found.", e.Message); } const string EXAMPLE = "(n {a 5})"; var SDF_EXAMPLE = TestHelper.ParseString(EXAMPLE); try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type""} [ (attribute {name ""a"" required true} (list {min 2} (literal-element {type ""number""}))) ]) ]) " )); Assert.IsTrue(!listSchema.Validate(SDF_EXAMPLE)); TestHelper.StreamParseString(EXAMPLE, listSchema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nLess than minimal (2) amount of elements in a list.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type""} [ (attribute {name ""a"" required true} (list {max 0} (literal-element {type ""number""}))) ]) ]) " )); Assert.IsTrue(!listSchema.Validate(SDF_EXAMPLE)); TestHelper.StreamParseString(EXAMPLE, listSchema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Document already does not match the schema:\nMore than maximum (0) amount of elements in a list.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type""} [ (attribute {name ""a"" required true} (sequence [ (literal-element {type ""number""}) (literal-element {type ""string""}) ])) ]) ]) " )); Assert.IsTrue(!listSchema.Validate(SDF_EXAMPLE)); TestHelper.StreamParseString(EXAMPLE, listSchema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nA sequence of 2 elements expected, one element found.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (one-of [ (literal-element {type ""null""}) (literal-element {type ""string""}) ]) }) ]) " )); var ex = "(n [null 5 null])"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.StreamParseString(ex, listSchema); Assert.Fail(NOT_HERE); } catch (InvalidDataException e) { Assert.AreEqual("Document already does not match the schema:\nElement does not match neither of allowed options even partially.", e.Message); } { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (one-of [ (literal-element {type ""nll""}) (literal-element {type ""str""}) (literal-element {type ""bln""}) ]) }) (literal-type {name ""nll"" base-type ""null""}) (literal-type {name ""str"" base-type ""string""}) (literal-type {name ""bln"" base-type ""bool"" conditions (condition ""=true"")}) ]) " )); var ex = "(n null)"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); Assert.IsTrue(!listSchema.Validate(TestHelper.ParseString("(n 5)"))); Assert.IsTrue(!listSchema.Validate(TestHelper.ParseString("(n false)"))); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd"" conditions (condition ""=true"")}) ]) " )); var ex = "(n (nd))"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nElement \'/n/nd\' does not match \'=true\' condition.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd"" conditions (condition ""=true"") children (literal-element {type ""number""})}) ]) " )); var ex = "(n (nd))"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nOne literal expected, multiple (or none) found.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd"" conditions (condition ""=true"")}) ]) " )); var ex = "(n [5 6])"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("Document already does not match the schema:\nOne node expected, multiple found.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd""} [(attribute {name ""n"" required true} (literal-element {type ""number""}))]) ]) " )); var ex = "(n (nd))"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nRequired attribute \'n\' is missing on element \'/n/nd\'.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd"" conditions (all-of-conditions [(condition ""=true"") (condition ""=false"")])}) ]) " )); var ex = "(n (nd))"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nOne of the conditions is not met:\n\tElement \'/n/nd\' does not match \'=true\' condition.", e.Message); } try { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (node-element {name ""nd"" type ""nd""}) }) (node-type {name ""nd"" conditions (one-of-conditions [(condition ""=true"") (condition ""=false"")])}) ]) " )); var ex = "(n (nd))"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); TestHelper.AssertAreDeeplyEqual(sdf, TestHelper.StreamParseString(ex, listSchema)); } catch (InvalidDataException e) { Assert.AreEqual("File is read completely, but document does not match the schema:\nNone of the following multiple conditions is not met:\n\tElement \'/n/nd\' does not match \'=true\' condition.\n\tElement \'/n/nd\' does not match \'=false\' condition.\n", e.Message); } { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type""} [ (attribute {name ""a"" required true} (sequence [ (literal-element {type ""number""}) ])) ]) ]) " )); var ex = "(n {a null})"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); } { var listSchema = new Schema(TestHelper.StreamParseString(@" (schema {top-element (node-element {name ""n"" type ""n-type""})} [ (node-type {name ""n-type"" children (sequence [ (literal-element {type ""number""}) ]) }) ]) " )); var ex = "(n [null])"; var sdf = TestHelper.ParseString(ex); Assert.IsTrue(!listSchema.Validate(sdf)); } }