aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Naganov <mnaganov@google.com>2021-02-23 02:21:03 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-02-23 02:21:03 +0000
commitfcf13b67d15723b32da321df7d00128aa9781e5e (patch)
tree57624dfde525ab400676998f859f7c2c2cd80232
parent7f109231171d41e94454886e1f200a2281ae001d (diff)
parent2b3040434ef85b51f87c546ca3193dc0f2581981 (diff)
downloadxsdc-fcf13b67d15723b32da321df7d00128aa9781e5e.tar.gz
Split C++ generated code into "enums" and "parser" parts am: 70dbbc6c8d am: d69b0fc8f4 am: 2b3040434e
Original change: https://android-review.googlesource.com/c/platform/system/tools/xsdc/+/1595434 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Id6b7736bdeb08c2c0946af61b3ab5cb2a371d003
-rw-r--r--build/xsdc.go63
-rw-r--r--src/com/android/xsdc/CodeWriter.java21
-rw-r--r--src/com/android/xsdc/Main.java29
-rw-r--r--src/com/android/xsdc/cpp/CppCodeGenerator.java373
-rw-r--r--tests/Android.bp55
-rw-r--r--tests/main.cpp306
-rw-r--r--tests/resources/simple_type/Android.bp16
-rw-r--r--tests/simple_type.cpp52
-rw-r--r--tests/simple_type_enumsonly.cpp28
-rw-r--r--tests/tests.cpp282
-rw-r--r--tests/xmltest.h29
11 files changed, 761 insertions, 493 deletions
diff --git a/build/xsdc.go b/build/xsdc.go
index 22c0fc5..492d68e 100644
--- a/build/xsdc.go
+++ b/build/xsdc.go
@@ -69,7 +69,14 @@ type xsdConfigProperties struct {
// Whether has{element or atrribute} methods are set to public.
// It is not applied to C++, because these methods are always
// generated to public for C++.
- Gen_has *bool
+ Gen_has *bool
+ // Only generate code for enum converters. Applies to C++ only.
+ // This is useful for memory footprint reduction since it avoids
+ // depending on libxml2.
+ Enums_only *bool
+ // Only generate complementary code for XML parser. Applies to C++ only.
+ // The code being generated depends on the enum converters module.
+ Parser_only *bool
}
type xsdConfig struct {
@@ -79,13 +86,13 @@ type xsdConfig struct {
genOutputDir android.Path
genOutputs_j android.WritablePath
- genOutputs_c android.WritablePath
- genOutputs_h android.WritablePath
+ genOutputs_c android.WritablePaths
+ genOutputs_h android.WritablePaths
docsPath android.Path
xsdConfigPath android.OptionalPath
- genOutputs android.Paths
+ genOutputs android.Paths
}
var _ android.SourceFileProducer = (*xsdConfig)(nil)
@@ -112,7 +119,7 @@ type DroidstubsProperties struct {
}
func (module *xsdConfig) GeneratedSourceFiles() android.Paths {
- return android.Paths{module.genOutputs_c}
+ return module.genOutputs_c.Paths()
}
func (module *xsdConfig) Srcs() android.Paths {
@@ -120,7 +127,7 @@ func (module *xsdConfig) Srcs() android.Paths {
}
func (module *xsdConfig) GeneratedDeps() android.Paths {
- return android.Paths{module.genOutputs_h}
+ return module.genOutputs_h.Paths()
}
func (module *xsdConfig) GeneratedHeaderDirs() android.Paths {
@@ -179,6 +186,14 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
args = args + " -g "
}
+ if proptools.Bool(module.properties.Enums_only) {
+ args = args + " -e "
+ }
+
+ if proptools.Bool(module.properties.Parser_only) {
+ args = args + " -x "
+ }
+
module.genOutputs_j = android.PathForModuleGen(ctx, "java", filenameStem+"_xsdcgen.srcjar")
ctx.Build(pctx, android.BuildParams{
@@ -189,25 +204,41 @@ func (module *xsdConfig) GenerateAndroidBuildActions(ctx android.ModuleContext)
Output: module.genOutputs_j,
Args: map[string]string{
"pkgName": pkgName,
- "args": args,
+ "args": args,
},
})
- module.genOutputs_c = android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp")
- module.genOutputs_h = android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h")
+ if proptools.Bool(module.properties.Enums_only) {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")}
+ } else if proptools.Bool(module.properties.Parser_only) {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h")}
+ } else {
+ module.genOutputs_c = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", filenameStem+".cpp"),
+ android.PathForModuleGen(ctx, "cpp", filenameStem+"_enums.cpp")}
+ module.genOutputs_h = android.WritablePaths{
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+".h"),
+ android.PathForModuleGen(ctx, "cpp", "include/"+filenameStem+"_enums.h")}
+ }
module.genOutputDir = android.PathForModuleGen(ctx, "cpp", "include")
ctx.Build(pctx, android.BuildParams{
- Rule: xsdcCppRule,
- Description: "xsdc " + xsdFile.String(),
- Input: xsdFile,
- Implicit: module.docsPath,
- Output: module.genOutputs_c,
- ImplicitOutput: module.genOutputs_h,
+ Rule: xsdcCppRule,
+ Description: "xsdc " + xsdFile.String(),
+ Input: xsdFile,
+ Implicit: module.docsPath,
+ Outputs: module.genOutputs_c,
+ ImplicitOutputs: module.genOutputs_h,
Args: map[string]string{
"pkgName": pkgName,
"outDir": android.PathForModuleGen(ctx, "cpp").String(),
- "args": args,
+ "args": args,
},
})
module.xsdConfigPath = android.ExistentPathForSource(ctx, xsdFile.String())
diff --git a/src/com/android/xsdc/CodeWriter.java b/src/com/android/xsdc/CodeWriter.java
index 1ffe801..489ccdc 100644
--- a/src/com/android/xsdc/CodeWriter.java
+++ b/src/com/android/xsdc/CodeWriter.java
@@ -24,6 +24,10 @@ public class CodeWriter implements Closeable {
private int indent;
private boolean startLine;
+ public CodeWriter() {
+ this(null);
+ }
+
public CodeWriter(PrintWriter printWriter) {
out = printWriter;
indent = 0;
@@ -33,13 +37,15 @@ public class CodeWriter implements Closeable {
private void printIndent() {
assert startLine;
for (int i = 0; i < indent; ++i) {
- out.print(" ");
+ printImpl(" ");
}
startLine = false;
}
public void println() {
- out.println();
+ if (out != null) {
+ out.println();
+ }
startLine = true;
}
@@ -58,13 +64,12 @@ public class CodeWriter implements Closeable {
if (startLine && !line.isEmpty()) {
printIndent();
}
- out.print(line);
+ printImpl(line);
if (line.endsWith("{")) {
++indent;
}
if (i + 1 < lines.length) {
- out.println();
- startLine = true;
+ println();
}
}
}
@@ -79,4 +84,10 @@ public class CodeWriter implements Closeable {
out.close();
}
}
+
+ private void printImpl(String code) {
+ if (out != null) {
+ out.print(code);
+ }
+ }
}
diff --git a/src/com/android/xsdc/Main.java b/src/com/android/xsdc/Main.java
index 5f786f3..caac98b 100644
--- a/src/com/android/xsdc/Main.java
+++ b/src/com/android/xsdc/Main.java
@@ -29,7 +29,9 @@ import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
@@ -75,6 +77,24 @@ public class Main {
.hasArgs(0)
.withDescription("Generate public hasX() method")
.create("g"));
+ Option genEnumsOnly = OptionBuilder
+ .withLongOpt("genEnumsOnly")
+ .hasArgs(0)
+ .withDescription("Only generate enum converters in Cpp code.")
+ .create("e");
+ options.addOption(genEnumsOnly);
+ Option genParserOnly = OptionBuilder
+ .withLongOpt("genParserOnly")
+ .hasArgs(0)
+ .withDescription("Only generate XML parser in Cpp code.")
+ .create("x");
+ options.addOption(genParserOnly);
+ // "Only generate enums" and "Only generate parser" options are mutually exclusive.
+ OptionGroup genOnlyGroup = new OptionGroup();
+ genOnlyGroup.setRequired(false);
+ genOnlyGroup.addOption(genEnumsOnly);
+ genOnlyGroup.addOption(genParserOnly);
+ options.addOptionGroup(genOnlyGroup);
CommandLineParser CommandParser = new GnuParser();
CommandLine cmd;
@@ -93,9 +113,11 @@ public class Main {
boolean writer = cmd.hasOption('w');
boolean nullability = cmd.hasOption('n');
boolean genHas = cmd.hasOption('g');
+ boolean enumsOnly = cmd.hasOption('e');
+ boolean parserOnly = cmd.hasOption('x');
if (xsdFile.length != 1 || packageName == null) {
- System.err.println("Error: no xsd files or pacakge name");
+ System.err.println("Error: no xsd files or package name");
help(options);
}
@@ -116,8 +138,11 @@ public class Main {
File includeDir = new File(Paths.get(outDir, "include").toString());
includeDir.mkdirs();
FileSystem fs = new FileSystem(new File(outDir));
+ int generators = enumsOnly ? CppCodeGenerator.GENERATE_ENUMS :
+ (parserOnly ? CppCodeGenerator.GENERATE_PARSER :
+ CppCodeGenerator.GENERATE_ENUMS | CppCodeGenerator.GENERATE_PARSER);
CppCodeGenerator cppCodeGenerator =
- new CppCodeGenerator(xmlSchema, packageName, writer);
+ new CppCodeGenerator(xmlSchema, packageName, writer, generators);
cppCodeGenerator.print(fs);
}
}
diff --git a/src/com/android/xsdc/cpp/CppCodeGenerator.java b/src/com/android/xsdc/cpp/CppCodeGenerator.java
index e2a98c8..561d3f5 100644
--- a/src/com/android/xsdc/cpp/CppCodeGenerator.java
+++ b/src/com/android/xsdc/cpp/CppCodeGenerator.java
@@ -34,21 +34,28 @@ import java.util.Set;
import javax.xml.namespace.QName;
public class CppCodeGenerator {
+ public static final int GENERATE_ENUMS = 1 << 0;
+ public static final int GENERATE_PARSER = 1 << 1;
+
private XmlSchema xmlSchema;
private String pkgName;
private Map<String, CppSimpleType> cppSimpleTypeMap;
- private CodeWriter cppFile;
- private CodeWriter headerFile;
+ private CodeWriter enumsCppFile;
+ private CodeWriter enumsHeaderFile;
+ private CodeWriter parserCppFile;
+ private CodeWriter parserHeaderFile;
private boolean hasAttr;
private boolean writer;
+ private int generators;
private static final String UNKNOWN_ENUM = "UNKNOWN";
- public CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer)
+ public CppCodeGenerator(XmlSchema xmlSchema, String pkgName, boolean writer, int generators)
throws CppCodeGeneratorException {
this.xmlSchema = xmlSchema;
this.pkgName = pkgName;
this.writer = writer;
+ this.generators = generators;
// class naming validation
{
@@ -95,11 +102,26 @@ public class CppCodeGenerator {
public void print(FileSystem fs)
throws CppCodeGeneratorException, IOException {
- // cpp file, headr file init
- String cppFileName = pkgName.replace(".", "_") + ".cpp";
- String hFileName = pkgName.replace(".", "_") + ".h";
- cppFile = new CodeWriter(fs.getPrintWriter(cppFileName));
- headerFile = new CodeWriter(fs.getPrintWriter("include/" + hFileName));
+ // cpp file, header file init
+ String fileNameStem = pkgName.replace('.', '_');
+ String enumsCppFileName = fileNameStem + "_enums.cpp";
+ String enumsHeaderFileName = fileNameStem + "_enums.h";
+ String parserCppFileName = fileNameStem + ".cpp";
+ String parserHeaderFileName = fileNameStem + ".h";
+ if ((this.generators & GENERATE_ENUMS) == GENERATE_ENUMS) {
+ enumsCppFile = new CodeWriter(fs.getPrintWriter(enumsCppFileName));
+ enumsHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + enumsHeaderFileName));
+ } else {
+ enumsCppFile = new CodeWriter();
+ enumsHeaderFile = new CodeWriter();
+ }
+ if ((this.generators & GENERATE_PARSER) == GENERATE_PARSER) {
+ parserCppFile = new CodeWriter(fs.getPrintWriter(parserCppFileName));
+ parserHeaderFile = new CodeWriter(fs.getPrintWriter("include/" + parserHeaderFileName));
+ } else {
+ parserCppFile = new CodeWriter();
+ parserHeaderFile = new CodeWriter();
+ }
boolean hasEnums = false;
for (XsdType type : xmlSchema.getTypeMap().values()) {
@@ -110,33 +132,46 @@ public class CppCodeGenerator {
}
}
- String headerMacro = hFileName.toUpperCase().replace(".", "_");
- headerFile.printf("#ifndef %s\n", headerMacro);
- headerFile.printf("#define %s\n", headerMacro);
- headerFile.printf("\n");
- headerFile.printf("#include <array>\n");
- headerFile.printf("#include <map>\n");
- headerFile.printf("#include <optional>\n");
- headerFile.printf("#include <string>\n");
- headerFile.printf("#include <vector>\n");
+ String enumsHeaderMacro = enumsHeaderFileName.toUpperCase().replace('.', '_');
+ String parserHeaderMacro = parserHeaderFileName.toUpperCase().replace('.', '_');
+ enumsHeaderFile.printf("#ifndef %s\n", enumsHeaderMacro);
+ enumsHeaderFile.printf("#define %s\n", enumsHeaderMacro);
+ enumsHeaderFile.printf("\n");
+ enumsHeaderFile.printf("#include <array>\n");
+ enumsHeaderFile.printf("#include <string>\n");
+ enumsHeaderFile.printf("\n");
+ parserHeaderFile.printf("#ifndef %s\n", parserHeaderMacro);
+ parserHeaderFile.printf("#define %s\n", parserHeaderMacro);
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#include <array>\n");
+ parserHeaderFile.printf("#include <map>\n");
+ parserHeaderFile.printf("#include <optional>\n");
+ parserHeaderFile.printf("#include <string>\n");
+ parserHeaderFile.printf("#include <vector>\n");
if (writer) {
- headerFile.printf("#include <iostream>\n");
- }
- headerFile.printf("\n");
- headerFile.printf("#if __has_include(<libxml/parser.h>)\n");
- headerFile.printf("#include <libxml/parser.h>\n");
- headerFile.printf("#include <libxml/xinclude.h>\n");
- headerFile.printf("#else\n");
- headerFile.printf("#error Require libxml2 library. ");
- headerFile.printf("Please add libxml2 to shared_libs or static_libs\n");
- headerFile.printf("#endif\n");
+ parserHeaderFile.printf("#include <iostream>\n");
+ }
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#if __has_include(<libxml/parser.h>)\n");
+ parserHeaderFile.printf("#include <libxml/parser.h>\n");
+ parserHeaderFile.printf("#include <libxml/xinclude.h>\n");
+ parserHeaderFile.printf("#else\n");
+ parserHeaderFile.printf("#error Require libxml2 library. ");
+ parserHeaderFile.printf("Please add libxml2 to shared_libs or static_libs\n");
+ parserHeaderFile.printf("#endif\n");
if (hasEnums) {
- headerFile.printf("#include <xsdc/XsdcSupport.h>\n");
+ enumsHeaderFile.printf("#include <xsdc/XsdcSupport.h>\n");
+ enumsHeaderFile.printf("\n");
}
- headerFile.printf("\n");
+ parserHeaderFile.printf("\n");
+ parserHeaderFile.printf("#include \"%s\"\n", enumsHeaderFileName);
+ parserHeaderFile.printf("\n");
- cppFile.printf("#define LOG_TAG \"%s\"\n", pkgName);
- cppFile.printf("#include \"%s\"\n\n", hFileName);
+ enumsCppFile.printf("#include <map>\n");
+ enumsCppFile.printf("\n");
+ enumsCppFile.printf("#include \"%s\"\n\n", enumsHeaderFileName);
+ parserCppFile.printf("#define LOG_TAG \"%s\"\n", pkgName);
+ parserCppFile.printf("#include \"%s\"\n\n", parserHeaderFileName);
List<String> namespace = new java.util.ArrayList<>();
for (String token : pkgName.split("\\.")) {
@@ -147,8 +182,10 @@ public class CppCodeGenerator {
token = "_" + token;
}
namespace.add(token);
- headerFile.printf("namespace %s {\n", token);
- cppFile.printf("namespace %s {\n", token);
+ enumsHeaderFile.printf("namespace %s {\n", token);
+ enumsCppFile.printf("namespace %s {\n", token);
+ parserHeaderFile.printf("namespace %s {\n", token);
+ parserCppFile.printf("namespace %s {\n", token);
}
printPrototype();
@@ -183,13 +220,15 @@ public class CppCodeGenerator {
Collections.reverse(namespace);
for (String token : namespace) {
- headerFile.printf("} // %s\n", token);
- cppFile.printf("} // %s\n", token);
+ enumsHeaderFile.printf("} // %s\n", token);
+ enumsCppFile.printf("} // %s\n", token);
+ parserHeaderFile.printf("} // %s\n", token);
+ parserCppFile.printf("} // %s\n", token);
}
if (hasEnums) {
- headerFile.printf("\n//\n// global type declarations for package\n//\n\n");
- headerFile.printf("namespace android {\nnamespace details {\n");
+ enumsHeaderFile.printf("\n//\n// global type declarations for package\n//\n\n");
+ enumsHeaderFile.printf("namespace android {\nnamespace details {\n");
Collections.reverse(namespace);
for (XsdType type : xmlSchema.getTypeMap().values()) {
if (type instanceof XsdRestriction &&
@@ -199,82 +238,79 @@ public class CppCodeGenerator {
printEnumValues(namespace, name, restrictionType);
}
}
- headerFile.printf("} // namespace details\n} // namespace android\n\n");
+ enumsHeaderFile.printf("} // namespace details\n} // namespace android\n\n");
}
- headerFile.printf("#endif // %s\n", headerMacro);
- cppFile.close();
- headerFile.close();
+ parserHeaderFile.printf("#endif // %s\n", parserHeaderMacro);
+ enumsHeaderFile.printf("#endif // %s\n", enumsHeaderMacro);
+ parserCppFile.close();
+ parserHeaderFile.close();
+ enumsCppFile.close();
+ enumsHeaderFile.close();
}
private void printEnum(String name, XsdRestriction restrictionType)
throws CppCodeGeneratorException {
- headerFile.printf("enum class %s {\n", name);
- cppFile.printf("const std::map<std::string, %s> %sString {\n", name, name);
+ enumsHeaderFile.printf("enum class %s {\n", name);
+ enumsCppFile.printf("const std::map<std::string, %s> %sString {\n", name, name);
List<XsdEnumeration> enums = restrictionType.getEnums();
- headerFile.printf("%s = %d,\n", UNKNOWN_ENUM, -1);
+ enumsHeaderFile.printf("%s = %d,\n", UNKNOWN_ENUM, -1);
for (XsdEnumeration tag : enums) {
String value = tag.getValue();
- headerFile.printf("%s,\n", Utils.toEnumName(value));
- cppFile.printf("{ \"%s\", %s::%s },\n", tag.getValue(), name,
+ enumsHeaderFile.printf("%s,\n", Utils.toEnumName(value));
+ enumsCppFile.printf("{ \"%s\", %s::%s },\n", tag.getValue(), name,
Utils.toEnumName(value));
}
- headerFile.printf("};\n");
- cppFile.printf("};\n\n");
+ enumsHeaderFile.printf("};\n");
+ enumsCppFile.printf("};\n\n");
- headerFile.printf("%s stringTo%s(const std::string& value);\n",
+ enumsHeaderFile.printf("%s stringTo%s(const std::string& value);\n",
name, name);
- cppFile.printf("%s stringTo%s(const std::string& value) {\n"
+ enumsCppFile.printf("%s stringTo%s(const std::string& value) {\n"
+ "auto enumValue = %sString.find(value);\n"
+ "return enumValue != %sString.end() ? enumValue->second : %s::%s;\n"
+ "}\n\n", name, name, name, name, name, UNKNOWN_ENUM);
- headerFile.printf("std::string toString(%s o);\n\n", name);
- cppFile.printf("std::string toString(%s o) {\n", name);
- cppFile.printf("switch (o) {\n");
+ enumsHeaderFile.printf("std::string toString(%s o);\n\n", name);
+ enumsCppFile.printf("std::string toString(%s o) {\n", name);
+ enumsCppFile.printf("switch (o) {\n");
for (XsdEnumeration tag : enums) {
String value = tag.getValue();
- cppFile.printf("case %s::%s: return \"%s\";\n",
+ enumsCppFile.printf("case %s::%s: return \"%s\";\n",
name, Utils.toEnumName(value), tag.getValue());
}
- cppFile.printf("default: return std::to_string(static_cast<int>(o));\n}\n");
- cppFile.printf("}\n\n");
+ enumsCppFile.printf("default: return std::to_string(static_cast<int>(o));\n}\n");
+ enumsCppFile.printf("}\n\n");
}
private void printEnumValues(List<String> namespace, String name,
XsdRestriction restrictionType) throws CppCodeGeneratorException {
List<XsdEnumeration> enums = restrictionType.getEnums();
String absoluteNamespace = "::" + String.join("::", namespace);
- headerFile.printf("template<> inline constexpr std::array<%s::%s, %d> "
+ enumsHeaderFile.printf("template<> inline constexpr std::array<%s::%s, %d> "
+ "xsdc_enum_values<%s::%s> = {\n",
absoluteNamespace, name, enums.size(), absoluteNamespace, name);
for (XsdEnumeration tag : enums) {
String value = tag.getValue();
- headerFile.printf("%s::%s::%s,\n", absoluteNamespace, name, Utils.toEnumName(value));
+ enumsHeaderFile.printf("%s::%s::%s,\n",
+ absoluteNamespace, name, Utils.toEnumName(value));
}
- headerFile.printf("};\n");
+ enumsHeaderFile.printf("};\n");
}
private void printPrototype() throws CppCodeGeneratorException {
for (XsdType type : xmlSchema.getTypeMap().values()) {
- if (type instanceof XsdRestriction &&
- ((XsdRestriction)type).getEnums() != null) {
- String name = Utils.toClassName(type.getName());
- headerFile.printf("enum class %s;\n", name);
- }
- }
- for (XsdType type : xmlSchema.getTypeMap().values()) {
if (type instanceof XsdComplexType) {
String name = Utils.toClassName(type.getName());
- headerFile.printf("class %s;\n", name);
+ parserHeaderFile.printf("class %s;\n", name);
}
}
for (XsdElement element : xmlSchema.getElementMap().values()) {
XsdType type = element.getType();
if (type.getRef() == null && type instanceof XsdComplexType) {
String name = Utils.toClassName(element.getName());
- headerFile.printf("class %s;\n", name);
+ parserHeaderFile.printf("class %s;\n", name);
}
}
}
@@ -288,12 +324,12 @@ public class CppCodeGenerator {
CppSimpleType valueType = (complexType instanceof XsdSimpleContent) ?
getValueType((XsdSimpleContent) complexType, false) : null;
- headerFile.printf("class %s ", name);
+ parserHeaderFile.printf("class %s ", name);
if (baseName != null) {
- headerFile.printf(": public %s {\n", baseName);
+ parserHeaderFile.printf(": public %s {\n", baseName);
} else {
- headerFile.println("{");
+ parserHeaderFile.println("{");
}
// parse types for elements and attributes
@@ -308,11 +344,11 @@ public class CppCodeGenerator {
if (element.getRef() == null && element.getType().getRef() == null
&& element.getType() instanceof XsdComplexType) {
// print inner class for anonymous types
- headerFile.printf("public:\n");
+ parserHeaderFile.printf("public:\n");
String innerName = Utils.toClassName(getElementName(element));
XsdComplexType innerType = (XsdComplexType) element.getType();
printClass(innerName, nameScope + name + "::", innerType);
- headerFile.println();
+ parserHeaderFile.println();
cppType = new CppComplexType(nameScope + name + "::"+ innerName);
} else {
cppType = parseType(elementValue.getType(), getElementName(elementValue));
@@ -333,14 +369,14 @@ public class CppCodeGenerator {
// print member variables
- headerFile.printf("private:\n");
+ parserHeaderFile.printf("private:\n");
for (int i = 0; i < elementTypes.size(); ++i) {
CppType type = elementTypes.get(i);
XsdElement element = elements.get(i);
XsdElement elementValue = resolveElement(element);
String typeName = Utils.elementTypeName(type.getName(),
element.isMultiple() || type instanceof CppComplexType);
- headerFile.printf("const %s %s_;\n", typeName,
+ parserHeaderFile.printf("const %s %s_;\n", typeName,
Utils.toVariableName(getElementName(elementValue)));
}
for (int i = 0; i < attributeTypes.size(); ++i) {
@@ -348,16 +384,17 @@ public class CppCodeGenerator {
XsdAttribute attribute = resolveAttribute(attributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
if (attribute.isRequired()) {
- headerFile.printf("const %s %s_;\n", type.getName(), variableName);
+ parserHeaderFile.printf("const %s %s_;\n", type.getName(), variableName);
} else {
- headerFile.printf("const std::optional<%s> %s_;\n", type.getName(), variableName);
+ parserHeaderFile.printf("const std::optional<%s> %s_;\n",
+ type.getName(), variableName);
}
}
if (valueType != null) {
- headerFile.printf("const std::optional<%s> _value;\n", valueType.getName());
+ parserHeaderFile.printf("const std::optional<%s> _value;\n", valueType.getName());
}
- headerFile.printf("public:\n");
+ parserHeaderFile.printf("public:\n");
String constructorArgs = printConstructor(name, nameScope, complexType, elements,
attributes, baseName);
@@ -388,7 +425,7 @@ public class CppCodeGenerator {
printWriter(name, nameScope, complexType);
}
- headerFile.println("};\n");
+ parserHeaderFile.println("};\n");
}
private void printParser(String name, String nameScope, XsdComplexType complexType, String args)
@@ -413,51 +450,51 @@ public class CppCodeGenerator {
}
String fullName = nameScope + name;
- headerFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name));
- cppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName);
+ parserHeaderFile.printf("static %s read(xmlNode *root);\n", fullName, Utils.lowerize(name));
+ parserCppFile.printf("\n%s %s::read(xmlNode *root) {\n", fullName, fullName);
- cppFile.print("std::string raw;\n");
+ parserCppFile.print("std::string raw;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
CppSimpleType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
- cppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
+ parserCppFile.printf("raw = getXmlAttribute(root, \"%s\");\n", attribute.getName());
if (attribute.isRequired()) {
if (type.isEnum()) {
- cppFile.printf("%s %s = %s::%s;\n",
+ parserCppFile.printf("%s %s = %s::%s;\n",
type.getName(), variableName, type.getName(), UNKNOWN_ENUM);
} else {
- cppFile.printf("%s %s{};\n", type.getName(), variableName);
+ parserCppFile.printf("%s %s{};\n", type.getName(), variableName);
}
} else {
- cppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(),
+ parserCppFile.printf("std::optional<%s> %s = std::nullopt;\n", type.getName(),
variableName);
}
- cppFile.printf("if (raw != \"\") {\n");
- cppFile.print(type.getParsingExpression());
- cppFile.printf("%s = value;\n}\n", variableName);
+ parserCppFile.printf("if (raw != \"\") {\n");
+ parserCppFile.print(type.getParsingExpression());
+ parserCppFile.printf("%s = value;\n}\n", variableName);
}
if (baseValueType != null) {
- cppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString("
+ parserCppFile.printf("auto xmlValue = make_xmlUnique(xmlNodeListGetString("
+ "root->doc, root->xmlChildrenNode, 1));\n"
+ "if (xmlValue != nullptr) {\n"
+ "raw = reinterpret_cast<const char*>(xmlValue.get());\n");
- cppFile.print(baseValueType.getParsingExpression());
- cppFile.printf("instance.setValue(value);\n");
- cppFile.printf("}\n");
+ parserCppFile.print(baseValueType.getParsingExpression());
+ parserCppFile.printf("instance.setValue(value);\n");
+ parserCppFile.printf("}\n");
} else if (!allElements.isEmpty()) {
for (int i = 0; i < allElements.size(); ++i) {
CppType type = allElementTypes.get(i);
XsdElement element = allElements.get(i);
XsdElement elementValue = resolveElement(element);
String variableName = Utils.toVariableName(getElementName(elementValue));
- cppFile.printf("%s %s;\n", Utils.elementTypeName(type.getName(),
+ parserCppFile.printf("%s %s;\n", Utils.elementTypeName(type.getName(),
element.isMultiple() || type instanceof CppComplexType), variableName);
}
- cppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;"
+ parserCppFile.print("for (xmlNode *child = root->xmlChildrenNode; child != nullptr;"
+ " child = child->next) {\n");
for (int i = 0; i < allElements.size(); ++i) {
CppType type = allElementTypes.get(i);
@@ -465,29 +502,31 @@ public class CppCodeGenerator {
XsdElement elementValue = resolveElement(element);
String variableName = Utils.toVariableName(getElementName(elementValue));
- if (i != 0) cppFile.printf("} else ");
- cppFile.print("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
- cppFile.printf("(\"%s\"))) {\n", elementValue.getName());
+ if (i != 0) parserCppFile.printf("} else ");
+ parserCppFile.print("if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>");
+ parserCppFile.printf("(\"%s\"))) {\n", elementValue.getName());
if (type instanceof CppSimpleType) {
- cppFile.print("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
- cppFile.print("child->doc, child->xmlChildrenNode, 1));\n");
- cppFile.print("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
- cppFile.print("raw = reinterpret_cast<const char*>(xmlValue.get());\n}\n");
+ parserCppFile.print("auto xmlValue = make_xmlUnique(xmlNodeListGetString(");
+ parserCppFile.print("child->doc, child->xmlChildrenNode, 1));\n");
+ parserCppFile.print("if (xmlValue == nullptr) {\nraw = \"\";\n} else {\n");
+ parserCppFile.print("raw = reinterpret_cast<const char*>(xmlValue.get());\n}");
+ parserCppFile.print("\n");
}
- cppFile.print(type.getParsingExpression());
+ parserCppFile.print(type.getParsingExpression());
if (element.isMultiple() || type instanceof CppComplexType) {
- cppFile.printf("%s.push_back(std::move(value));\n", variableName);
+ parserCppFile.printf("%s.push_back(std::move(value));\n", variableName);
} else {
- cppFile.printf("%s = std::move(value);\n", variableName);
+ parserCppFile.printf("%s = std::move(value);\n", variableName);
}
}
- cppFile.printf("}\n}\n");
+ parserCppFile.printf("}\n}\n");
}
- cppFile.printf("%s instance%s;\n", fullName, args.length() > 0 ? "(" + args + ")" : "");
- cppFile.print("return instance;\n}\n");
+ parserCppFile.printf("%s instance%s;\n",
+ fullName, args.length() > 0 ? "(" + args + ")" : "");
+ parserCppFile.print("return instance;\n}\n");
}
private void printWriter(String name, String nameScope, XsdComplexType complexType)
@@ -512,23 +551,24 @@ public class CppCodeGenerator {
}
String fullName = nameScope + name;
- headerFile.printf("void write(std::ostream& out, const std::string& name) const;\n");
- cppFile.printf("\nvoid %s::write(std::ostream& out, const std::string& name) const {\n",
+ parserHeaderFile.printf("void write(std::ostream& out, const std::string& name) const;\n");
+ parserCppFile.printf(
+ "\nvoid %s::write(std::ostream& out, const std::string& name) const {\n",
fullName);
- cppFile.printf("out << printIndent() << \"<\" << name;\n");
+ parserCppFile.printf("out << printIndent() << \"<\" << name;\n");
for (int i = 0; i < allAttributes.size(); ++i) {
CppType type = allAttributeTypes.get(i);
XsdAttribute attribute = resolveAttribute(allAttributes.get(i));
String variableName = Utils.toVariableName(attribute.getName());
- cppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
- cppFile.printf("out << \" %s=\\\"\";\n", attribute.getName());
- cppFile.print(type.getWritingExpression(String.format("get%s()",
+ parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ parserCppFile.printf("out << \" %s=\\\"\";\n", attribute.getName());
+ parserCppFile.print(type.getWritingExpression(String.format("get%s()",
Utils.capitalize(variableName)), attribute.getName()));
- cppFile.printf("out << \"\\\"\";\n}\n");
+ parserCppFile.printf("out << \"\\\"\";\n}\n");
}
- cppFile.print("out << \">\" << std::endl;\n");
- cppFile.print("++indentIndex;\n");
+ parserCppFile.print("out << \">\" << std::endl;\n");
+ parserCppFile.print("++indentIndex;\n");
if (!allElements.isEmpty()) {
for (int i = 0; i < allElements.size(); ++i) {
@@ -539,37 +579,38 @@ public class CppCodeGenerator {
String variableName = Utils.toVariableName(elementName);
if (type instanceof CppComplexType || element.isMultiple()) {
- cppFile.printf("for (auto& value : get%s()) {\n",
+ parserCppFile.printf("for (auto& value : get%s()) {\n",
Utils.capitalize(variableName));
if (type instanceof CppSimpleType) {
- cppFile.printf("out << printIndent() << \"<%s>\";\n",
+ parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
elementValue.getName());
}
- cppFile.printf(type.getWritingExpression("value", elementValue.getName()));
+ parserCppFile.printf(
+ type.getWritingExpression("value", elementValue.getName()));
if (type instanceof CppSimpleType) {
- cppFile.printf("out << \"</%s>\" << std::endl;\n",
+ parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
elementValue.getName());
}
- cppFile.printf("}\n");
+ parserCppFile.printf("}\n");
} else {
- cppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
+ parserCppFile.printf("if (has%s()) {\n", Utils.capitalize(variableName));
if (type instanceof CppSimpleType) {
- cppFile.printf("out << printIndent() << \"<%s>\";\n",
+ parserCppFile.printf("out << printIndent() << \"<%s>\";\n",
elementValue.getName());
}
- cppFile.print(type.getWritingExpression(String.format("get%s()",
+ parserCppFile.print(type.getWritingExpression(String.format("get%s()",
Utils.capitalize(variableName)), elementValue.getName()));
if (type instanceof CppSimpleType) {
- cppFile.printf("out << \"</%s>\" << std::endl;\n",
+ parserCppFile.printf("out << \"</%s>\" << std::endl;\n",
elementValue.getName());
}
- cppFile.print("}\n");
+ parserCppFile.print("}\n");
}
}
}
- cppFile.print("--indentIndex;\n");
- cppFile.printf("out << printIndent() << \"</\" << name << \">\" << std::endl;\n");
- cppFile.printf("}\n");
+ parserCppFile.print("--indentIndex;\n");
+ parserCppFile.printf("out << printIndent() << \"</\" << name << \">\" << std::endl;\n");
+ parserCppFile.printf("}\n");
}
private void printGetter(String name, CppType type, String variableName,
@@ -577,32 +618,33 @@ public class CppCodeGenerator {
String typeName = isMultiple ? String.format("std::vector<%s>",
type.getName()) : type.getName();
- headerFile.printf("const %s& get%s() const;\n", typeName, Utils.capitalize(variableName));
+ parserHeaderFile.printf("const %s& get%s() const;\n", typeName,
+ Utils.capitalize(variableName));
- cppFile.println();
- cppFile.printf("const %s& %s::get%s() const {\n"
+ parserCppFile.println();
+ parserCppFile.printf("const %s& %s::get%s() const {\n"
+ "return %s;\n}\n\n",
typeName, name, Utils.capitalize(variableName), isMultiple || isRequired ?
variableName + "_" : String.format("%s_.value()", variableName));
- headerFile.printf("bool has%s() const;\n", Utils.capitalize(variableName));
- cppFile.printf("bool %s::has%s() const {\n", name, Utils.capitalize(variableName));
+ parserHeaderFile.printf("bool has%s() const;\n", Utils.capitalize(variableName));
+ parserCppFile.printf("bool %s::has%s() const {\n", name, Utils.capitalize(variableName));
if (isMultiple) {
- cppFile.printf("return !(%s_.empty());\n}\n", variableName);
+ parserCppFile.printf("return !(%s_.empty());\n}\n", variableName);
} else if (isRequired){
- cppFile.print("return true;\n}\n");
+ parserCppFile.print("return true;\n}\n");
} else {
- cppFile.printf("return %s_.has_value();\n}\n", variableName);
+ parserCppFile.printf("return %s_.has_value();\n}\n", variableName);
}
if (isMultiple || isMultipleType) {
String elementTypeName = type instanceof CppComplexType ? type.getName() :
((CppSimpleType)type).getTypeName();
if (elementTypeName.equals("bool")) {
- headerFile.printf("%s getFirst%s() const;\n",
+ parserHeaderFile.printf("%s getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
- cppFile.println();
- cppFile.printf("%s %s::getFirst%s() const {\n"
+ parserCppFile.println();
+ parserCppFile.printf("%s %s::getFirst%s() const {\n"
+ "if (%s_%sempty()) {\n"
+ "return false;\n"
+ "}\n"
@@ -613,10 +655,10 @@ public class CppCodeGenerator {
isMultiple ? String.format("%s_[0]", variableName) :
String.format("%s_.value()[0]", variableName));
} else {
- headerFile.printf("const %s* getFirst%s() const;\n",
+ parserHeaderFile.printf("const %s* getFirst%s() const;\n",
elementTypeName, Utils.capitalize(variableName));
- cppFile.println();
- cppFile.printf("const %s* %s::getFirst%s() const {\n"
+ parserCppFile.println();
+ parserCppFile.printf("const %s* %s::getFirst%s() const {\n"
+ "if (%s_%sempty()) {\n"
+ "return nullptr;\n"
+ "}\n"
@@ -692,17 +734,17 @@ public class CppCodeGenerator {
if (constructorArgsString.length() > 0) {
constructorArgsString = constructorArgsString.substring(2);
}
- headerFile.printf("%s(%s);\n", name, constructorArgsString);
- cppFile.printf("\n%s::%s(%s) : ", fullName, name, constructorArgsString);
+ parserHeaderFile.printf("%s(%s);\n", name, constructorArgsString);
+ parserCppFile.printf("\n%s::%s(%s) : ", fullName, name, constructorArgsString);
String parentArgsString = parentArgs.toString();
if (parentArgsString.length() > 0) {
parentArgsString = parentArgsString.substring(2);
- cppFile.printf("%s(%s)", baseName, parentArgsString);
+ parserCppFile.printf("%s(%s)", baseName, parentArgsString);
} else {
constructorString = constructorString.substring(2);
}
- cppFile.printf("%s {\n}\n", constructorString);
+ parserCppFile.printf("%s {\n}\n", constructorString);
String argsString = args.toString();
if (argsString.length() > 0) {
@@ -712,7 +754,7 @@ public class CppCodeGenerator {
}
private void printXmlParser() throws CppCodeGeneratorException {
- cppFile.printf("template <class T>\n"
+ parserCppFile.printf("template <class T>\n"
+ "constexpr void (*xmlDeleter)(T* t);\n"
+ "template <>\nconstexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;\n"
+ "template <>\nauto xmlDeleter<xmlChar> = [](xmlChar *s) { xmlFree(s); };\n\n"
@@ -723,7 +765,7 @@ public class CppCodeGenerator {
+ "}\n\n");
if (hasAttr) {
- cppFile.printf("static std::string getXmlAttribute"
+ parserCppFile.printf("static std::string getXmlAttribute"
+ "(const xmlNode *cur, const char *attribute) {\n"
+ "auto xmlValue = make_xmlUnique(xmlGetProp(cur, "
+ "reinterpret_cast<const xmlChar*>(attribute)));\n"
@@ -745,11 +787,11 @@ public class CppCodeGenerator {
String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
Utils.toClassName(cppType.getName());
- headerFile.printf("std::optional<%s> read%s(const char* configFile);\n\n",
+ parserHeaderFile.printf("std::optional<%s> read%s(const char* configFile);\n\n",
typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- cppFile.printf("std::optional<%s> read%s(const char* configFile) {\n",
+ parserCppFile.printf("std::optional<%s> read%s(const char* configFile) {\n",
typeName, isMultiRootElement ? Utils.capitalize(typeName) : "");
- cppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n"
+ parserCppFile.printf("auto doc = make_xmlUnique(xmlParseFile(configFile));\n"
+ "if (doc == nullptr) {\n"
+ "return std::nullopt;\n"
+ "}\n"
@@ -765,14 +807,14 @@ public class CppCodeGenerator {
elementName);
if (cppType instanceof CppSimpleType) {
- cppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n",
+ parserCppFile.printf("%s value = getXmlAttribute(child, \"%s\");\n",
elementName, elementName);
} else {
- cppFile.printf(cppType.getParsingExpression());
+ parserCppFile.printf(cppType.getParsingExpression());
}
- cppFile.printf("return value;\n}\n");
- cppFile.printf("return std::nullopt;\n");
- cppFile.printf("}\n\n");
+ parserCppFile.printf("return value;\n}\n");
+ parserCppFile.printf("return std::nullopt;\n");
+ parserCppFile.printf("}\n\n");
}
}
@@ -783,17 +825,18 @@ public class CppCodeGenerator {
String VariableName = Utils.toVariableName(elementName);
String typeName = cppType instanceof CppSimpleType ? cppType.getName() :
Utils.toClassName(cppType.getName());
- headerFile.printf("void write(std::ostream& out, %s& %s);\n\n",
+ parserHeaderFile.printf("void write(std::ostream& out, %s& %s);\n\n",
typeName, VariableName);
- cppFile.printf("void write(std::ostream& out, %s& %s) {\n",
+ parserCppFile.printf("void write(std::ostream& out, %s& %s) {\n",
typeName, VariableName);
- cppFile.print("out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n");
- cppFile.printf("%s.write(out, \"%s\");\n", VariableName, elementName);
- cppFile.printf("}\n\n");
+ parserCppFile.print(
+ "out << \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\"?>\\n\";\n");
+ parserCppFile.printf("%s.write(out, \"%s\");\n", VariableName, elementName);
+ parserCppFile.printf("}\n\n");
}
- cppFile.print("static int indentIndex = 0;\n"
+ parserCppFile.print("static int indentIndex = 0;\n"
+ "std::string printIndent() {\n"
+ "std::string s = \"\";\n"
+ "for (int index = 0; index < indentIndex; ++index) {\n"
diff --git a/tests/Android.bp b/tests/Android.bp
index d49369b..ab44220 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -32,6 +32,8 @@ java_test_host {
cc_test_host {
name: "xsdc-cpp-tests",
srcs: [
+ "simple_type.cpp",
+ "tests.cpp",
"main.cpp",
],
test_options: {
@@ -67,3 +69,56 @@ cc_test_host {
data: ["resources/*.xml"],
test_suites: ["general-tests"],
}
+
+// These tests verify that enums-only and parser-only
+// modules can be combined later.
+cc_test_host {
+ name: "xsdc-cpp-tests-split",
+ srcs: [
+ "simple_type.cpp",
+ "main.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ generated_sources: [
+ "xsdc_simple_type_tests_enums",
+ "xsdc_simple_type_tests_parser",
+ ],
+ generated_headers: [
+ "xsdc_simple_type_tests_enums",
+ "xsdc_simple_type_tests_parser",
+ ],
+ header_libs: ["libxsdc-utils"],
+ shared_libs: [
+ "libbase",
+ "libxml2",
+ ],
+ data: ["resources/*.xml"],
+ test_suites: ["general-tests"],
+}
+
+// These tests verify that enums-only module can be used on
+// its own and it does not depend on libxml2.
+cc_test_host {
+ name: "xsdc-cpp-tests-enums",
+ srcs: [
+ "simple_type_enumsonly.cpp",
+ "main.cpp",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+ generated_sources: [
+ "xsdc_simple_type_tests_enums",
+ ],
+ generated_headers: [
+ "xsdc_simple_type_tests_enums",
+ ],
+ header_libs: ["libxsdc-utils"],
+ shared_libs: [
+ "libbase",
+ ],
+ data: ["resources/*.xml"],
+ test_suites: ["general-tests"],
+}
diff --git a/tests/main.cpp b/tests/main.cpp
index 4dbf2d0..5e91e2d 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,311 +14,7 @@
* limitations under the License.
*/
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <optional>
-
-#include <android-base/file.h>
#include <gtest/gtest.h>
-#include "nested_type.h"
-#include "purchase_simple.h"
-#include "simple_complex_content.h"
-
-#include "predefined_types.h"
-#include "reference.h"
-#include "simple_type.h"
-#include "attr_group_simple.h"
-#include "group.h"
-
-using namespace std;
-using ::android::base::GetExecutableDirectory;
-
-class XmlTest : public ::testing::Test {
-public:
- virtual void SetUp() override {
- }
- virtual void TearDown() override {
- }
- std::string Resource(const std::string& filename) {
- return GetExecutableDirectory() + "/resources/" + filename;
- }
-};
-
-TEST_F(XmlTest, Simpletype) {
- using namespace simple::type;
- for (const auto v : android::xsdc_enum_range<EnumType>()) {
- EXPECT_NE(v, EnumType::UNKNOWN);
- EXPECT_EQ(stringToEnumType(toString(v)), v);
- }
-
- string file_name = Resource("simple_type.xml");
- SimpleTypes simple = *readSimpleTypes(file_name.c_str());
-
- for (int i = 0; i < simple.getListInt().size(); ++i) {
- EXPECT_EQ(simple.getListInt()[i], i + 1);
- }
- EXPECT_EQ(*simple.getFirstUnionTest(), "100");
- EXPECT_EQ(simple.getYesOrNo()[0], EnumType::YES);
- EXPECT_EQ(simple.getYesOrNo()[1], EnumType::EMPTY);
- ofstream out("old_simple_type.xml");
- write(out, simple);
- SimpleTypes simple2 = *readSimpleTypes("old_simple_type.xml");
- for (int i = 0; i < simple.getListInt().size(); ++i) {
- EXPECT_EQ(simple.getListInt()[i], simple2.getListInt()[i]);
- }
- EXPECT_EQ(*simple.getFirstUnionTest(), *simple2.getFirstUnionTest());
- EXPECT_EQ(simple.getYesOrNo()[0], simple2.getYesOrNo()[0]);
- EXPECT_EQ(simple.getYesOrNo()[1], simple2.getYesOrNo()[1]);
-}
-
-TEST_F(XmlTest, Predefinedtypes) {
- using namespace predefined::types;
- Types type = *read(Resource("predefined_types.xml").c_str());
-
- StringTypes stringTypes = *type.getFirstStringTypes();
- DateTypes dateTypes = *type.getFirstDateTypes();
- NumericTypes numericTypes = *type.getFirstNumericTypes();
- MiscTypes miscTypes = *type.getFirstMiscTypes();
- ListPrimitiveTypes listPrimitiveTypes = *type.getFirstListPrimitiveTypes();
-
- EXPECT_EQ(stringTypes.getString(), "abcd");
- EXPECT_EQ(stringTypes.getToken(), "abcd");
- EXPECT_EQ(stringTypes.getNormalizedString(), "abcd");
- EXPECT_EQ(stringTypes.getLanguage(), "abcd");
- EXPECT_EQ(stringTypes.getEntity(), "abcd");
- EXPECT_EQ(stringTypes.getEntities()[0], "a");
- EXPECT_EQ(stringTypes.getEntities()[1], "b");
- EXPECT_EQ(stringTypes.getEntities()[2], "c");
- EXPECT_EQ(stringTypes.getEntities()[3], "d");
- EXPECT_EQ(stringTypes.getId(), "abcd");
- EXPECT_EQ(stringTypes.getName(), "abcd");
- EXPECT_EQ(stringTypes.getNcname(), "abcd");
- EXPECT_EQ(stringTypes.getNmtoken(), "abcd");
- EXPECT_EQ(stringTypes.getNmtokens()[0], "a");
- EXPECT_EQ(stringTypes.getNmtokens()[1], "b");
- EXPECT_EQ(stringTypes.getNmtokens()[2], "c");
- EXPECT_EQ(stringTypes.getNmtokens()[3], "d");
-
-
- EXPECT_EQ(dateTypes.getDate(), "2018-06-18");
- EXPECT_EQ(dateTypes.getDateTime(), "2018-06-18T21:32:52");
- EXPECT_EQ(dateTypes.getDuration(), "P3M");
- EXPECT_EQ(dateTypes.getGDay(), "---18");
- EXPECT_EQ(dateTypes.getGMonth(), "--06");
- EXPECT_EQ(dateTypes.getGMonthDay(), "--06-18");
- EXPECT_EQ(dateTypes.getGYear(), "2018");
- EXPECT_EQ(dateTypes.getGYearMonth(), "2018-06");
- EXPECT_EQ(dateTypes.getTime(), "21:32:52");
-
- EXPECT_EQ(numericTypes.getDecimal(), 1234.57);
- EXPECT_EQ(numericTypes.getInteger(), 1234567890123456789);
- EXPECT_EQ(numericTypes.get_long(), 9223372036854775807);
- EXPECT_EQ(numericTypes.get_int(), 2147483647);
- EXPECT_EQ(numericTypes.get_short(), 32767);
- EXPECT_EQ((int)numericTypes.getByte(), 127);
- EXPECT_EQ(numericTypes.getNegativeInteger(), -1234);
- EXPECT_EQ(numericTypes.getNonNegativeInteger(), 1234);
- EXPECT_EQ(numericTypes.getPositiveInteger(), 1234);
- EXPECT_EQ(numericTypes.getNonPositiveInteger(), -1234);
- EXPECT_EQ(numericTypes.getUnsignedLong(), 1234);
- EXPECT_EQ(numericTypes.getUnsignedInt(), 1234);
- EXPECT_EQ(numericTypes.getUnsignedShort(), 1234);
- EXPECT_EQ((int)(numericTypes.getUnsignedByte()), 255);
-
- EXPECT_EQ(miscTypes.get_double(), 1234.57);
- EXPECT_EQ(miscTypes.getAnyURI(), "https://www.google.com");
- EXPECT_EQ(miscTypes.getBase64Binary(), "Z29vZ2xl");
- EXPECT_TRUE(miscTypes.getBoolean());
- EXPECT_EQ(miscTypes.getHexBinary(), "016a75cb56d7e7");
- EXPECT_EQ(miscTypes.getQName(), "abcd");
- EXPECT_EQ(miscTypes.getIDREF(), "abcd");
- EXPECT_EQ(miscTypes.getIDREFS()[0], "abcd");
- EXPECT_EQ(miscTypes.getIDREFS()[1], "abcd");
- EXPECT_EQ(miscTypes.getAnyType(), "abcd");
-
- EXPECT_EQ(listPrimitiveTypes.getListInt()[0], -2147483648);
- EXPECT_EQ(listPrimitiveTypes.getListInt()[1], 2147483647);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[0], -32768);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[1], 32767);
- EXPECT_EQ((int)listPrimitiveTypes.getListByte()[0], -128);
- EXPECT_EQ((int)listPrimitiveTypes.getListByte()[1], 127);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], 1234.56);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], 5678.12);
- EXPECT_TRUE(listPrimitiveTypes.getListBoolean()[0]);
- EXPECT_FALSE(listPrimitiveTypes.getListBoolean()[1]);
-
- ofstream out("old_predefined_types.xml");
- write(out, type);
- Types type2 = *read("old_predefined_types.xml");
-
- NumericTypes numericTypes2 = *type.getFirstNumericTypes();
- ListPrimitiveTypes listPrimitiveTypes2 = *type.getFirstListPrimitiveTypes();
-
- EXPECT_EQ(numericTypes.getDecimal(), numericTypes2.getDecimal());
- EXPECT_EQ(numericTypes.getInteger(), numericTypes2.getInteger());
- EXPECT_EQ(numericTypes.get_long(), numericTypes2.get_long());
- EXPECT_EQ(numericTypes.get_int(), numericTypes2.get_int());
- EXPECT_EQ(numericTypes.get_short(), numericTypes2.get_short());
- EXPECT_EQ(numericTypes.getByte(), numericTypes2.getByte());
- EXPECT_EQ(numericTypes.getNegativeInteger(), numericTypes2.getNegativeInteger());
- EXPECT_EQ(numericTypes.getNonNegativeInteger(), numericTypes2.getNonNegativeInteger());
- EXPECT_EQ(numericTypes.getPositiveInteger(), numericTypes2.getPositiveInteger());
- EXPECT_EQ(numericTypes.getNonPositiveInteger(), numericTypes2.getNonPositiveInteger());
- EXPECT_EQ(numericTypes.getUnsignedLong(), numericTypes2.getUnsignedLong());
- EXPECT_EQ(numericTypes.getUnsignedInt(), numericTypes2.getUnsignedInt());
- EXPECT_EQ(numericTypes.getUnsignedShort(), numericTypes2.getUnsignedShort());
- EXPECT_EQ((numericTypes.getUnsignedByte()), numericTypes2.getUnsignedByte());
-
- EXPECT_EQ(listPrimitiveTypes.getListInt()[0], listPrimitiveTypes2.getListInt()[0]);
- EXPECT_EQ(listPrimitiveTypes.getListInt()[1], listPrimitiveTypes2.getListInt()[1]);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[0], listPrimitiveTypes2.getListShort()[0]);
- EXPECT_EQ(listPrimitiveTypes.getListShort()[1], listPrimitiveTypes2.getListShort()[1]);
- EXPECT_EQ(listPrimitiveTypes.getListByte()[0], listPrimitiveTypes2.getListByte()[0]);
- EXPECT_EQ(listPrimitiveTypes.getListByte()[1], listPrimitiveTypes2.getListByte()[1]);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], listPrimitiveTypes2.getListDouble()[0]);
- EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], listPrimitiveTypes2.getListDouble()[1]);
- EXPECT_EQ(listPrimitiveTypes.getListBoolean()[0], listPrimitiveTypes2.getListBoolean()[0]);
- EXPECT_EQ(listPrimitiveTypes.getListBoolean()[1], listPrimitiveTypes2.getListBoolean()[1]);
-}
-
-TEST_F(XmlTest, Nestedtype) {
- using namespace nested::type;
- Employee employee = *read(Resource("nested_type.xml").c_str());
-
- Employee::Address address = *employee.getFirstAddress();
- Employee::Address::Extra extra = *address.getFirstExtra();
-
- EXPECT_EQ((int)employee.getId(), 1);
- EXPECT_EQ(employee.getName(), "Peter");
- EXPECT_EQ(address.getCountry(), "US");
- EXPECT_EQ(address.getState(), "Mountain View");
- EXPECT_EQ(address.getZip(), 3342);
- EXPECT_EQ(extra.getLine1(), "Donga 303-111");
- EXPECT_EQ(extra.getLine2(), "Good Street");
-
- ofstream out("old_nested_type.xml");
- write(out, employee);
-}
-
-TEST_F(XmlTest, Purchasesimple) {
- using namespace purchase::simple;
- PurchaseOrderType orderType = *read(Resource("purchase_simple.xml").c_str());
-
- EXPECT_EQ(orderType.getOrderDate(), "1900-01-01");
-
- EXPECT_EQ(orderType.getShipTo()[0].getName(), "name1");
- EXPECT_EQ(orderType.getShipTo()[0].getStreet(), "street1");
- EXPECT_EQ(orderType.getShipTo()[0].getCity(), "city1");
- EXPECT_EQ(orderType.getShipTo()[0].getState(), "state1");
- EXPECT_EQ(orderType.getShipTo()[0].getZip(), 1);
- EXPECT_EQ(orderType.getShipTo()[0].getCountry(), "US");
- EXPECT_EQ(orderType.getShipTo()[1].getName(), "name2");
- EXPECT_EQ(orderType.getShipTo()[1].getStreet(), "street2");
- EXPECT_EQ(orderType.getShipTo()[1].getCity(), "city2");
- EXPECT_EQ(orderType.getShipTo()[1].getState(), "state2");
- EXPECT_EQ(orderType.getShipTo()[1].getZip(), -7922816251426433759);
- EXPECT_EQ(orderType.getShipTo()[1].getCountry(), "US");
-
- EXPECT_EQ(orderType.getBillTo()[0].getName(), "billName");
- EXPECT_EQ(orderType.getBillTo()[0].getStreet(), "billStreet");
- EXPECT_EQ(orderType.getBillTo()[0].getCity(), "billCity");
- EXPECT_EQ(orderType.getBillTo()[0].getState(), "billState");
- EXPECT_EQ(orderType.getBillTo()[0].getZip(), 1);
- EXPECT_EQ(orderType.getBillTo()[0].getCountry(), "US");
-
- ofstream out("old_purchase_simple.xml");
- write(out, orderType);
-
- PurchaseOrderType orderType2 = *read("old_purchase_simple.xml");
-
- EXPECT_EQ(orderType.getOrderDate(), orderType2.getOrderDate());
-
- EXPECT_EQ(orderType.getShipTo()[0].getName(), orderType2.getShipTo()[0].getName());
- EXPECT_EQ(orderType.getShipTo()[0].getStreet(), orderType2.getShipTo()[0].getStreet());
- EXPECT_EQ(orderType.getShipTo()[0].getCity(), orderType2.getShipTo()[0].getCity());
- EXPECT_EQ(orderType.getShipTo()[0].getState(), orderType2.getShipTo()[0].getState());
- EXPECT_EQ(orderType.getShipTo()[0].getZip(), orderType2.getShipTo()[0].getZip());
- EXPECT_EQ(orderType.getShipTo()[0].getCountry(), orderType2.getShipTo()[0].getCountry());
- EXPECT_EQ(orderType.getShipTo()[1].getName(), orderType2.getShipTo()[1].getName());
- EXPECT_EQ(orderType.getShipTo()[1].getStreet(), orderType2.getShipTo()[1].getStreet());
- EXPECT_EQ(orderType.getShipTo()[1].getCity(), orderType2.getShipTo()[1].getCity());
- EXPECT_EQ(orderType.getShipTo()[1].getState(), orderType2.getShipTo()[1].getState());
- EXPECT_EQ(orderType.getShipTo()[1].getZip(), orderType2.getShipTo()[1].getZip());
- EXPECT_EQ(orderType.getShipTo()[1].getCountry(), orderType2.getShipTo()[1].getCountry());
-
- EXPECT_EQ(orderType.getBillTo()[0].getName(), orderType2.getBillTo()[0].getName());
- EXPECT_EQ(orderType.getBillTo()[0].getStreet(), orderType2.getBillTo()[0].getStreet());
- EXPECT_EQ(orderType.getBillTo()[0].getCity(), orderType2.getBillTo()[0].getCity());
- EXPECT_EQ(orderType.getBillTo()[0].getState(), orderType2.getBillTo()[0].getState());
- EXPECT_EQ(orderType.getBillTo()[0].getZip(), orderType2.getBillTo()[0].getZip());
- EXPECT_EQ(orderType.getBillTo()[0].getCountry(), orderType2.getBillTo()[0].getCountry());
-}
-
-TEST_F(XmlTest, Reference) {
- using namespace reference;
- Class _class = *read(Resource("reference.xml").c_str());
-
- EXPECT_EQ(_class.getStudent()[0], "Sam");
- EXPECT_EQ(_class.getStudent()[1], "Paul");
- EXPECT_EQ(_class.getStudent()[2], "Peter");
-
- ofstream out("old_reference.xml");
- write(out, _class);
-}
-
-TEST_F(XmlTest, Simplecomplexcontent) {
- using namespace simple::complex::content;
- Person person = *readPerson(Resource("simple_complex_content.xml").c_str());
- USAddressP uSAddressP = *person.getFirstUSAddressP();
- KRAddress kRAddress = *person.getFirstKRAddress();
- SubAddress subAddress = *person.getFirstSubAddress();
-
- EXPECT_EQ(person.getName(), "Petr");
-
- EXPECT_EQ(uSAddressP.getName(), "404");
- EXPECT_EQ(uSAddressP.getStreet(), "street fighter");
- EXPECT_EQ(uSAddressP.getCity(), "New York");
- EXPECT_EQ(uSAddressP.getState(), "Washington");
- EXPECT_EQ(uSAddressP.getZipcode(), 323232318329852);
-
- EXPECT_EQ(kRAddress.getName(), "Donga Studio");
- EXPECT_EQ(kRAddress.getStreet(), "Nokdu Street");
- EXPECT_EQ(kRAddress.getCity(), "Seoul");
-
- EXPECT_EQ(subAddress.getChoice1_optional(), "Temp");
-
- ofstream out("old_simple_complex_content.xml");
- write(out, person);
-}
-
-TEST_F(XmlTest, Attrgroupsimple) {
- using namespace attr::group::simple;
- Student student = *read(Resource("attr_group_simple.xml").c_str());
-
- EXPECT_EQ(student.getName(), "Jun");
- EXPECT_EQ(student.getCity(), "Mountain View");
- EXPECT_EQ(student.getState(), "CA");
- EXPECT_EQ(student.getRoad(), "Street 101");
- EXPECT_EQ(student.getList()[0], 1);
- EXPECT_EQ(student.getList()[1], 2);
- EXPECT_EQ(student.getList()[2], 3);
-
- ofstream out("old_attr_group_simple.xml");
- write(out, student);
-}
-
-TEST_F(XmlTest, Group) {
- using namespace group;
- Student student = *read(Resource("group.xml").c_str());
-
- EXPECT_EQ(student.getCity(), "Mountain View");
- EXPECT_EQ(student.getState(), "CA");
- EXPECT_EQ(student.getRoad(), "Street 101");
-
- ofstream out("old_group.xml");
- write(out, student);
-}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/tests/resources/simple_type/Android.bp b/tests/resources/simple_type/Android.bp
index 9bf2a52..b6a681d 100644
--- a/tests/resources/simple_type/Android.bp
+++ b/tests/resources/simple_type/Android.bp
@@ -9,3 +9,19 @@ xsd_config {
package_name: "simple.type",
gen_writer: true,
}
+
+xsd_config {
+ name: "xsdc_simple_type_tests_enums",
+ srcs: ["simple_type.xsd"],
+ package_name: "simple.type",
+ enums_only: true,
+ gen_writer: true,
+}
+
+xsd_config {
+ name: "xsdc_simple_type_tests_parser",
+ srcs: ["simple_type.xsd"],
+ package_name: "simple.type",
+ parser_only: true,
+ gen_writer: true,
+}
diff --git a/tests/simple_type.cpp b/tests/simple_type.cpp
new file mode 100644
index 0000000..5162c6d
--- /dev/null
+++ b/tests/simple_type.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+#include <iostream>
+#include <fstream>
+
+#include <android-base/macros.h>
+
+#include "simple_type.h"
+#include "xmltest.h"
+
+using namespace std;
+
+TEST_F(XmlTest, Simpletype) {
+ using namespace simple::type;
+ for (const auto v : android::xsdc_enum_range<EnumType>()) {
+ EXPECT_NE(v, EnumType::UNKNOWN);
+ EXPECT_EQ(stringToEnumType(toString(v)), v);
+ }
+
+ string file_name = Resource("simple_type.xml");
+ SimpleTypes simple = *readSimpleTypes(file_name.c_str());
+
+ for (int i = 0; i < simple.getListInt().size(); ++i) {
+ EXPECT_EQ(simple.getListInt()[i], i + 1);
+ }
+ EXPECT_EQ(*simple.getFirstUnionTest(), "100");
+ EXPECT_EQ(simple.getYesOrNo()[0], EnumType::YES);
+ EXPECT_EQ(simple.getYesOrNo()[1], EnumType::EMPTY);
+ ofstream out("old_simple_type.xml");
+ write(out, simple);
+ SimpleTypes simple2 = *readSimpleTypes("old_simple_type.xml");
+ for (int i = 0; i < simple.getListInt().size(); ++i) {
+ EXPECT_EQ(simple.getListInt()[i], simple2.getListInt()[i]);
+ }
+ EXPECT_EQ(*simple.getFirstUnionTest(), *simple2.getFirstUnionTest());
+ EXPECT_EQ(simple.getYesOrNo()[0], simple2.getYesOrNo()[0]);
+ EXPECT_EQ(simple.getYesOrNo()[1], simple2.getYesOrNo()[1]);
+}
diff --git a/tests/simple_type_enumsonly.cpp b/tests/simple_type_enumsonly.cpp
new file mode 100644
index 0000000..b083a6c
--- /dev/null
+++ b/tests/simple_type_enumsonly.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+#include <android-base/macros.h>
+
+#include "simple_type_enums.h"
+#include "xmltest.h"
+
+TEST_F(XmlTest, SimpletypeEnumsOnly) {
+ using namespace simple::type;
+ for (const auto v : android::xsdc_enum_range<EnumType>()) {
+ EXPECT_NE(v, EnumType::UNKNOWN);
+ EXPECT_EQ(stringToEnumType(toString(v)), v);
+ }
+}
diff --git a/tests/tests.cpp b/tests/tests.cpp
new file mode 100644
index 0000000..c143f4e
--- /dev/null
+++ b/tests/tests.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <optional>
+
+#include <android-base/macros.h>
+#include <gtest/gtest.h>
+#include "nested_type.h"
+#include "purchase_simple.h"
+#include "simple_complex_content.h"
+
+#include "predefined_types.h"
+#include "reference.h"
+#include "attr_group_simple.h"
+#include "group.h"
+#include "xmltest.h"
+
+using namespace std;
+
+TEST_F(XmlTest, Predefinedtypes) {
+ using namespace predefined::types;
+ Types type = *read(Resource("predefined_types.xml").c_str());
+
+ StringTypes stringTypes = *type.getFirstStringTypes();
+ DateTypes dateTypes = *type.getFirstDateTypes();
+ NumericTypes numericTypes = *type.getFirstNumericTypes();
+ MiscTypes miscTypes = *type.getFirstMiscTypes();
+ ListPrimitiveTypes listPrimitiveTypes = *type.getFirstListPrimitiveTypes();
+
+ EXPECT_EQ(stringTypes.getString(), "abcd");
+ EXPECT_EQ(stringTypes.getToken(), "abcd");
+ EXPECT_EQ(stringTypes.getNormalizedString(), "abcd");
+ EXPECT_EQ(stringTypes.getLanguage(), "abcd");
+ EXPECT_EQ(stringTypes.getEntity(), "abcd");
+ EXPECT_EQ(stringTypes.getEntities()[0], "a");
+ EXPECT_EQ(stringTypes.getEntities()[1], "b");
+ EXPECT_EQ(stringTypes.getEntities()[2], "c");
+ EXPECT_EQ(stringTypes.getEntities()[3], "d");
+ EXPECT_EQ(stringTypes.getId(), "abcd");
+ EXPECT_EQ(stringTypes.getName(), "abcd");
+ EXPECT_EQ(stringTypes.getNcname(), "abcd");
+ EXPECT_EQ(stringTypes.getNmtoken(), "abcd");
+ EXPECT_EQ(stringTypes.getNmtokens()[0], "a");
+ EXPECT_EQ(stringTypes.getNmtokens()[1], "b");
+ EXPECT_EQ(stringTypes.getNmtokens()[2], "c");
+ EXPECT_EQ(stringTypes.getNmtokens()[3], "d");
+
+
+ EXPECT_EQ(dateTypes.getDate(), "2018-06-18");
+ EXPECT_EQ(dateTypes.getDateTime(), "2018-06-18T21:32:52");
+ EXPECT_EQ(dateTypes.getDuration(), "P3M");
+ EXPECT_EQ(dateTypes.getGDay(), "---18");
+ EXPECT_EQ(dateTypes.getGMonth(), "--06");
+ EXPECT_EQ(dateTypes.getGMonthDay(), "--06-18");
+ EXPECT_EQ(dateTypes.getGYear(), "2018");
+ EXPECT_EQ(dateTypes.getGYearMonth(), "2018-06");
+ EXPECT_EQ(dateTypes.getTime(), "21:32:52");
+
+ EXPECT_EQ(numericTypes.getDecimal(), 1234.57);
+ EXPECT_EQ(numericTypes.getInteger(), 1234567890123456789);
+ EXPECT_EQ(numericTypes.get_long(), 9223372036854775807);
+ EXPECT_EQ(numericTypes.get_int(), 2147483647);
+ EXPECT_EQ(numericTypes.get_short(), 32767);
+ EXPECT_EQ((int)numericTypes.getByte(), 127);
+ EXPECT_EQ(numericTypes.getNegativeInteger(), -1234);
+ EXPECT_EQ(numericTypes.getNonNegativeInteger(), 1234);
+ EXPECT_EQ(numericTypes.getPositiveInteger(), 1234);
+ EXPECT_EQ(numericTypes.getNonPositiveInteger(), -1234);
+ EXPECT_EQ(numericTypes.getUnsignedLong(), 1234);
+ EXPECT_EQ(numericTypes.getUnsignedInt(), 1234);
+ EXPECT_EQ(numericTypes.getUnsignedShort(), 1234);
+ EXPECT_EQ((int)(numericTypes.getUnsignedByte()), 255);
+
+ EXPECT_EQ(miscTypes.get_double(), 1234.57);
+ EXPECT_EQ(miscTypes.getAnyURI(), "https://www.google.com");
+ EXPECT_EQ(miscTypes.getBase64Binary(), "Z29vZ2xl");
+ EXPECT_TRUE(miscTypes.getBoolean());
+ EXPECT_EQ(miscTypes.getHexBinary(), "016a75cb56d7e7");
+ EXPECT_EQ(miscTypes.getQName(), "abcd");
+ EXPECT_EQ(miscTypes.getIDREF(), "abcd");
+ EXPECT_EQ(miscTypes.getIDREFS()[0], "abcd");
+ EXPECT_EQ(miscTypes.getIDREFS()[1], "abcd");
+ EXPECT_EQ(miscTypes.getAnyType(), "abcd");
+
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[0], -2147483648);
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[1], 2147483647);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[0], -32768);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[1], 32767);
+ EXPECT_EQ((int)listPrimitiveTypes.getListByte()[0], -128);
+ EXPECT_EQ((int)listPrimitiveTypes.getListByte()[1], 127);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], 1234.56);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], 5678.12);
+ EXPECT_TRUE(listPrimitiveTypes.getListBoolean()[0]);
+ EXPECT_FALSE(listPrimitiveTypes.getListBoolean()[1]);
+
+ ofstream out("old_predefined_types.xml");
+ write(out, type);
+ Types type2 = *read("old_predefined_types.xml");
+
+ NumericTypes numericTypes2 = *type.getFirstNumericTypes();
+ ListPrimitiveTypes listPrimitiveTypes2 = *type.getFirstListPrimitiveTypes();
+
+ EXPECT_EQ(numericTypes.getDecimal(), numericTypes2.getDecimal());
+ EXPECT_EQ(numericTypes.getInteger(), numericTypes2.getInteger());
+ EXPECT_EQ(numericTypes.get_long(), numericTypes2.get_long());
+ EXPECT_EQ(numericTypes.get_int(), numericTypes2.get_int());
+ EXPECT_EQ(numericTypes.get_short(), numericTypes2.get_short());
+ EXPECT_EQ(numericTypes.getByte(), numericTypes2.getByte());
+ EXPECT_EQ(numericTypes.getNegativeInteger(), numericTypes2.getNegativeInteger());
+ EXPECT_EQ(numericTypes.getNonNegativeInteger(), numericTypes2.getNonNegativeInteger());
+ EXPECT_EQ(numericTypes.getPositiveInteger(), numericTypes2.getPositiveInteger());
+ EXPECT_EQ(numericTypes.getNonPositiveInteger(), numericTypes2.getNonPositiveInteger());
+ EXPECT_EQ(numericTypes.getUnsignedLong(), numericTypes2.getUnsignedLong());
+ EXPECT_EQ(numericTypes.getUnsignedInt(), numericTypes2.getUnsignedInt());
+ EXPECT_EQ(numericTypes.getUnsignedShort(), numericTypes2.getUnsignedShort());
+ EXPECT_EQ((numericTypes.getUnsignedByte()), numericTypes2.getUnsignedByte());
+
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[0], listPrimitiveTypes2.getListInt()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListInt()[1], listPrimitiveTypes2.getListInt()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[0], listPrimitiveTypes2.getListShort()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListShort()[1], listPrimitiveTypes2.getListShort()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListByte()[0], listPrimitiveTypes2.getListByte()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListByte()[1], listPrimitiveTypes2.getListByte()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[0], listPrimitiveTypes2.getListDouble()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListDouble()[1], listPrimitiveTypes2.getListDouble()[1]);
+ EXPECT_EQ(listPrimitiveTypes.getListBoolean()[0], listPrimitiveTypes2.getListBoolean()[0]);
+ EXPECT_EQ(listPrimitiveTypes.getListBoolean()[1], listPrimitiveTypes2.getListBoolean()[1]);
+}
+
+TEST_F(XmlTest, Nestedtype) {
+ using namespace nested::type;
+ Employee employee = *read(Resource("nested_type.xml").c_str());
+
+ Employee::Address address = *employee.getFirstAddress();
+ Employee::Address::Extra extra = *address.getFirstExtra();
+
+ EXPECT_EQ((int)employee.getId(), 1);
+ EXPECT_EQ(employee.getName(), "Peter");
+ EXPECT_EQ(address.getCountry(), "US");
+ EXPECT_EQ(address.getState(), "Mountain View");
+ EXPECT_EQ(address.getZip(), 3342);
+ EXPECT_EQ(extra.getLine1(), "Donga 303-111");
+ EXPECT_EQ(extra.getLine2(), "Good Street");
+
+ ofstream out("old_nested_type.xml");
+ write(out, employee);
+}
+
+TEST_F(XmlTest, Purchasesimple) {
+ using namespace purchase::simple;
+ PurchaseOrderType orderType = *read(Resource("purchase_simple.xml").c_str());
+
+ EXPECT_EQ(orderType.getOrderDate(), "1900-01-01");
+
+ EXPECT_EQ(orderType.getShipTo()[0].getName(), "name1");
+ EXPECT_EQ(orderType.getShipTo()[0].getStreet(), "street1");
+ EXPECT_EQ(orderType.getShipTo()[0].getCity(), "city1");
+ EXPECT_EQ(orderType.getShipTo()[0].getState(), "state1");
+ EXPECT_EQ(orderType.getShipTo()[0].getZip(), 1);
+ EXPECT_EQ(orderType.getShipTo()[0].getCountry(), "US");
+ EXPECT_EQ(orderType.getShipTo()[1].getName(), "name2");
+ EXPECT_EQ(orderType.getShipTo()[1].getStreet(), "street2");
+ EXPECT_EQ(orderType.getShipTo()[1].getCity(), "city2");
+ EXPECT_EQ(orderType.getShipTo()[1].getState(), "state2");
+ EXPECT_EQ(orderType.getShipTo()[1].getZip(), -7922816251426433759);
+ EXPECT_EQ(orderType.getShipTo()[1].getCountry(), "US");
+
+ EXPECT_EQ(orderType.getBillTo()[0].getName(), "billName");
+ EXPECT_EQ(orderType.getBillTo()[0].getStreet(), "billStreet");
+ EXPECT_EQ(orderType.getBillTo()[0].getCity(), "billCity");
+ EXPECT_EQ(orderType.getBillTo()[0].getState(), "billState");
+ EXPECT_EQ(orderType.getBillTo()[0].getZip(), 1);
+ EXPECT_EQ(orderType.getBillTo()[0].getCountry(), "US");
+
+ ofstream out("old_purchase_simple.xml");
+ write(out, orderType);
+
+ PurchaseOrderType orderType2 = *read("old_purchase_simple.xml");
+
+ EXPECT_EQ(orderType.getOrderDate(), orderType2.getOrderDate());
+
+ EXPECT_EQ(orderType.getShipTo()[0].getName(), orderType2.getShipTo()[0].getName());
+ EXPECT_EQ(orderType.getShipTo()[0].getStreet(), orderType2.getShipTo()[0].getStreet());
+ EXPECT_EQ(orderType.getShipTo()[0].getCity(), orderType2.getShipTo()[0].getCity());
+ EXPECT_EQ(orderType.getShipTo()[0].getState(), orderType2.getShipTo()[0].getState());
+ EXPECT_EQ(orderType.getShipTo()[0].getZip(), orderType2.getShipTo()[0].getZip());
+ EXPECT_EQ(orderType.getShipTo()[0].getCountry(), orderType2.getShipTo()[0].getCountry());
+ EXPECT_EQ(orderType.getShipTo()[1].getName(), orderType2.getShipTo()[1].getName());
+ EXPECT_EQ(orderType.getShipTo()[1].getStreet(), orderType2.getShipTo()[1].getStreet());
+ EXPECT_EQ(orderType.getShipTo()[1].getCity(), orderType2.getShipTo()[1].getCity());
+ EXPECT_EQ(orderType.getShipTo()[1].getState(), orderType2.getShipTo()[1].getState());
+ EXPECT_EQ(orderType.getShipTo()[1].getZip(), orderType2.getShipTo()[1].getZip());
+ EXPECT_EQ(orderType.getShipTo()[1].getCountry(), orderType2.getShipTo()[1].getCountry());
+
+ EXPECT_EQ(orderType.getBillTo()[0].getName(), orderType2.getBillTo()[0].getName());
+ EXPECT_EQ(orderType.getBillTo()[0].getStreet(), orderType2.getBillTo()[0].getStreet());
+ EXPECT_EQ(orderType.getBillTo()[0].getCity(), orderType2.getBillTo()[0].getCity());
+ EXPECT_EQ(orderType.getBillTo()[0].getState(), orderType2.getBillTo()[0].getState());
+ EXPECT_EQ(orderType.getBillTo()[0].getZip(), orderType2.getBillTo()[0].getZip());
+ EXPECT_EQ(orderType.getBillTo()[0].getCountry(), orderType2.getBillTo()[0].getCountry());
+}
+
+TEST_F(XmlTest, Reference) {
+ using namespace reference;
+ Class _class = *read(Resource("reference.xml").c_str());
+
+ EXPECT_EQ(_class.getStudent()[0], "Sam");
+ EXPECT_EQ(_class.getStudent()[1], "Paul");
+ EXPECT_EQ(_class.getStudent()[2], "Peter");
+
+ ofstream out("old_reference.xml");
+ write(out, _class);
+}
+
+TEST_F(XmlTest, Simplecomplexcontent) {
+ using namespace simple::complex::content;
+ Person person = *readPerson(Resource("simple_complex_content.xml").c_str());
+ USAddressP uSAddressP = *person.getFirstUSAddressP();
+ KRAddress kRAddress = *person.getFirstKRAddress();
+ SubAddress subAddress = *person.getFirstSubAddress();
+
+ EXPECT_EQ(person.getName(), "Petr");
+
+ EXPECT_EQ(uSAddressP.getName(), "404");
+ EXPECT_EQ(uSAddressP.getStreet(), "street fighter");
+ EXPECT_EQ(uSAddressP.getCity(), "New York");
+ EXPECT_EQ(uSAddressP.getState(), "Washington");
+ EXPECT_EQ(uSAddressP.getZipcode(), 323232318329852);
+
+ EXPECT_EQ(kRAddress.getName(), "Donga Studio");
+ EXPECT_EQ(kRAddress.getStreet(), "Nokdu Street");
+ EXPECT_EQ(kRAddress.getCity(), "Seoul");
+
+ EXPECT_EQ(subAddress.getChoice1_optional(), "Temp");
+
+ ofstream out("old_simple_complex_content.xml");
+ write(out, person);
+}
+
+TEST_F(XmlTest, Attrgroupsimple) {
+ using namespace attr::group::simple;
+ Student student = *read(Resource("attr_group_simple.xml").c_str());
+
+ EXPECT_EQ(student.getName(), "Jun");
+ EXPECT_EQ(student.getCity(), "Mountain View");
+ EXPECT_EQ(student.getState(), "CA");
+ EXPECT_EQ(student.getRoad(), "Street 101");
+ EXPECT_EQ(student.getList()[0], 1);
+ EXPECT_EQ(student.getList()[1], 2);
+ EXPECT_EQ(student.getList()[2], 3);
+
+ ofstream out("old_attr_group_simple.xml");
+ write(out, student);
+}
+
+TEST_F(XmlTest, Group) {
+ using namespace group;
+ Student student = *read(Resource("group.xml").c_str());
+
+ EXPECT_EQ(student.getCity(), "Mountain View");
+ EXPECT_EQ(student.getState(), "CA");
+ EXPECT_EQ(student.getRoad(), "Street 101");
+
+ ofstream out("old_group.xml");
+ write(out, student);
+}
diff --git a/tests/xmltest.h b/tests/xmltest.h
new file mode 100644
index 0000000..b645b98
--- /dev/null
+++ b/tests/xmltest.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed 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.
+ */
+
+#pragma once
+
+#include <string>
+
+#include <android-base/file.h>
+#include <gtest/gtest.h>
+
+class XmlTest : public ::testing::Test {
+public:
+ std::string Resource(const std::string& filename) {
+ return ::android::base::GetExecutableDirectory() + "/resources/" + filename;
+ }
+};