Skip to content

Commit

Permalink
Add test cases for TDML display data extraction
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-hoke committed Nov 13, 2023
1 parent 3812cb2 commit 99eafa3
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 32 deletions.
78 changes: 63 additions & 15 deletions src/tdmlEditor/src/utilities/tdmlXmlUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,33 @@

import { readFileSync } from 'fs'
import os from 'os'
import { XmlElement, parseXml } from '@rgrove/parse-xml'
import { join } from 'path'
import { XmlDocument, XmlElement, parseXml } from '@rgrove/parse-xml'

/*
* Note that the functions in this file assumes the structure of a TDML file
* and is not tied directly to the schema or JAXB bindings.
* A valid TDML file contains at least 0 documents and/or infosets. Any TDML files
* created by the extension will have one of each. However, we should be able to
* interact with a wide variety of files
* We are also assuming that namespace prefixes may be present. We can't know which
* prefix is correct so we can't do an exact match. We should also be able to handle
* a TDML file that does not use namespace prefixes.
* *******************************************************************************
* The general expected format is as follows:
* <testSuite suiteName=''>
* <parserTestCase name='' model='' description=''>
* <document>
* <documentPart></documentPart>
* </document>
* <infoset>
* <infosetPart></infosetPart>
* </infoset>
* </parserTestCase>
* </testSuite>
*/

// Custom type that contains information on a test case
type TDMLTestCaseDisplay = {
testCaseName: string
testCaseDescription: string
Expand All @@ -27,11 +52,14 @@ type TDMLTestCaseDisplay = {
dfdlInfosets: string[]
}

// Custom type that contains information on a test suite
// Each item in the array represents a single test case
type TDMLTestSuiteDisplay = {
suiteName: string
testCases: TDMLTestCaseDisplay[]
}

// Hard coded element/attribute names expected in the XML
const testSuiteAttribute = 'suiteName'
const testCaseNameAttribute = 'name'
const testCaseDescriptionAttribute = 'description'
Expand All @@ -42,12 +70,18 @@ const documentPartElement = 'documentPart'
const infosetElement = 'infoset'
const dfdlInfosetElement = 'dfdlInfoset'

// When a TDML file is generated on a DFDL parse, it is generated at this location
export async function getTmpTDMLFilePath() {
// '/' is recognized as a valid separator on all operating systems.
const tmpTDMLFileName: String = 'generatedTDML.tdml' as const
return os.tmpdir() + '/' + tmpTDMLFileName
const tmpTDMLFileName: string = 'generatedTDML.tdml' as const
return join(os.tmpdir(), tmpTDMLFileName)
}

/*
* Read the XML contents of a TDML file
*
* tdmlFilePath: File path to a TDML file
* returns XML contents of given TDML file
*/
export async function readTDMLFileContents(tdmlFilePath: string) {
try {
return readFileSync(tdmlFilePath, 'utf8')
Expand All @@ -56,11 +90,23 @@ export async function readTDMLFileContents(tdmlFilePath: string) {
return ''
}
}

/*
* Get the test case data from a TDML file.
* The data is returned in custom types.
*/
export async function getTestCaseDisplayData(
xmlBuffer: string
): Promise<TDMLTestSuiteDisplay> {
const xmlDoc = parseXml(xmlBuffer)
var xmlDoc: XmlDocument
try {
xmlDoc = parseXml(xmlBuffer)
} catch (error) {
return {
suiteName: '',
testCases: [],
}
}

const rootNode = xmlDoc.root
if (!rootNode) {
return {
Expand All @@ -70,26 +116,26 @@ export async function getTestCaseDisplayData(
}
const retVal: TDMLTestCaseDisplay[] = []

// Each TDML file contains at least one test case
const testCases = rootNode.children.filter(
(node): node is XmlElement =>
(node as XmlElement).name?.endsWith(`:${testCaseElement}`)
(node as XmlElement).name?.endsWith(testCaseElement)
)

// Each test case may contain any number of documents
const documentParts: string[][] = []
testCases.forEach((testCaseNode) => {
const documentsGrouped: string[] = []
testCaseNode.children
.filter(
(childNode): childNode is XmlElement =>
(childNode as XmlElement).name?.endsWith(`:${documentElement}`)
(childNode as XmlElement).name?.endsWith(documentElement)
)
.forEach((documentNode) =>
documentNode.children
.filter(
(childNode): childNode is XmlElement =>
(childNode as XmlElement).name?.endsWith(
`:${documentPartElement}`
)
(childNode as XmlElement).name?.endsWith(documentPartElement)
)
.forEach((documentPartNode) =>
documentsGrouped.push(documentPartNode.text)
Expand All @@ -98,19 +144,20 @@ export async function getTestCaseDisplayData(
documentParts.push(documentsGrouped)
})

// Each test case may contain any number of infosets
const infosetParts: string[][] = []
testCases.forEach((testCaseNode) => {
const infosetsGrouped: string[] = []
testCaseNode.children
.filter(
(childNode): childNode is XmlElement =>
(childNode as XmlElement).name?.endsWith(`:${infosetElement}`)
(childNode as XmlElement).name?.endsWith(infosetElement)
)
.forEach((infosetNode) =>
infosetNode.children
.filter(
(childNode): childNode is XmlElement =>
(childNode as XmlElement).name?.endsWith(`:${dfdlInfosetElement}`)
(childNode as XmlElement).name?.endsWith(dfdlInfosetElement)
)
.forEach((dfdlInfosetNode) =>
infosetsGrouped.push(dfdlInfosetNode.text)
Expand All @@ -119,14 +166,15 @@ export async function getTestCaseDisplayData(
infosetParts.push(infosetsGrouped)
})

// Combine the extracted data info the custom types for returning
testCases.forEach((testCaseNode, index) =>
retVal.push({
testCaseName: testCaseNode.attributes[testCaseNameAttribute],
testCaseDescription:
testCaseNode.attributes[testCaseDescriptionAttribute],
testCaseModel: testCaseNode.attributes[testCaseModelAttribute],
dataDocuments: documentParts[index].map((node) => node),
dfdlInfosets: infosetParts[index].map((node) => node),
dataDocuments: documentParts[index],
dfdlInfosets: infosetParts[index],
})
)

Expand Down
35 changes: 35 additions & 0 deletions src/tests/data/test-multiple.tdml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ns1:testSuite xmlns:ns1="http://www.ibm.com/xmlns/dfdl/testData" xmlns:ns2="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:ns3="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ns4="http://www.ogf.org/dfdl/dfdl-1.0/extensions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns6="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:int" suiteName="TestTDMLSuiteNameMultiple" defaultRoundTrip="onePass">
<ns1:parserTestCase name="FirstTDMLTestCase" root="file" model="test1.dfdl.xsd" roundTrip="onePass" description="First TDML Description">
<ns1:document>
<ns1:documentPart type="file">noData1.xml</ns1:documentPart>
</ns1:document>
<ns1:infoset>
<ns1:dfdlInfoset type="file">noInfoset1.xml</ns1:dfdlInfoset>
</ns1:infoset>
</ns1:parserTestCase>
<ns1:parserTestCase name="SecondTDMLTestCase" root="file" model="test2.dfdl.xsd" roundTrip="onePass" description="Second TDML Description">
<ns1:document>
<ns1:documentPart type="file">noData2.xml</ns1:documentPart>
</ns1:document>
<ns1:infoset>
<ns1:dfdlInfoset type="file">noInfoset2.xml</ns1:dfdlInfoset>
</ns1:infoset>
</ns1:parserTestCase>
</ns1:testSuite>
22 changes: 22 additions & 0 deletions src/tests/data/test-no-document-or-infoset.tdml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ns1:testSuite xmlns:ns1="http://www.ibm.com/xmlns/dfdl/testData" xmlns:ns2="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:ns3="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ns4="http://www.ogf.org/dfdl/dfdl-1.0/extensions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns6="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:int" suiteName="TestTDMLSuiteName" defaultRoundTrip="onePass">
<ns1:parserTestCase name="TestTDMLName" root="file" model="test.dfdl.xsd" roundTrip="onePass" description="Test TDML Description">
<dummyElement />
</ns1:parserTestCase>
</ns1:testSuite>
27 changes: 27 additions & 0 deletions src/tests/data/test-no-namespace.tdml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<testSuite suiteName="TestTDMLSuiteName" defaultRoundTrip="onePass">
<parserTestCase name="TestTDMLName" root="file" model="test.dfdl.xsd" roundTrip="onePass" description="Test TDML Description">
<document>
<documentPart type="file">noData.xml</documentPart>
</document>
<infoset>
<dfdlInfoset type="file">noInfoset.xml</dfdlInfoset>
</infoset>
</parserTestCase>
</testSuite>
2 changes: 1 addition & 1 deletion src/tests/data/test.tdml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<ns1:testSuite xmlns:ns1="http://www.ibm.com/xmlns/dfdl/testData" xmlns:ns2="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:ns3="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ns4="http://www.ogf.org/dfdl/dfdl-1.0/extensions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns6="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:int" suiteName="TestTDMLName" defaultRoundTrip="onePass">
<ns1:testSuite xmlns:ns1="http://www.ibm.com/xmlns/dfdl/testData" xmlns:ns2="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:ns3="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:ns4="http://www.ogf.org/dfdl/dfdl-1.0/extensions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns6="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:int" suiteName="TestTDMLSuiteName" defaultRoundTrip="onePass">
<ns1:parserTestCase name="TestTDMLName" root="file" model="test.dfdl.xsd" roundTrip="onePass" description="Test TDML Description">
<ns1:document>
<ns1:documentPart type="file">noData.xml</ns1:documentPart>
Expand Down
Loading

0 comments on commit 99eafa3

Please sign in to comment.