#include "nodetests.h" #include "yaml-cpp/yaml.h" #include #include namespace { struct TEST { TEST(): ok(false) {} TEST(bool ok_): ok(ok_) {} TEST(const char *error_): ok(false), error(error_) {} bool ok; std::string error; }; } #define YAML_ASSERT(cond) do { if(!(cond)) return " Assert failed: " #cond; } while(false) #define YAML_ASSERT_THROWS(cond, exc) do { try { (cond); return " Expression did not throw: " #cond; } catch(const exc&) {} catch(...) { return " Expression threw something other than " #exc ": " #cond; } } while(false) namespace Test { namespace Node { TEST SimpleScalar() { YAML::Node node = YAML::Node("Hello, World!"); YAML_ASSERT(node.IsScalar()); YAML_ASSERT(node.as() == "Hello, World!"); return true; } TEST IntScalar() { YAML::Node node = YAML::Node(15); YAML_ASSERT(node.IsScalar()); YAML_ASSERT(node.as() == 15); return true; } TEST SimpleAppendSequence() { YAML::Node node; node.push_back(10); node.push_back("foo"); node.push_back("monkey"); YAML_ASSERT(node.IsSequence()); YAML_ASSERT(node.size() == 3); YAML_ASSERT(node[0].as() == 10); YAML_ASSERT(node[1].as() == "foo"); YAML_ASSERT(node[2].as() == "monkey"); YAML_ASSERT(node.IsSequence()); return true; } TEST SimpleAssignSequence() { YAML::Node node; node[0] = 10; node[1] = "foo"; node[2] = "monkey"; YAML_ASSERT(node.IsSequence()); YAML_ASSERT(node.size() == 3); YAML_ASSERT(node[0].as() == 10); YAML_ASSERT(node[1].as() == "foo"); YAML_ASSERT(node[2].as() == "monkey"); YAML_ASSERT(node.IsSequence()); return true; } TEST SimpleMap() { YAML::Node node; node["key"] = "value"; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node["key"].as() == "value"); YAML_ASSERT(node.size() == 1); return true; } TEST MapWithUndefinedValues() { YAML::Node node; node["key"] = "value"; node["undefined"]; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node["key"].as() == "value"); YAML_ASSERT(node.size() == 1); node["undefined"] = "monkey"; YAML_ASSERT(node["undefined"].as() == "monkey"); YAML_ASSERT(node.size() == 2); return true; } TEST MapIteratorWithUndefinedValues() { YAML::Node node; node["key"] = "value"; node["undefined"]; std::size_t count = 0; for(YAML::const_iterator it=node.begin();it!=node.end();++it) count++; YAML_ASSERT(count == 1); return true; } TEST SimpleSubkeys() { YAML::Node node; node["device"]["udid"] = "12345"; node["device"]["name"] = "iPhone"; node["device"]["os"] = "4.0"; node["username"] = "monkey"; YAML_ASSERT(node["device"]["udid"].as() == "12345"); YAML_ASSERT(node["device"]["name"].as() == "iPhone"); YAML_ASSERT(node["device"]["os"].as() == "4.0"); YAML_ASSERT(node["username"].as() == "monkey"); return true; } TEST StdVector() { std::vector primes; primes.push_back(2); primes.push_back(3); primes.push_back(5); primes.push_back(7); primes.push_back(11); primes.push_back(13); YAML::Node node; node["primes"] = primes; YAML_ASSERT(node["primes"].as >() == primes); return true; } TEST StdList() { std::list primes; primes.push_back(2); primes.push_back(3); primes.push_back(5); primes.push_back(7); primes.push_back(11); primes.push_back(13); YAML::Node node; node["primes"] = primes; YAML_ASSERT(node["primes"].as >() == primes); return true; } TEST StdMap() { std::map squares; squares[0] = 0; squares[1] = 1; squares[2] = 4; squares[3] = 9; squares[4] = 16; YAML::Node node; node["squares"] = squares; YAML_ASSERT((node["squares"].as >() == squares)); return true; } TEST SimpleAlias() { YAML::Node node; node["foo"] = "value"; node["bar"] = node["foo"]; YAML_ASSERT(node["foo"].as() == "value"); YAML_ASSERT(node["bar"].as() == "value"); YAML_ASSERT(node["foo"] == node["bar"]); YAML_ASSERT(node.size() == 2); return true; } TEST AliasAsKey() { YAML::Node node; node["foo"] = "value"; YAML::Node value = node["foo"]; node[value] = "foo"; YAML_ASSERT(node["foo"].as() == "value"); YAML_ASSERT(node[value].as() == "foo"); YAML_ASSERT(node["value"].as() == "foo"); YAML_ASSERT(node.size() == 2); return true; } TEST SelfReferenceSequence() { YAML::Node node; node[0] = node; YAML_ASSERT(node.IsSequence()); YAML_ASSERT(node.size() == 1); YAML_ASSERT(node[0] == node); YAML_ASSERT(node[0][0] == node); YAML_ASSERT(node[0][0] == node[0]); return true; } TEST ValueSelfReferenceMap() { YAML::Node node; node["key"] = node; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node.size() == 1); YAML_ASSERT(node["key"] == node); YAML_ASSERT(node["key"]["key"] == node); YAML_ASSERT(node["key"]["key"] == node["key"]); return true; } TEST KeySelfReferenceMap() { YAML::Node node; node[node] = "value"; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node.size() == 1); YAML_ASSERT(node[node].as() == "value"); return true; } TEST SelfReferenceMap() { YAML::Node node; node[node] = node; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node.size() == 1); YAML_ASSERT(node[node] == node); YAML_ASSERT(node[node][node] == node); YAML_ASSERT(node[node][node] == node[node]); return true; } TEST TempMapVariable() { YAML::Node node; YAML::Node tmp = node["key"]; tmp = "value"; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node.size() == 1); YAML_ASSERT(node["key"].as() == "value"); return true; } TEST TempMapVariableAlias() { YAML::Node node; YAML::Node tmp = node["key"]; tmp = node["other"]; node["other"] = "value"; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node.size() == 2); YAML_ASSERT(node["key"].as() == "value"); YAML_ASSERT(node["other"].as() == "value"); YAML_ASSERT(node["other"] == node["key"]); return true; } TEST Bool() { YAML::Node node; node[true] = false; YAML_ASSERT(node.IsMap()); YAML_ASSERT(node[true].as() == false); return true; } TEST AutoBoolConversion() { YAML::Node node; node["foo"] = "bar"; YAML_ASSERT(static_cast(node["foo"])); YAML_ASSERT(!node["monkey"]); YAML_ASSERT(!!node["foo"]); return true; } TEST Reassign() { YAML::Node node = YAML::Load("foo"); node = YAML::Node(); return true; } TEST FallbackValues() { YAML::Node node = YAML::Load("foo: bar\nx: 2"); YAML_ASSERT(node["foo"].as() == "bar"); YAML_ASSERT(node["foo"].as("hello") == "bar"); YAML_ASSERT(node["baz"].as("hello") == "hello"); YAML_ASSERT(node["x"].as() == 2); YAML_ASSERT(node["x"].as(5) == 2); YAML_ASSERT(node["y"].as(5) == 5); return true; } TEST NumericConversion() { YAML::Node node = YAML::Load("[1.5, 1, .nan, .inf, -.inf, 0x15, 015]"); YAML_ASSERT(node[0].as() == 1.5f); YAML_ASSERT(node[0].as() == 1.5); YAML_ASSERT_THROWS(node[0].as(), std::runtime_error); YAML_ASSERT(node[1].as() == 1); YAML_ASSERT(node[1].as() == 1.0f); YAML_ASSERT(node[2].as() != node[2].as()); YAML_ASSERT(node[3].as() == std::numeric_limits::infinity()); YAML_ASSERT(node[4].as() == -std::numeric_limits::infinity()); YAML_ASSERT(node[5].as() == 21); YAML_ASSERT(node[6].as() == 13); return true; } TEST Binary() { YAML::Node node = YAML::Load("[!!binary \"SGVsbG8sIFdvcmxkIQ==\", !!binary \"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4K\"]"); YAML_ASSERT(node[0].as() == YAML::Binary(reinterpret_cast("Hello, World!"), 13)); YAML_ASSERT(node[1].as() == YAML::Binary(reinterpret_cast("Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.\n"), 270)); return true; } TEST IterateSequence() { YAML::Node node = YAML::Load("[1, 3, 5, 7]"); int seq[] = {1, 3, 5, 7}; int i=0; for(YAML::const_iterator it=node.begin();it!=node.end();++it) { YAML_ASSERT(i < 4); int x = seq[i++]; YAML_ASSERT(it->as() == x); } YAML_ASSERT(i == 4); return true; } TEST IterateMap() { YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); int i=0; for(YAML::const_iterator it=node.begin();it!=node.end();++it) { YAML_ASSERT(i < 3); i++; YAML_ASSERT(it->first.as() + 'A' - 'a' == it->second.as()); } YAML_ASSERT(i == 3); return true; } TEST ForEach() { YAML::Node node = YAML::Load("[1, 3, 5, 7]"); int seq[] = {1, 3, 5, 7}; int i = 0; BOOST_FOREACH(const YAML::Node &item, node) { int x = seq[i++]; YAML_ASSERT(item.as() == x); } return true; } TEST ForEachMap() { YAML::Node node = YAML::Load("{a: A, b: B, c: C}"); BOOST_FOREACH(const YAML::const_iterator::value_type &p, node) { YAML_ASSERT(p.first.as() + 'A' - 'a' == p.second.as()); } return true; } TEST CloneScalar() { YAML::Node node = YAML::Load("!foo monkey"); YAML::Node clone = Clone(node); YAML_ASSERT(!(node == clone)); YAML_ASSERT(node.as() == clone.as()); YAML_ASSERT(node.Tag() == clone.Tag()); return true; } TEST CloneSeq() { YAML::Node node = YAML::Load("[1, 3, 5, 7]"); YAML::Node clone = Clone(node); YAML_ASSERT(!(node == clone)); YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); YAML_ASSERT(node.size() == clone.size()); for(std::size_t i=0;i() == clone[i].as()); return true; } TEST CloneMap() { YAML::Node node = YAML::Load("{foo: bar}"); YAML::Node clone = Clone(node); YAML_ASSERT(!(node == clone)); YAML_ASSERT(clone.Type() == YAML::NodeType::Map); YAML_ASSERT(node.size() == clone.size()); YAML_ASSERT(node["foo"].as() == clone["foo"].as()); return true; } TEST CloneAlias() { YAML::Node node = YAML::Load("&foo [*foo]"); YAML::Node clone = Clone(node); YAML_ASSERT(!(node == clone)); YAML_ASSERT(clone.Type() == YAML::NodeType::Sequence); YAML_ASSERT(node.size() == clone.size()); YAML_ASSERT(clone == clone[0]); return true; } TEST ForceInsertIntoMap() { YAML::Node node; node["a"] = "b"; node.force_insert("x", "y"); node.force_insert("a", 5); YAML_ASSERT(node.size() == 3); YAML_ASSERT(node.Type() == YAML::NodeType::Map); bool ab = false; bool a5 = false; bool xy = false; for(YAML::const_iterator it=node.begin();it!=node.end();++it) { if(it->first.as() == "a") { if(it->second.as() == "b") ab = true; else if(it->second.as() == "5") a5 = true; } else if(it->first.as() == "x" && it->second.as() == "y") xy = true; } YAML_ASSERT(ab); YAML_ASSERT(a5); YAML_ASSERT(xy); return true; } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { TEST ret; try { ret = test(); } catch(...) { ret.ok = false; } if(ret.ok) { passed++; } else { std::cout << "Node test failed: " << name << "\n"; if(ret.error != "") std::cout << ret.error << "\n"; } total++; } bool RunNodeTests() { int passed = 0; int total = 0; RunNodeTest(&Node::SimpleScalar, "simple scalar", passed, total); RunNodeTest(&Node::IntScalar, "int scalar", passed, total); RunNodeTest(&Node::SimpleAppendSequence, "simple append sequence", passed, total); RunNodeTest(&Node::SimpleAssignSequence, "simple assign sequence", passed, total); RunNodeTest(&Node::SimpleMap, "simple map", passed, total); RunNodeTest(&Node::MapWithUndefinedValues, "map with undefined values", passed, total); RunNodeTest(&Node::MapIteratorWithUndefinedValues, "map iterator with undefined values", passed, total); RunNodeTest(&Node::SimpleSubkeys, "simple subkey", passed, total); RunNodeTest(&Node::StdVector, "std::vector", passed, total); RunNodeTest(&Node::StdList, "std::list", passed, total); RunNodeTest(&Node::StdMap, "std::map", passed, total); RunNodeTest(&Node::SimpleAlias, "simple alias", passed, total); RunNodeTest(&Node::AliasAsKey, "alias as key", passed, total); RunNodeTest(&Node::SelfReferenceSequence, "self reference sequence", passed, total); RunNodeTest(&Node::ValueSelfReferenceMap, "value self reference map", passed, total); RunNodeTest(&Node::KeySelfReferenceMap, "key self reference map", passed, total); RunNodeTest(&Node::SelfReferenceMap, "self reference map", passed, total); RunNodeTest(&Node::TempMapVariable, "temp map variable", passed, total); RunNodeTest(&Node::TempMapVariableAlias, "temp map variable alias", passed, total); RunNodeTest(&Node::Bool, "bool", passed, total); RunNodeTest(&Node::AutoBoolConversion, "auto bool conversion", passed, total); RunNodeTest(&Node::Reassign, "reassign", passed, total); RunNodeTest(&Node::FallbackValues, "fallback values", passed, total); RunNodeTest(&Node::NumericConversion, "numeric conversion", passed, total); RunNodeTest(&Node::Binary, "binary", passed, total); RunNodeTest(&Node::IterateSequence, "iterate sequence", passed, total); RunNodeTest(&Node::IterateMap, "iterate map", passed, total); RunNodeTest(&Node::ForEach, "for each", passed, total); RunNodeTest(&Node::ForEachMap, "for each map", passed, total); RunNodeTest(&Node::CloneScalar, "clone scalar", passed, total); RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); RunNodeTest(&Node::CloneMap, "clone map", passed, total); RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total; } }