Skip to content

Commit

Permalink
Add tests for validate and fromJson APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
SasinduDilshara committed Nov 18, 2024
1 parent 34b5e12 commit ba93e9b
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 41 deletions.
26 changes: 26 additions & 0 deletions ballerina/tests/test_from_json.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ballerina/test;

@test:Config {groups: ["xsd", "to_xml"], dataProvider: fromJsonDataProvider}
function testFromJson(json value, xml expected) returns error?{
xml|Error xmlResult = fromJson(value);
test:assertEquals(xmlResult, expected);
}

function fromJsonDataProvider() returns [json, xml][] {
return [
[{a: {b: 2, c: 3}}, xml `<a><b>2</b><c>3</c></a>`],
[{a: {a: 1}}, xml `<a><a>1</a></a>`],
[{a: {d: 4, e: {f: 5, g: "text"}}}, xml `<a><d>4</d><e><f>5</f><g>text</g></e></a>`],
[{root: {nested: {value1: "example", value2: 10}}}, xml `<root><nested><value1>example</value1><value2>10</value2></nested></root>`],
[{book: {title: "XML Guide", author: "John Doe", year: 2024}}, xml `<book><title>XML Guide</title><author>John Doe</author><year>2024</year></book>`],
[{library: {section: {book1: "Book A", book2: "Book B"}}}, xml `<library><section><book1>Book A</book1><book2>Book B</book2></section></library>`],
[{person: {name: "Alice", details: {age: 30, city: "Wonderland"}}}, xml `<person><name>Alice</name><details><age>30</age><city>Wonderland</city></details></person>`],
[{catalog: {item: [{id: 1, name: "Item 1"}, {id: 2, name: "Item 2"}]}}, xml `<catalog><item><id>1</id><name>Item 1</name></item><item><id>2</id><name>Item 2</name></item></catalog>`],
[{company: {employee: {id: 1001, name: "Bob", department: "Engineering"}}}, xml `<company><employee><id>1001</id><name>Bob</name><department>Engineering</department></employee></company>`],
[{'order: {orderId: 5001, items: {item1: "Widget", item2: "Gadget"}}}, xml `<order><orderId>5001</orderId><items><item1>Widget</item1><item2>Gadget</item2></items></order>`],
[{menu: {dish: [{name: "Pasta", price: 12.5}, {name: "Salad", price: 8.0}]}}, xml `<menu><dish><name>Pasta</name><price>12.5</price></dish><dish><name>Salad</name><price>8.0</price></dish></menu>`],
[{report: {entries: [{date: "2024-10-01", detail: "Entry 1"}, {date: "2024-10-02", detail: "Entry 2"}]}}, xml `<report><entries><date>2024-10-01</date><detail>Entry 1</detail></entries><entries><date>2024-10-02</date><detail>Entry 2</detail></entries></report>`],
[{shoppingList: {items: [{item: "Apples", quantity: 5}, {item: "Bananas", quantity: 3}]}}, xml `<shoppingList><items><item>Apples</item><quantity>5</quantity></items><items><item>Bananas</item><quantity>3</quantity></items></shoppingList>`],
[{conference: {session: [{topic: "AI Trends", speaker: "Dr. Smith"}, {topic: "Web 3.0", speaker: "Jane Doe"}]}}, xml `<conference><session><topic>AI Trends</topic><speaker>Dr. Smith</speaker></session><session><topic>Web 3.0</topic><speaker>Jane Doe</speaker></session></conference>`]
];
}
18 changes: 18 additions & 0 deletions ballerina/tests/xsd_choice_test_with_parse_type.bal
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,36 @@ function testXsdChoiceWithXmlValue() returns error? {
v = parseAsType(xmlValue);
test:assertEquals(v, {choice_XSDChoiceWithXmlValueRecord: {age: 10}});
test:assertEquals(toXml(check v), xmlValue);
Error? e = validate(XSDChoiceWithXmlValueRecord, xmlValue);
test:assertEquals(e, ());

xmlValue = xml `<Root><salary>10.5</salary></Root>`;
v = parseAsType(xmlValue);
test:assertEquals(v, {choice_XSDChoiceWithXmlValueRecord: {salary: 10.5}});
test:assertEquals(toXml(check v), xmlValue);
e = validate(XSDChoiceWithXmlValueRecord, xmlValue);
test:assertEquals(e, ());

xmlValue = xml `<Root><age>10</age><salary>11.1</salary></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "'choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times");
e = validate(XSDChoiceWithXmlValueRecord, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times'");

xmlValue = xml `<Root><salary>11.1</salary><salary>11.1</salary></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "'choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times");
e = validate(XSDChoiceWithXmlValueRecord, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord' occurs more than the max allowed times'");

xmlValue = xml `<Root></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "'choice_XSDChoiceWithXmlValueRecord' occurs less than the min required times");
e = validate(XSDChoiceWithXmlValueRecord, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord' occurs less than the min required times'");
}

@Name {
Expand Down Expand Up @@ -585,19 +595,27 @@ function testXsdChoiceWithXmlValue10() returns error? {
XSDChoiceWithXmlValueRecord10|Error v2 = parseAsType(xmlValue);
test:assertEquals(v2, <XSDChoiceWithXmlValueRecord10>{choice_XSDChoiceWithXmlValueRecord10_1: {field1: {value1: {a: "1"}}}, choice_XSDChoiceWithXmlValueRecord10_2: {field5: {value2: {"d": "2"}}}});
test:assertEquals(toXml(check v2), xmlValue);
Error? e = validate(XSDChoiceWithXmlValueRecord10, xmlValue);
test:assertEquals(e, ());

xmlValue = xml `<Root><field1><a>1</a></field1><field2><d>1</d></field2><field5><d>2</d></field5></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "'choice_XSDChoiceWithXmlValueRecord10_1' occurs more than the max allowed times");
e = validate(XSDChoiceWithXmlValueRecord10, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord10_1' occurs more than the max allowed times'");

xmlValue = xml `<Root><field1><a>1</a></field1><field5><d>2</d></field5><field6><h>2</h></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "'choice_XSDChoiceWithXmlValueRecord10_2' occurs more than the max allowed times");
e = validate(XSDChoiceWithXmlValueRecord10, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''choice_XSDChoiceWithXmlValueRecord10_2' occurs more than the max allowed times'");

xmlValue = xml `<Root><field2><d>1</d><e>1</e></field2><field5><d>2</d></field5></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "'value2' occurs more than the max allowed times");
e = validate(XSDChoiceWithXmlValueRecord10, xmlValue);
test:assertEquals((<Error>e).message(), "Invalid XML found: ''value2' occurs more than the max allowed times'");
}
33 changes: 33 additions & 0 deletions ballerina/tests/xsd_sequence_tests_with_parse_type.bal
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,40 @@ function testXsdSequenceWithXmlValue() returns error? {
test:assertEquals((check v).seq_XSDSequenceRecordWithXmlValue.age, 13);
test:assertEquals((check v).seq_XSDSequenceRecordWithXmlValue.salary, 11.1);
test:assertEquals(toXml(check v), xmlValue);
Error? e = validate(XSDSequenceRecordWithXmlValue, xmlValue);
test:assertTrue(e is ());

xmlValue = xml `<Root><salary>11.1</salary></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "Element 'salary' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue'");
e = validate(XSDSequenceRecordWithXmlValue, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error> e).message(), "Invalid XML found: 'Element 'salary' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue''");

xmlValue = xml `<Root><age>13</age></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "Element(s) 'salary' is not found in 'seq_XSDSequenceRecordWithXmlValue'");
e = validate(XSDSequenceRecordWithXmlValue, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error> e).message(), "Invalid XML found: 'Element(s) 'salary' is not found in 'seq_XSDSequenceRecordWithXmlValue''");

xmlValue = xml `<Root></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), ("required field 'seq_XSDSequenceRecordWithXmlValue' not present in XML"), msg = (<Error>v).message());
e = validate(XSDSequenceRecordWithXmlValue, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error> e).message(), "Invalid XML found: 'required field 'seq_XSDSequenceRecordWithXmlValue' not present in XML'");

xmlValue = xml `<Root><salary>11.1</salary><age>13</age></Root>`;
v = parseAsType(xmlValue);
test:assertTrue(v is Error);
test:assertEquals((<Error>v).message(), "Element 'salary' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue'");
e = validate(XSDSequenceRecordWithXmlValue, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error> e).message(), "Invalid XML found: 'Element 'salary' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue''");
}

@Name {
Expand Down Expand Up @@ -979,34 +993,53 @@ function testXsdSequenceWithXmlValue13() returns error? {
XSDSequenceRecordWithXmlValue13|Error v2 = parseAsType(xmlValue);
test:assertEquals(v2, <XSDSequenceRecordWithXmlValue13>{seq_XSDSequenceRecordWithXmlValue13_1: {field1: {value1: {a: "1", b: "2", c: "3"}}, field2: {value2: {d: "1", e: "2", f: "3"}}, field3: {value3: {g: "1", h: "2", i: "3"}}}, seq_XSDSequenceRecordWithXmlValue13_2: {field4: {value1: {a: "1", b: "2", c: "3"}}, field5: {value2: {d: "1", e: "2", f: "3"}}, field6: {value3: {g: "1", h: "2", i: "3"}}}});
test:assertEquals(toXml(check v2), xml `<Root><field1><a>1</a><b>2</b><c>3</c></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><field6><g>1</g><h>2</h><i>3</i></field6></Root>`);
Error? e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is ());

xmlValue = xml `<Root><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><field6><g>1</g><h>2</h><i>3</i></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertEquals(v2, <XSDSequenceRecordWithXmlValue13>{seq_XSDSequenceRecordWithXmlValue13_2: {field4: {value1: {a: "1", b: "2", c: "3"}}, field5: {value2: {d: "1", e: "2", f: "3"}}, field6: {value3: {g: "1", h: "2", i: "3"}}}});
test:assertEquals(toXml(check v2), xml `<Root><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><field6><g>1</g><h>2</h><i>3</i></field6></Root>`);
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is ());

xmlValue = xml `<Root><field1><a>1</a><b>2</b><c>3</c></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><g>1</g><h>2</h><i>3</i><field6><g>1</g><h>2</h><i>3</i></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "Element(s) 'field6' is not found in 'seq_XSDSequenceRecordWithXmlValue13_2'");
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error>e).message(), "Invalid XML found: 'Element(s) 'field6' is not found in 'seq_XSDSequenceRecordWithXmlValue13_2''");

xmlValue = xml `<Root><field1><a>1</a><b>2</b><c>3</c></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><g>1</g><h>2</h><i>3</i><f>3</f></field5><field6><g>1</g><h>2</h><i>3</i></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "Element(s) 'f' is not found in 'value2'");
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error>e).message(), "Invalid XML found: 'Element(s) 'f' is not found in 'value2''");

xmlValue = xml `<Root><field1><a>1</a><b>2</b><c>3</c></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><field6><g>1</g><i>3</i><h>2</h></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "Element 'i' is not in the correct order in 'value3'");
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error>e).message(), "Invalid XML found: 'Element 'i' is not in the correct order in 'value3''");

xmlValue = xml `<Root><field1><a>1</a><c>3</c><b>2</b></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field4><a>1</a><b>2</b><c>3</c></field4><field5><d>1</d><e>2</e><f>3</f></field5><field6><g>1</g><h>2</h><i>3</i></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), "Element 'c' is not in the correct order in 'value1'");
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error>e).message(), "Invalid XML found: 'Element 'c' is not in the correct order in 'value1''");

xmlValue = xml `<Root><field1><a>1</a><b>2</b><c>3</c></field1><field2><d>1</d><e>2</e><f>3</f></field2><field3><g>1</g><h>2</h><i>3</i></field3><field5><d>1</d><e>2</e><f>3</f></field5><field4><a>1</a><b>2</b><c>3</c></field4><field6><g>1</g><h>2</h><i>3</i></field6></Root>`;
v2 = parseAsType(xmlValue);
test:assertTrue(v2 is Error);
test:assertEquals((<Error>v2).message(), ("Element 'field5' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue13_2'"), msg = (<Error>v2).message());
e = validate(XSDSequenceRecordWithXmlValue13, xmlValue);
test:assertTrue(e is Error);
test:assertEquals((<Error>e).message(), "Invalid XML found: 'Element 'field5' is not in the correct order in 'seq_XSDSequenceRecordWithXmlValue13_2''");
}
45 changes: 25 additions & 20 deletions ballerina/tests/xsd_validation_with_file_path_tests.bal
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ function testValidateSchema1() returns error? {
xml validXml = check readXmlFile(validXmlPath);
xml invalidXml = check readXmlFile(invalidXmlPath);

boolean isValid = validate(xsdPath, validXml);
test:assertTrue(isValid, msg = "Valid XML should pass validation");
Error? e = validate(xsdPath, validXml);
test:assertTrue(e is (), msg = "Valid XML should pass validation");

boolean isInvalid = validate(xsdPath, invalidXml);
test:assertFalse(isInvalid, msg = "Invalid XML should fail validation");
e = validate(xsdPath, invalidXml);
test:assertTrue(e is Error, msg = "Invalid XML should fail validation");
test:assertTrue((<Error>e).message().includes("Invalid XML found"), msg = "Invalid XML should fail validation");
}

@test:Config {groups: ["xsd"]}
Expand All @@ -46,11 +47,12 @@ function testValidateSchema2() returns error? {
xml validXml = check readXmlFile(validXmlPath);
xml invalidXml = check readXmlFile(invalidXmlPath);

boolean isValid = validate(xsdPath, validXml);
test:assertTrue(isValid, msg = "Valid XML should pass validation");
Error? e = validate(xsdPath, validXml);
test:assertTrue(e is (), msg = "Valid XML should pass validation");

boolean isInvalid = validate(xsdPath, invalidXml);
test:assertFalse(isInvalid, msg = "Invalid XML should fail validation");
e = validate(xsdPath, invalidXml);
test:assertTrue(e is Error, msg = "Invalid XML should fail validation");
test:assertTrue((<Error>e).message().includes("Invalid XML found"), msg = "Invalid XML should fail validation");
}

@test:Config {groups: ["xsd"]}
Expand All @@ -62,11 +64,12 @@ function testValidateSchema3() returns error? {
xml validXml = check readXmlFile(validXmlPath);
xml invalidXml = check readXmlFile(invalidXmlPath);

boolean isValid = validate(xsdPath, validXml);
test:assertTrue(isValid, msg = "Valid XML should pass validation");
Error? e = validate(xsdPath, validXml);
test:assertTrue(e is (), msg = "Valid XML should pass validation");

boolean isInvalid = validate(xsdPath, invalidXml);
test:assertFalse(isInvalid, msg = "Invalid XML should fail validation");
e = validate(xsdPath, invalidXml);
test:assertTrue(e is Error, msg = "Invalid XML should fail validation");
test:assertTrue((<Error>e).message().includes("Invalid XML found"), msg = "Invalid XML should fail validation");
}

@test:Config {groups: ["xsd"]}
Expand All @@ -78,11 +81,12 @@ function testValidateSchema4() returns error? {
xml validXml = check readXmlFile(validXmlPath);
xml invalidXml = check readXmlFile(invalidXmlPath);

boolean isValid = validate(xsdPath, validXml);
test:assertTrue(isValid, msg = "Valid XML should pass validation");
Error? e = validate(xsdPath, validXml);
test:assertTrue(e is (), msg = "Valid XML should pass validation");

boolean isInvalid = validate(xsdPath, invalidXml);
test:assertFalse(isInvalid, msg = "Invalid XML should fail validation");
e = validate(xsdPath, invalidXml);
test:assertTrue(e is Error, msg = "Invalid XML should fail validation");
test:assertTrue((<Error>e).message().includes("Invalid XML found"), msg = "Invalid XML should fail validation");
}

@test:Config {groups: ["xsd"]}
Expand All @@ -94,9 +98,10 @@ function testValidateSchema5() returns error? {
xml validXml = check readXmlFile(validXmlPath);
xml invalidXml = check readXmlFile(invalidXmlPath);

boolean isValid = validate(xsdPath, validXml);
test:assertTrue(isValid, msg = "Valid XML should pass validation");
Error? e = validate(xsdPath, validXml);
test:assertTrue(e is (), msg = "Valid XML should pass validation");

boolean isInvalid = validate(xsdPath, invalidXml);
test:assertFalse(isInvalid, msg = "Invalid XML should fail validation");
e = validate(xsdPath, invalidXml);
test:assertTrue(e is Error, msg = "Invalid XML should fail validation");
test:assertTrue((<Error>e).message().includes("Invalid XML found"), msg = "Invalid XML should fail validation");
}
8 changes: 4 additions & 4 deletions ballerina/xml_api.bal
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ isolated function addNamespaces(map<string> allNamespaces, map<string> namespace
#
# + schema - A `string` representing the XSD content or a Ballerina record type representing the XSD.
# + xmlValue - The XML document that needs to be validated against the schema.
# + return - Returns `true` if the XML is valid according to the schema, otherwise returns `false`.
# + return - Returns `()` if the XML is valid according to the schema, otherwise returns `Error`.
#
# # Examples
#
Expand All @@ -478,14 +478,14 @@ isolated function addNamespaces(map<string> allNamespaces, map<string> namespace
# <xs:element name="Book" type="xs:string"/>
# </xs:schema>`;
# xml bookXml = xml `<Book>Sample</Book>`;
# boolean isValid = validate(xsdContent, bookXml);
# Error? isValid = validate(xsdContent, bookXml);
#
# // Using Ballerina record to represent XSD
# type xsdRecord record {string name;};
# boolean isValid = validate(xsdRecord, bookXml);
# Error? isValid = validate(xsdRecord, bookXml);
# ```
public function validate(string|typedesc<record{}> schema, xml xmlValue)
returns boolean = @java:Method {'class: "io.ballerina.lib.data.xmldata.xml.Native"} external;
returns Error? = @java:Method {'class: "io.ballerina.lib.data.xmldata.xml.Native"} external;

public isolated function fromRecordToXml(json jsonValue, JsonOptions options, typedesc<anydata> inputType) returns xml|Error
= @java:Method {'class: "io.ballerina.lib.data.xmldata.utils.ToXmlUtils"} external;
Loading

0 comments on commit ba93e9b

Please sign in to comment.