Added new test framework
git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization@764 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-app/pom.xml b/asterix-app/pom.xml
index 75ec501..fe62ae9 100644
--- a/asterix-app/pom.xml
+++ b/asterix-app/pom.xml
@@ -214,6 +214,12 @@
<artifactId>cobertura</artifactId>
<version>1.9.4</version>
</dependency>
+ <dependency>
+ <groupId>edu.uci.ics.asterix</groupId>
+ <artifactId>asterix-test-framework</artifactId>
+ <version>0.0.4-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/asterix-app/src/test/resources/runtimets/queries/ifthenelse_01.aql b/asterix-app/src/test/resources/runtimets/queries/ifthenelse_01.aql
deleted file mode 100644
index 1da06a7..0000000
--- a/asterix-app/src/test/resources/runtimets/queries/ifthenelse_01.aql
+++ /dev/null
@@ -1,8 +0,0 @@
-use dataverse test;
-
-write output to nc1:"rttest/ifthenelse_01.adm";
-
-if (2>1) then
- 20
-else
- 10
diff --git a/asterix-app/src/test/resources/runtimets/queries/float_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/float_01.aql
similarity index 72%
rename from asterix-app/src/test/resources/runtimets/queries/float_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/float_01.aql
index dea3790..ec0e8e5 100644
--- a/asterix-app/src/test/resources/runtimets/queries/float_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/float_01.aql
@@ -2,7 +2,7 @@
create dataverse test;
use dataverse test;
-write output to nc1:"rttest/float_01.adm";
+write output to nc1:"rttest/misc_float_01.adm";
for $f in [1f, 1F, 1.1f, 1.1F, .1f, .1F]
return $f
diff --git a/asterix-app/src/test/resources/runtimets/queries/groupby-orderby-count.aql b/asterix-app/src/test/resources/runtimets/queries/misc/groupby-orderby-count.aql
similarity index 90%
rename from asterix-app/src/test/resources/runtimets/queries/groupby-orderby-count.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/groupby-orderby-count.aql
index ce4662d..e5887ae 100644
--- a/asterix-app/src/test/resources/runtimets/queries/groupby-orderby-count.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/groupby-orderby-count.aql
@@ -13,7 +13,7 @@
using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
(("path"="nc1://data/twitter/extrasmalltweets.txt"),("format"="adm"));
-write output to nc1:"rttest/groupby-orderby-count.adm";
+write output to nc1:"rttest/misc_groupby-orderby-count.adm";
for $t in dataset('TwitterData')
let $tokens := word-tokens($t.text)
diff --git a/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_01.aql
new file mode 100644
index 0000000..a65e675
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/ifthenelse_01.aql
@@ -0,0 +1,8 @@
+use dataverse test;
+
+write output to nc1:"rttest/misc_ifthenelse_01.adm";
+
+if (2>1) then
+ 20
+else
+ 10
diff --git a/asterix-app/src/test/resources/runtimets/queries/is-null_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/is-null_01.aql
similarity index 67%
rename from asterix-app/src/test/resources/runtimets/queries/is-null_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/is-null_01.aql
index ca6ac7a..9005392 100644
--- a/asterix-app/src/test/resources/runtimets/queries/is-null_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/is-null_01.aql
@@ -3,6 +3,6 @@
use dataverse test;
-write output to nc1:"rttest/is-null_01.adm";
+write output to nc1:"rttest/misc_is-null_01.adm";
-[is-null(null), is-null(10)]
\ No newline at end of file
+[is-null(null), is-null(10)]
diff --git a/asterix-app/src/test/resources/runtimets/queries/nested-loop-join_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/nested-loop-join_01.aql
similarity index 94%
rename from asterix-app/src/test/resources/runtimets/queries/nested-loop-join_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/nested-loop-join_01.aql
index 79b3a9f..f148d2e 100644
--- a/asterix-app/src/test/resources/runtimets/queries/nested-loop-join_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/nested-loop-join_01.aql
@@ -28,7 +28,7 @@
using "edu.uci.ics.asterix.external.dataset.adapter.NCFileSystemAdapter"
(("path"="nc1://data/users-visitors-small/visitors.json"),("format"="adm"));
-write output to nc1:'rttest/nested-loop-join_01.adm';
+write output to nc1:'rttest/misc_nested-loop-join_01.adm';
for $user in dataset('Users')
for $visitor in dataset('Visitors')
diff --git a/asterix-app/src/test/resources/runtimets/queries/range_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/range_01.aql
similarity index 65%
rename from asterix-app/src/test/resources/runtimets/queries/range_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/range_01.aql
index 0f38113..9c5991d 100644
--- a/asterix-app/src/test/resources/runtimets/queries/range_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/range_01.aql
@@ -1,7 +1,7 @@
drop dataverse test if exists;
create dataverse test;
-write output to nc1:"rttest/range_01.adm";
+write output to nc1:"rttest/misc_range_01.adm";
for $x in range(20,30)
return $x
diff --git a/asterix-app/src/test/resources/runtimets/queries/tid_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/tid_01.aql
similarity index 67%
rename from asterix-app/src/test/resources/runtimets/queries/tid_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/tid_01.aql
index 3cd8396..ff216ea 100644
--- a/asterix-app/src/test/resources/runtimets/queries/tid_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/tid_01.aql
@@ -1,7 +1,7 @@
drop dataverse test if exists;
create dataverse test;
-write output to nc1:"rttest/tid_01.adm";
+write output to nc1:"rttest/misc_tid_01.adm";
for $x at $i in ["a","b","c"]
return $i
diff --git a/asterix-app/src/test/resources/runtimets/queries/year_01.aql b/asterix-app/src/test/resources/runtimets/queries/misc/year_01.aql
similarity index 61%
rename from asterix-app/src/test/resources/runtimets/queries/year_01.aql
rename to asterix-app/src/test/resources/runtimets/queries/misc/year_01.aql
index da93e96..f431a52 100644
--- a/asterix-app/src/test/resources/runtimets/queries/year_01.aql
+++ b/asterix-app/src/test/resources/runtimets/queries/misc/year_01.aql
@@ -1,6 +1,6 @@
drop dataverse test if exists;
create dataverse test;
-write output to nc1:"rttest/year_01.adm";
+write output to nc1:"rttest/misc_year_01.adm";
year("1996-12-01")
diff --git a/asterix-app/src/test/resources/runtimets/results/float_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/float_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/float_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/float_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/groupby-orderby-count.adm b/asterix-app/src/test/resources/runtimets/results/misc/groupby-orderby-count.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/groupby-orderby-count.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/groupby-orderby-count.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/ifthenelse_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/ifthenelse_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/ifthenelse_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/is-null_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/is-null_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/is-null_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/is-null_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/nested-loop-join_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/nested-loop-join_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/nested-loop-join_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/nested-loop-join_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/range_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/range_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/range_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/range_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/tid_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/tid_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/tid_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/tid_01.adm
diff --git a/asterix-app/src/test/resources/runtimets/results/year_01.adm b/asterix-app/src/test/resources/runtimets/results/misc/year_01.adm
similarity index 100%
rename from asterix-app/src/test/resources/runtimets/results/year_01.adm
rename to asterix-app/src/test/resources/runtimets/results/misc/year_01.adm
diff --git a/asterix-test-framework/pom.xml b/asterix-test-framework/pom.xml
new file mode 100755
index 0000000..2f0142e
--- /dev/null
+++ b/asterix-test-framework/pom.xml
@@ -0,0 +1,36 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>asterix</artifactId>
+ <groupId>edu.uci.ics.asterix</groupId>
+ <version>0.0.4-SNAPSHOT</version>
+ </parent>
+ <artifactId>asterix-test-framework</artifactId>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.0.2</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ </dependencies>
+</project>
diff --git a/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/context/TestCaseContext.java b/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/context/TestCaseContext.java
new file mode 100644
index 0000000..d5164db
--- /dev/null
+++ b/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/context/TestCaseContext.java
@@ -0,0 +1,103 @@
+package edu.uci.ics.asterix.testframework.context;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.testframework.xml.TestCase;
+import edu.uci.ics.asterix.testframework.xml.TestCase.CompilationUnit;
+import edu.uci.ics.asterix.testframework.xml.TestGroup;
+import edu.uci.ics.asterix.testframework.xml.TestSuite;
+import edu.uci.ics.asterix.testframework.xml.TestSuiteParser;
+
+public class TestCaseContext {
+ public static final String DEFAULT_TESTSUITE_XML_NAME = "testsuite.xml";
+
+ private File tsRoot;
+
+ private TestSuite testSuite;
+
+ private TestGroup[] testGroups;
+
+ private TestCase testCase;
+
+ public TestCaseContext(File tsRoot, TestSuite testSuite, TestGroup[] testGroups, TestCase testCase) {
+ this.tsRoot = tsRoot;
+ this.testSuite = testSuite;
+ this.testGroups = testGroups;
+ this.testCase = testCase;
+ }
+
+ public File getTsRoot() {
+ return tsRoot;
+ }
+
+ public TestSuite getTestSuite() {
+ return testSuite;
+ }
+
+ public TestGroup[] getTestGroups() {
+ return testGroups;
+ }
+
+ public TestCase getTestCase() {
+ return testCase;
+ }
+
+ public File getTestFile(CompilationUnit cUnit) {
+ File path = tsRoot;
+ path = new File(path, testSuite.getQueryOffsetPath());
+ path = new File(path, testCase.getFilePath());
+ return new File(path, cUnit.getName() + testSuite.getQueryFileExtension());
+ }
+
+ public File getExpectedResultFile(CompilationUnit cUnit) {
+ File path = tsRoot;
+ path = new File(path, testSuite.getResultOffsetPath());
+ path = new File(path, testCase.getFilePath());
+ return new File(path, cUnit.getOutputFile().getValue());
+ }
+
+ public File getActualResultFile(CompilationUnit cUnit, File actualResultsBase) {
+ File path = actualResultsBase;
+ path = new File(path, testSuite.getResultOffsetPath());
+ path = new File(path, testCase.getFilePath());
+ return new File(path, cUnit.getOutputFile().getValue());
+ }
+
+ public static class Builder {
+ public Builder() {
+ }
+
+ public List<TestCaseContext> build(File tsRoot) throws Exception {
+ return build(tsRoot, DEFAULT_TESTSUITE_XML_NAME);
+ }
+
+ public List<TestCaseContext> build(File tsRoot, String tsXMLFilePath) throws Exception {
+ File tsFile = new File(tsRoot, tsXMLFilePath);
+ TestSuiteParser tsp = new TestSuiteParser();
+ TestSuite ts = tsp.parse(tsFile);
+ List<TestCaseContext> tccs = new ArrayList<TestCaseContext>();
+ List<TestGroup> tgPath = new ArrayList<TestGroup>();
+ addContexts(tsRoot, ts, tgPath, ts.getTestGroup(), tccs);
+ return tccs;
+ }
+
+ private void addContexts(File tsRoot, TestSuite ts, List<TestGroup> tgPath, List<TestGroup> testGroups,
+ List<TestCaseContext> tccs) {
+ for (TestGroup tg : testGroups) {
+ tgPath.add(tg);
+ addContexts(tsRoot, ts, tgPath, tccs);
+ tgPath.remove(tgPath.size() - 1);
+ }
+ }
+
+ private void addContexts(File tsRoot, TestSuite ts, List<TestGroup> tgPath, List<TestCaseContext> tccs) {
+ TestGroup tg = tgPath.get(tgPath.size() - 1);
+ for (TestCase tc : tg.getTestCase()) {
+ tccs.add(new TestCaseContext(tsRoot, ts, tgPath.toArray(new TestGroup[tgPath.size()]), tc));
+ }
+ addContexts(tsRoot, ts, tgPath, tg.getTestGroup(), tccs);
+ }
+ }
+}
\ No newline at end of file
diff --git a/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/xml/TestSuiteParser.java b/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/xml/TestSuiteParser.java
new file mode 100644
index 0000000..0c544ac
--- /dev/null
+++ b/asterix-test-framework/src/main/java/edu/uci/ics/asterix/testframework/xml/TestSuiteParser.java
@@ -0,0 +1,15 @@
+package edu.uci.ics.asterix.testframework.xml;
+
+import java.io.File;
+
+import javax.xml.bind.JAXBContext;
+
+public class TestSuiteParser {
+ public TestSuiteParser() {
+ }
+
+ public TestSuite parse(File testSuiteCatalog) throws Exception {
+ JAXBContext ctx = JAXBContext.newInstance(TestSuite.class);
+ return (TestSuite) ctx.createUnmarshaller().unmarshal(testSuiteCatalog);
+ }
+}
\ No newline at end of file
diff --git a/asterix-test-framework/src/main/resources/Catalog.xsd b/asterix-test-framework/src/main/resources/Catalog.xsd
new file mode 100755
index 0000000..feadbd7
--- /dev/null
+++ b/asterix-test-framework/src/main/resources/Catalog.xsd
@@ -0,0 +1,210 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:test="urn:xml.testframework.asterix.ics.uci.edu"
+ targetNamespace="urn:xml.testframework.asterix.ics.uci.edu" elementFormDefault="qualified">
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- test-suite - top level element -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <xs:element name="test-suite">
+ <xs:annotation>
+ <xs:documentation>
+ This is the top level element for documents that use this schema.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="test:test-group" maxOccurs="unbounded"/>
+ </xs:sequence>
+
+ <xs:attribute name="CatalogDesignDate" type="xs:date" use="required"/>
+
+ <xs:attribute name="ResultOffsetPath" type="test:SimplifiedRelativeFilePath" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ offset from root to results
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <xs:attribute name="QueryOffsetPath" type="test:SimplifiedRelativeFilePath"
+ use="required">
+ <xs:annotation>
+ <xs:documentation>
+ offset from root to Query expression files
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ <!-- file extension for XQuery expression files -->
+ <xs:attribute name="QueryFileExtension" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ file extension for Query files
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+
+ </xs:complexType>
+
+ <xs:unique name="unique-test-group">
+ <xs:selector xpath=".//test:test-group"/>
+ <xs:field xpath="@name"/>
+ </xs:unique>
+
+ </xs:element>
+
+
+ <!-- SimplifiedRelativeFilePath type -->
+
+ <xs:simpleType name="SimplifiedRelativeFilePath">
+ <xs:restriction base="xs:anyURI">
+ <xs:pattern value="([a-zA-Z0-9\-\.]+/)+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- test-group -->
+ <!-- -->
+ <!-- Group of test cases and test groups. -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <xs:element name="test-group">
+ <xs:annotation>
+ <xs:documentation>
+ Group of test cases and test groups.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="test-case" type="test:test-case" minOccurs="0" maxOccurs="unbounded">
+ <xs:unique name="unique-expected-error">
+ <xs:selector xpath=".//test:expected-error"/>
+ <xs:field xpath="."/>
+ </xs:unique>
+ </xs:element>
+
+ <xs:element ref="test:test-group" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+
+
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+ <!-- test-case -->
+ <!-- -->
+ <!-- A test case to be run. -->
+ <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+ <xs:complexType name="test-case">
+ <xs:sequence>
+ <xs:element name="description" type="test:description"/>
+
+ <xs:element name="compilation-unit" minOccurs="1" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="description" type="test:description" minOccurs="0"/>
+ <xs:element name="output-file" minOccurs="0">
+ <xs:annotation>
+ <xs:documentation>
+ Zero or one file containing expected results for this query.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="compare" type="test:comparison-enum" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+
+ <!-- Zero or more expected errors for this query -->
+
+ <xs:element name="expected-error" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation>
+ <xs:documentation>
+ Zero or more expected errors for this query.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="test:ErrorCode">
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ </xs:sequence>
+
+ <!-- This name is always equal to the name of the test case -->
+ <xs:attribute name="name" type="xs:string" use="required"/>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Zero or more files containing expected results for this query -->
+
+ </xs:sequence>
+
+ <!-- The filename for this query can be constructed from: -->
+ <!-- the QueryOffsetPath -->
+ <!-- the FilePath -->
+ <!-- the name -->
+ <!-- the QueryFileExtension -->
+
+ <xs:attribute name="FilePath" type="test:SimplifiedRelativeFilePath" use="required"/>
+ <xs:attribute name="date" type="xs:date" use="required"/>
+ </xs:complexType>
+
+ <!-- comparison-enum type -->
+ <!-- Identify the type of comparison used to determine whether an -->
+ <!-- expected result and an actual result match. -->
+
+ <xs:simpleType name="comparison-enum">
+ <xs:annotation>
+ <xs:documentation>
+ Identify the type of comparison used to determine whether an
+ expected result and an actual result match.
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="XML"/>
+ <xs:enumeration value="Text"/>
+ <xs:enumeration value="Inspect"/>
+ <xs:enumeration value="Ignore"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <!-- description type -->
+
+ <xs:complexType name="description">
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="last-mod" type="xs:date"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+
+
+ <!-- ErrorCode type -->
+ <!-- * is used to mean that any error code is acceptable -->
+
+ <xs:simpleType name="ErrorCode">
+ <xs:annotation>
+ <xs:documentation>
+ * is used to mean that any error code is acceptable
+ </xs:documentation>
+ </xs:annotation>
+
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\*|([A-Z]{4}[0-9]{4})"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+</xs:schema>
diff --git a/pom.xml b/pom.xml
index 95f8103..506d57d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
<module>asterix-external-data</module>
<module>asterix-metadata</module>
<module>asterix-dist</module>
+ <module>asterix-test-framework</module>
</modules>
<repositories>