Message ID | 20220425144617.2549778-3-hanlinchen@chromium.org |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi Han-Lin, Thank you for the patch. On Mon, Apr 25, 2022 at 10:46:16PM +0800, Han-Lin Chen via libcamera-devel wrote: > Add a unit test to exercise the API of the YamlParser class. > > Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org> > --- > test/meson.build | 1 + > test/yaml-parser.cpp | 496 +++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 497 insertions(+) > create mode 100644 test/yaml-parser.cpp > > diff --git a/test/meson.build b/test/meson.build > index fd4c5ca0..9c68fae1 100644 > --- a/test/meson.build > +++ b/test/meson.build > @@ -54,6 +54,7 @@ internal_tests = [ > ['timer-thread', 'timer-thread.cpp'], > ['unique-fd', 'unique-fd.cpp'], > ['utils', 'utils.cpp'], > + ['yaml-parser', 'yaml-parser.cpp'], > ] > > internal_non_parallel_tests = [ > diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp > new file mode 100644 > index 00000000..b9122287 > --- /dev/null > +++ b/test/yaml-parser.cpp > @@ -0,0 +1,496 @@ > +/* SPDX-License-Identifier: GPL-2.0-or-later */ > +/* > + * Copyright (C) 2022, Google Inc. > + * > + * yaml-parser.cpp - YAML parser operations tests > + */ > + > +#include <iostream> > +#include <string> > +#include <unistd.h> > + > +#include <libcamera/internal/yaml_parser.h> > + > +#include "test.h" > + > +using namespace std; > +using namespace libcamera; Alphabetically sorted please. > + > +static const string testYaml = > + "string: libcamera\n" > + "double: 3.14159\n" > + "uint32_t: 100\n" > + "int32_t: -100\n" > + "size: [1920, 1080]\n" > + "list:\n" > + " - James\n" > + " - Mary\n" > + "dictionary:\n" > + " a: 1\n" > + " b: 2\n" > + " c: 3\n" > + "level1:\n" > + " level2:\n" > + " - [1, 2]\n" > + " - {one: 1, two: 2}\n"; > + > +static const string invalidYaml = > + "Invalid : - YAML : - Content"; > + > +class YamlParserTest : public Test > +{ > +protected: > + bool createFile(const string &content, string &filename) > + { > + filename = "/tmp/libcamera.test.XXXXXX"; > + int fd = mkstemp(&filename.front()); > + if (fd == -1) > + return false; > + > + FILE *fh = fdopen(fd, "w"); > + fputs(content.c_str(), fh); > + > + fclose(fh); > + > + return true; > + } > + > + int init() > + { > + if (!createFile(testYaml, testYamlFile_)) > + return TestFail; > + > + if (!createFile(invalidYaml, invalidYamlFile_)) > + return TestFail; > + > + return TestPass; > + } > + > + int run() > + { > + /* Test invalid YAML file */ > + FILE *fh = fopen(invalidYamlFile_.c_str(), "r"); > + if (!fh) { > + cerr << "Fail to open invalid YAML file"; Missing std::endl at the end of the line. Same below. > + return TestFail; > + } > + > + std::unique_ptr<YamlObject> root = YamlParser::parse(fh); > + > + if (root) { > + cerr << "Invalid YAML file parse successfully"; > + return TestFail; > + } > + > + fclose(fh); You can move this right after parse(). Same below. > + > + /* Test YAML file */ > + fh = fopen(testYamlFile_.c_str(), "r"); > + if (!fh) { > + cerr << "Fail to open test YAML file"; > + return TestFail; > + } > + > + root = YamlParser::parse(fh); > + > + if (!root) { > + cerr << "Fail to parse test YAML file: "; > + return TestFail; > + } > + > + fclose(fh); > + > + if (!(*root).isDictionary()) { if (!root->isDictionary()) { is more readable. Same below. > + cerr << "YAML root is not dictionary"; > + return TestFail; > + } > + > + if (!(*root).contains("string")) { > + cerr << "Missing string object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("double")) { > + cerr << "Missing double object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("int32_t")) { > + cerr << "Missing int32_t object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("uint32_t")) { > + cerr << "Missing uint32_t object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("size")) { > + cerr << "Missing Size object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("list")) { > + cerr << "Missing list object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("dictionary")) { > + cerr << "Missing dictionary object in YAML root"; > + return TestFail; > + } > + > + if (!(*root).contains("level1")) { > + cerr << "Missing leveled object in YAML root"; > + return TestFail; > + } > + > + /* Test string object */ > + bool ok; > + auto &strObj = (*root)["string"]; > + > + if (strObj.isDictionary()) { > + cerr << "String object parse as Dictionary"; > + return TestFail; > + } > + > + if (strObj.isList()) { > + cerr << "String object parse as List"; > + return TestFail; > + } > + > + if (strObj.get<string>("", &ok) != "libcamera" || !ok) { > + cerr << "String object parse as wrong content"; > + return TestFail; > + } > + > + if (strObj.get<int32_t>(-1, &ok) != -1 || ok) { > + cerr << "String object parse as integer"; > + return TestFail; > + } > + > + if (strObj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "String object parse as unsigned integer"; > + return TestFail; > + } > + > + if (strObj.get<double>(1.0, &ok) != 1.0 || ok) { > + cerr << "String object parse as double"; > + return TestFail; > + } > + > + if (strObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "String object parse as Size"; > + return TestFail; > + } > + > + /* Test int32_t object */ > + auto &int32Obj = (*root)["int32_t"]; > + > + if (int32Obj.isDictionary()) { > + cerr << "Integer object parse as Dictionary"; > + return TestFail; > + } > + > + if (int32Obj.isList()) { > + cerr << "Integer object parse as Integer"; > + return TestFail; > + } > + > + if (int32Obj.get<int32_t>(-100, &ok) != -100 || !ok) { > + cerr << "Integer object parse as wrong value"; > + return TestFail; > + } > + > + if (int32Obj.get<string>("", &ok) != "-100" || !ok) { > + cerr << "Integer object fail to parse as string"; > + return TestFail; > + } > + > + if (int32Obj.get<double>(1.0, &ok) != -100.0 || !ok) { > + cerr << "Integer object fail to parse as double"; > + return TestFail; > + } > + > + if (int32Obj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "Negative integer object parse as unsigned integer"; > + return TestFail; > + } > + > + if (int32Obj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "Integer object parse as Size"; > + return TestFail; > + } > + > + /* Test uint32_t object */ > + auto &uint32Obj = (*root)["uint32_t"]; > + > + if (uint32Obj.isDictionary()) { > + cerr << "Unsigned integer object parse as Dictionary"; > + return TestFail; > + } > + > + if (uint32Obj.isList()) { > + cerr << "Unsigned integer object parse as List"; > + return TestFail; > + } > + > + if (uint32Obj.get<int32_t>(-1, &ok) != 100 || !ok) { > + cerr << "Unsigned integer object fail to parse as integer"; > + return TestFail; > + } > + > + if (uint32Obj.get<string>("", &ok) != "100" || !ok) { > + cerr << "Unsigned integer object fail to parse as string"; > + return TestFail; > + } > + > + if (uint32Obj.get<double>(1.0, &ok) != 100.0 || !ok) { > + cerr << "Unsigned integer object fail to parse as double"; > + return TestFail; > + } > + > + if (uint32Obj.get<uint32_t>(100, &ok) != 100 || !ok) { > + cerr << "Unsigned integer object parsed as wrong value"; > + return TestFail; > + } > + > + if (uint32Obj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "Unsigned integer object parsed as Size"; > + return TestFail; > + } > + > + /* Test double value */ > + auto &doubleObj = (*root)["double"]; > + > + if (doubleObj.isDictionary()) { > + cerr << "Double object parse as Dictionary"; > + return TestFail; > + } > + > + if (doubleObj.isList()) { > + cerr << "Double object parse as List"; > + return TestFail; > + } > + > + if (doubleObj.get<string>("", &ok) != "3.14159" || !ok) { > + cerr << "Double object fail to parse as string"; > + return TestFail; > + } > + > + if (doubleObj.get<double>(1.0, &ok) != 3.14159 || !ok) { > + cerr << "Double object parse as wrong value"; > + return TestFail; > + } > + > + if (doubleObj.get<int32_t>(-1, &ok) != -1 || ok) { > + cerr << "Double object parse as integer"; > + return TestFail; > + } > + > + if (doubleObj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "Double object parse as unsigned integer"; > + return TestFail; > + } > + > + if (doubleObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "Double object parse as Size"; > + return TestFail; > + } > + > + /* Test Size value */ > + auto &sizeObj = (*root)["size"]; > + > + if (sizeObj.isDictionary()) { > + cerr << "Size object parse as Dictionary"; > + return TestFail; > + } > + > + if (!sizeObj.isList()) { > + cerr << "Size object parse as List"; > + return TestFail; > + } > + > + if (sizeObj.get<string>("", &ok) != "" || ok) { > + cerr << "Size object parse as string"; > + return TestFail; > + } > + > + if (sizeObj.get<double>(1.0, &ok) != 1.0 || ok) { > + cerr << "Size object parse as double"; > + return TestFail; > + } > + > + if (sizeObj.get<int32_t>(-1, &ok) != -1 || ok) { > + cerr << "Size object parse as integer"; > + return TestFail; > + } > + > + if (sizeObj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "Size object parse as unsigned integer"; > + return TestFail; > + } > + > + if (sizeObj.get<Size>(Size(0, 0), &ok) != Size(1920, 1080) || !ok) { > + cerr << "Size object parse as wrong value"; > + return TestFail; > + } > + > + /* Test list object */ > + auto &listObj = (*root)["list"]; > + > + if (listObj.isDictionary()) { > + cerr << "List object parse as Dictionary"; > + return TestFail; > + } > + > + if (!listObj.isList()) { > + cerr << "List object fail to parse as List"; > + return TestFail; > + } > + > + if (listObj.get<string>("", &ok) != "" || ok) { > + cerr << "List object parse as string"; > + return TestFail; > + } > + > + if (listObj.get<double>(1.0, &ok) != 1.0 || ok) { > + cerr << "List object parse as double"; > + return TestFail; > + } > + > + if (listObj.get<int32_t>(-1, &ok) != -1 || ok) { > + cerr << "List object parse as integer"; > + return TestFail; > + } > + > + if (listObj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "List object parse as unsigne integer"; > + return TestFail; > + } > + > + if (listObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "String list object parse as Size"; > + return TestFail; > + } > + > + if (listObj.size() > 2) { > + cerr << "List object parse with wrong size"; > + return TestFail; > + } > + > + if (listObj[0].get<string>("") != "James" || > + listObj[1].get<string>("") != "Mary") { > + cerr << "List object parse as wrong value"; > + return TestFail; > + } > + > + /* Test dictionary object */ > + auto &dictObj = (*root)["dictionary"]; > + > + if (!dictObj.isDictionary()) { > + cerr << "Dictionary object fail to parse as Dictionary"; > + return TestFail; > + } > + > + if (dictObj.isList()) { > + cerr << "Dictionary object parse as List"; > + return TestFail; > + } > + > + if (dictObj.get<string>("", &ok) != "" || ok) { > + cerr << "Dictionary object parse as string"; > + return TestFail; > + } > + > + if (dictObj.get<double>(1.0, &ok) != 1.0 || ok) { > + cerr << "Dictionary object parse as double"; > + return TestFail; > + } > + > + if (dictObj.get<int32_t>(-1, &ok) != -1 || ok) { > + cerr << "Dictionary object parse as integer"; > + return TestFail; > + } > + > + if (dictObj.get<uint32_t>(1, &ok) != 1 || ok) { > + cerr << "Dictionary object parse as unsigned integer"; > + return TestFail; > + } > + > + if (dictObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { > + cerr << "Dictionary object parse as Size"; > + return TestFail; > + } > + > + auto memeberNames = dictObj.getMemberNames(); > + sort(memeberNames.begin(), memeberNames.end()); > + > + if (memeberNames.size() != 3) { > + cerr << "Dictionary object fail to extra member names"; > + return TestFail; > + } > + > + if (memeberNames[0] != "a" || > + memeberNames[1] != "b" || > + memeberNames[2] != "c") { > + cerr << "Dictionary object fail to parse member names"; > + return TestFail; > + } > + > + if (dictObj["a"].get<int32_t>(0) != 1 || > + dictObj["b"].get<int32_t>(0) != 2 || > + dictObj["c"].get<int32_t>(0) != 3) { > + cerr << "Dictionary object fail to parse member value"; > + return TestFail; > + } > + > + /* Test leveled objects */ > + auto &level1Obj = (*root)["level1"]; > + > + if (!level1Obj.isDictionary()) { > + cerr << "level1 object fail to parse as Dictionary"; > + return TestFail; > + } > + > + auto &level2Obj = level1Obj["level2"]; > + > + if (!level2Obj.isList() || level2Obj.size() != 2) { > + cerr << "level2 object should be 2 element list"; > + return TestFail; > + } > + > + auto &firstElement = level2Obj[0]; > + if (!firstElement.isList() || > + firstElement.size() != 2 || > + firstElement[0].get<int32_t>(0) != 1 || > + firstElement[1].get<int32_t>(0) != 2) { > + cerr << "The first element of level2 object fail to pars as integer list"; s/pars/parse/ > + return TestFail; > + } > + > + auto &secondElement = level2Obj[1]; > + if (!secondElement.isDictionary() || > + !secondElement.contains("one") || > + !secondElement.contains("two") || > + secondElement["one"].get<int32_t>(0) != 1 || > + secondElement["two"].get<int32_t>(0) != 2) { > + cerr << "The second element of level2 object fail to pases as dictionary"; s/pases/parse/ Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > + return TestFail; > + } > + > + return TestPass; > + } > + > + void cleanup() > + { > + unlink(testYamlFile_.c_str()); > + unlink(invalidYamlFile_.c_str()); > + } > + > +private: > + std::string testYamlFile_; > + std::string invalidYamlFile_; > +}; > + > +TEST_REGISTER(YamlParserTest)
diff --git a/test/meson.build b/test/meson.build index fd4c5ca0..9c68fae1 100644 --- a/test/meson.build +++ b/test/meson.build @@ -54,6 +54,7 @@ internal_tests = [ ['timer-thread', 'timer-thread.cpp'], ['unique-fd', 'unique-fd.cpp'], ['utils', 'utils.cpp'], + ['yaml-parser', 'yaml-parser.cpp'], ] internal_non_parallel_tests = [ diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp new file mode 100644 index 00000000..b9122287 --- /dev/null +++ b/test/yaml-parser.cpp @@ -0,0 +1,496 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Google Inc. + * + * yaml-parser.cpp - YAML parser operations tests + */ + +#include <iostream> +#include <string> +#include <unistd.h> + +#include <libcamera/internal/yaml_parser.h> + +#include "test.h" + +using namespace std; +using namespace libcamera; + +static const string testYaml = + "string: libcamera\n" + "double: 3.14159\n" + "uint32_t: 100\n" + "int32_t: -100\n" + "size: [1920, 1080]\n" + "list:\n" + " - James\n" + " - Mary\n" + "dictionary:\n" + " a: 1\n" + " b: 2\n" + " c: 3\n" + "level1:\n" + " level2:\n" + " - [1, 2]\n" + " - {one: 1, two: 2}\n"; + +static const string invalidYaml = + "Invalid : - YAML : - Content"; + +class YamlParserTest : public Test +{ +protected: + bool createFile(const string &content, string &filename) + { + filename = "/tmp/libcamera.test.XXXXXX"; + int fd = mkstemp(&filename.front()); + if (fd == -1) + return false; + + FILE *fh = fdopen(fd, "w"); + fputs(content.c_str(), fh); + + fclose(fh); + + return true; + } + + int init() + { + if (!createFile(testYaml, testYamlFile_)) + return TestFail; + + if (!createFile(invalidYaml, invalidYamlFile_)) + return TestFail; + + return TestPass; + } + + int run() + { + /* Test invalid YAML file */ + FILE *fh = fopen(invalidYamlFile_.c_str(), "r"); + if (!fh) { + cerr << "Fail to open invalid YAML file"; + return TestFail; + } + + std::unique_ptr<YamlObject> root = YamlParser::parse(fh); + + if (root) { + cerr << "Invalid YAML file parse successfully"; + return TestFail; + } + + fclose(fh); + + /* Test YAML file */ + fh = fopen(testYamlFile_.c_str(), "r"); + if (!fh) { + cerr << "Fail to open test YAML file"; + return TestFail; + } + + root = YamlParser::parse(fh); + + if (!root) { + cerr << "Fail to parse test YAML file: "; + return TestFail; + } + + fclose(fh); + + if (!(*root).isDictionary()) { + cerr << "YAML root is not dictionary"; + return TestFail; + } + + if (!(*root).contains("string")) { + cerr << "Missing string object in YAML root"; + return TestFail; + } + + if (!(*root).contains("double")) { + cerr << "Missing double object in YAML root"; + return TestFail; + } + + if (!(*root).contains("int32_t")) { + cerr << "Missing int32_t object in YAML root"; + return TestFail; + } + + if (!(*root).contains("uint32_t")) { + cerr << "Missing uint32_t object in YAML root"; + return TestFail; + } + + if (!(*root).contains("size")) { + cerr << "Missing Size object in YAML root"; + return TestFail; + } + + if (!(*root).contains("list")) { + cerr << "Missing list object in YAML root"; + return TestFail; + } + + if (!(*root).contains("dictionary")) { + cerr << "Missing dictionary object in YAML root"; + return TestFail; + } + + if (!(*root).contains("level1")) { + cerr << "Missing leveled object in YAML root"; + return TestFail; + } + + /* Test string object */ + bool ok; + auto &strObj = (*root)["string"]; + + if (strObj.isDictionary()) { + cerr << "String object parse as Dictionary"; + return TestFail; + } + + if (strObj.isList()) { + cerr << "String object parse as List"; + return TestFail; + } + + if (strObj.get<string>("", &ok) != "libcamera" || !ok) { + cerr << "String object parse as wrong content"; + return TestFail; + } + + if (strObj.get<int32_t>(-1, &ok) != -1 || ok) { + cerr << "String object parse as integer"; + return TestFail; + } + + if (strObj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "String object parse as unsigned integer"; + return TestFail; + } + + if (strObj.get<double>(1.0, &ok) != 1.0 || ok) { + cerr << "String object parse as double"; + return TestFail; + } + + if (strObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "String object parse as Size"; + return TestFail; + } + + /* Test int32_t object */ + auto &int32Obj = (*root)["int32_t"]; + + if (int32Obj.isDictionary()) { + cerr << "Integer object parse as Dictionary"; + return TestFail; + } + + if (int32Obj.isList()) { + cerr << "Integer object parse as Integer"; + return TestFail; + } + + if (int32Obj.get<int32_t>(-100, &ok) != -100 || !ok) { + cerr << "Integer object parse as wrong value"; + return TestFail; + } + + if (int32Obj.get<string>("", &ok) != "-100" || !ok) { + cerr << "Integer object fail to parse as string"; + return TestFail; + } + + if (int32Obj.get<double>(1.0, &ok) != -100.0 || !ok) { + cerr << "Integer object fail to parse as double"; + return TestFail; + } + + if (int32Obj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "Negative integer object parse as unsigned integer"; + return TestFail; + } + + if (int32Obj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "Integer object parse as Size"; + return TestFail; + } + + /* Test uint32_t object */ + auto &uint32Obj = (*root)["uint32_t"]; + + if (uint32Obj.isDictionary()) { + cerr << "Unsigned integer object parse as Dictionary"; + return TestFail; + } + + if (uint32Obj.isList()) { + cerr << "Unsigned integer object parse as List"; + return TestFail; + } + + if (uint32Obj.get<int32_t>(-1, &ok) != 100 || !ok) { + cerr << "Unsigned integer object fail to parse as integer"; + return TestFail; + } + + if (uint32Obj.get<string>("", &ok) != "100" || !ok) { + cerr << "Unsigned integer object fail to parse as string"; + return TestFail; + } + + if (uint32Obj.get<double>(1.0, &ok) != 100.0 || !ok) { + cerr << "Unsigned integer object fail to parse as double"; + return TestFail; + } + + if (uint32Obj.get<uint32_t>(100, &ok) != 100 || !ok) { + cerr << "Unsigned integer object parsed as wrong value"; + return TestFail; + } + + if (uint32Obj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "Unsigned integer object parsed as Size"; + return TestFail; + } + + /* Test double value */ + auto &doubleObj = (*root)["double"]; + + if (doubleObj.isDictionary()) { + cerr << "Double object parse as Dictionary"; + return TestFail; + } + + if (doubleObj.isList()) { + cerr << "Double object parse as List"; + return TestFail; + } + + if (doubleObj.get<string>("", &ok) != "3.14159" || !ok) { + cerr << "Double object fail to parse as string"; + return TestFail; + } + + if (doubleObj.get<double>(1.0, &ok) != 3.14159 || !ok) { + cerr << "Double object parse as wrong value"; + return TestFail; + } + + if (doubleObj.get<int32_t>(-1, &ok) != -1 || ok) { + cerr << "Double object parse as integer"; + return TestFail; + } + + if (doubleObj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "Double object parse as unsigned integer"; + return TestFail; + } + + if (doubleObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "Double object parse as Size"; + return TestFail; + } + + /* Test Size value */ + auto &sizeObj = (*root)["size"]; + + if (sizeObj.isDictionary()) { + cerr << "Size object parse as Dictionary"; + return TestFail; + } + + if (!sizeObj.isList()) { + cerr << "Size object parse as List"; + return TestFail; + } + + if (sizeObj.get<string>("", &ok) != "" || ok) { + cerr << "Size object parse as string"; + return TestFail; + } + + if (sizeObj.get<double>(1.0, &ok) != 1.0 || ok) { + cerr << "Size object parse as double"; + return TestFail; + } + + if (sizeObj.get<int32_t>(-1, &ok) != -1 || ok) { + cerr << "Size object parse as integer"; + return TestFail; + } + + if (sizeObj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "Size object parse as unsigned integer"; + return TestFail; + } + + if (sizeObj.get<Size>(Size(0, 0), &ok) != Size(1920, 1080) || !ok) { + cerr << "Size object parse as wrong value"; + return TestFail; + } + + /* Test list object */ + auto &listObj = (*root)["list"]; + + if (listObj.isDictionary()) { + cerr << "List object parse as Dictionary"; + return TestFail; + } + + if (!listObj.isList()) { + cerr << "List object fail to parse as List"; + return TestFail; + } + + if (listObj.get<string>("", &ok) != "" || ok) { + cerr << "List object parse as string"; + return TestFail; + } + + if (listObj.get<double>(1.0, &ok) != 1.0 || ok) { + cerr << "List object parse as double"; + return TestFail; + } + + if (listObj.get<int32_t>(-1, &ok) != -1 || ok) { + cerr << "List object parse as integer"; + return TestFail; + } + + if (listObj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "List object parse as unsigne integer"; + return TestFail; + } + + if (listObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "String list object parse as Size"; + return TestFail; + } + + if (listObj.size() > 2) { + cerr << "List object parse with wrong size"; + return TestFail; + } + + if (listObj[0].get<string>("") != "James" || + listObj[1].get<string>("") != "Mary") { + cerr << "List object parse as wrong value"; + return TestFail; + } + + /* Test dictionary object */ + auto &dictObj = (*root)["dictionary"]; + + if (!dictObj.isDictionary()) { + cerr << "Dictionary object fail to parse as Dictionary"; + return TestFail; + } + + if (dictObj.isList()) { + cerr << "Dictionary object parse as List"; + return TestFail; + } + + if (dictObj.get<string>("", &ok) != "" || ok) { + cerr << "Dictionary object parse as string"; + return TestFail; + } + + if (dictObj.get<double>(1.0, &ok) != 1.0 || ok) { + cerr << "Dictionary object parse as double"; + return TestFail; + } + + if (dictObj.get<int32_t>(-1, &ok) != -1 || ok) { + cerr << "Dictionary object parse as integer"; + return TestFail; + } + + if (dictObj.get<uint32_t>(1, &ok) != 1 || ok) { + cerr << "Dictionary object parse as unsigned integer"; + return TestFail; + } + + if (dictObj.get<Size>(Size(0, 0), &ok) != Size(0, 0) || ok) { + cerr << "Dictionary object parse as Size"; + return TestFail; + } + + auto memeberNames = dictObj.getMemberNames(); + sort(memeberNames.begin(), memeberNames.end()); + + if (memeberNames.size() != 3) { + cerr << "Dictionary object fail to extra member names"; + return TestFail; + } + + if (memeberNames[0] != "a" || + memeberNames[1] != "b" || + memeberNames[2] != "c") { + cerr << "Dictionary object fail to parse member names"; + return TestFail; + } + + if (dictObj["a"].get<int32_t>(0) != 1 || + dictObj["b"].get<int32_t>(0) != 2 || + dictObj["c"].get<int32_t>(0) != 3) { + cerr << "Dictionary object fail to parse member value"; + return TestFail; + } + + /* Test leveled objects */ + auto &level1Obj = (*root)["level1"]; + + if (!level1Obj.isDictionary()) { + cerr << "level1 object fail to parse as Dictionary"; + return TestFail; + } + + auto &level2Obj = level1Obj["level2"]; + + if (!level2Obj.isList() || level2Obj.size() != 2) { + cerr << "level2 object should be 2 element list"; + return TestFail; + } + + auto &firstElement = level2Obj[0]; + if (!firstElement.isList() || + firstElement.size() != 2 || + firstElement[0].get<int32_t>(0) != 1 || + firstElement[1].get<int32_t>(0) != 2) { + cerr << "The first element of level2 object fail to pars as integer list"; + return TestFail; + } + + auto &secondElement = level2Obj[1]; + if (!secondElement.isDictionary() || + !secondElement.contains("one") || + !secondElement.contains("two") || + secondElement["one"].get<int32_t>(0) != 1 || + secondElement["two"].get<int32_t>(0) != 2) { + cerr << "The second element of level2 object fail to pases as dictionary"; + return TestFail; + } + + return TestPass; + } + + void cleanup() + { + unlink(testYamlFile_.c_str()); + unlink(invalidYamlFile_.c_str()); + } + +private: + std::string testYamlFile_; + std::string invalidYamlFile_; +}; + +TEST_REGISTER(YamlParserTest)
Add a unit test to exercise the API of the YamlParser class. Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org> --- test/meson.build | 1 + test/yaml-parser.cpp | 496 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 497 insertions(+) create mode 100644 test/yaml-parser.cpp