diff options
-rw-r--r-- | src/core/common/Argument.cpp | 27 | ||||
-rw-r--r-- | test/core/common/ArgumentTest.cpp | 146 |
2 files changed, 164 insertions, 9 deletions
diff --git a/src/core/common/Argument.cpp b/src/core/common/Argument.cpp index 4e80f23..8face55 100644 --- a/src/core/common/Argument.cpp +++ b/src/core/common/Argument.cpp @@ -192,12 +192,12 @@ static std::unordered_map<std::string, size_t> buildArgumentNames( for (const Argument &arg : arguments) { if (!Utils::isIdentifier(arg.name)) { throw OusiaException{std::string("Argument name ") + arg.name + - std::string(" is not a valid identifier!")}; + std::string(" is not a valid identifier")}; } if (!res.emplace(arg.name, i++).second) { throw OusiaException{ std::string("Argument names must be unique (") + arg.name + - std::string(")!")}; + std::string(")")}; } } return res; @@ -210,6 +210,8 @@ Arguments::Arguments(std::initializer_list<Argument> arguments) bool Arguments::validateArray(Variant::arrayType &arr, Logger &logger) { + Logger nullLogger; + // Fetch the number of arguments N and the initial array size n const size_t n = arr.size(); const size_t N = arguments.size(); @@ -235,9 +237,11 @@ bool Arguments::validateArray(Variant::arrayType &arr, Logger &logger) if (arguments[a].hasDefault) { arr[a] = arguments[a].defaultValue; } else { + // Call "validate" to inject a standard value + arguments[a].validate(arr[a], nullLogger); logger.error(std::string("Missing argument ") + - std::to_string(a + 1) + std::string("(") + - arguments[a].name + std::string(")!")); + std::to_string(a + 1) + std::string(" \"") + + arguments[a].name + std::string("\"")); ok = false; } } @@ -249,6 +253,8 @@ bool Arguments::validateArray(Variant::arrayType &arr, Logger &logger) bool Arguments::validateMap(Variant::mapType &map, Logger &logger, bool ignoreUnknown) { + Logger nullLogger; + // Fetch the number of arguments N const size_t N = arguments.size(); std::vector<bool> set(N); @@ -265,10 +271,10 @@ bool Arguments::validateMap(Variant::mapType &map, Logger &logger, ok = ok && set[idx]; } else { if (ignoreUnknown) { - logger.note(std::string("Ignoring argument ") + e.first); + logger.note(std::string("Ignoring argument \"") + e.first + std::string("\"")); } else { - logger.error(std::string("Unknown argument ") + e.first + - std::string("!")); + logger.error(std::string("Unknown argument \"") + e.first + + std::string("\"")); ok = false; } } @@ -280,8 +286,11 @@ bool Arguments::validateMap(Variant::mapType &map, Logger &logger, if (arguments[a].hasDefault) { map[arguments[a].name] = arguments[a].defaultValue; } else { - logger.error(std::string("Missing argument ") + - arguments[a].name); + // Call "validate" to inject a standard value + map[arguments[a].name] = Variant{}; + arguments[a].validate(map[arguments[a].name], nullLogger); + logger.error(std::string("Missing argument \"") + + arguments[a].name + std::string("\"")); ok = false; } } diff --git a/test/core/common/ArgumentTest.cpp b/test/core/common/ArgumentTest.cpp index f3f8f2b..d58f71b 100644 --- a/test/core/common/ArgumentTest.cpp +++ b/test/core/common/ArgumentTest.cpp @@ -52,6 +52,63 @@ static const Rtti<ousia::TestManaged2> TestManaged2 = RttiBuilder("TestManaged2").parent(&TestManaged1); } +TEST(Argument, validateAny) +{ + Argument a = Argument::Any("a"); + + ASSERT_FALSE(a.hasDefault); + + { + Variant v{true}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isBool()); + ASSERT_TRUE(v.asBool()); + } + + { + Variant v{"test"}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isString()); + ASSERT_EQ("test", v.asString()); + } + + { + Variant v{{1, 2, 3, 4}}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isArray()); + ASSERT_EQ(Variant::arrayType({1, 2, 3, 4}), v.asArray()); + } +} + +TEST(Argument, validateAnyDefault) +{ + Argument a = Argument::Any("a", true); + + ASSERT_TRUE(a.hasDefault); + ASSERT_TRUE(a.defaultValue.asBool()); + + { + Variant v{true}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isBool()); + ASSERT_TRUE(v.asBool()); + } + + { + Variant v{"test"}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isString()); + ASSERT_EQ("test", v.asString()); + } + + { + Variant v{{1, 2, 3, 4}}; + ASSERT_TRUE(a.validate(v, logger)); + ASSERT_TRUE(v.isArray()); + ASSERT_EQ(Variant::arrayType({1, 2, 3, 4}), v.asArray()); + } +} + TEST(Argument, validateBool) { Argument a = Argument::Bool("a"); @@ -716,5 +773,94 @@ TEST(Argument, validateMapInnerTypeDefault) ASSERT_EQ(mapDefault, v.asMap()); } } + +TEST(Arguments, construction) +{ + // This should work without exception + Arguments{Argument::Int("a"), Argument::Any("b")}; + + // This should throw an exception + ASSERT_THROW(Arguments({Argument::Int("a"), Argument::Any("a")}), + OusiaException); + ASSERT_THROW(Arguments({Argument::Int("test test")}), OusiaException); +} + +TEST(Arguments, validateArray) +{ + Arguments args{Argument::Int("a"), Argument::String("b", "test"), + Argument::Bool("c", true)}; + + { + Variant::arrayType arr{1, 5, false}; + ASSERT_TRUE(args.validateArray(arr, logger)); + ASSERT_EQ(Variant::arrayType({1, "5", false}), arr); + } + + { + Variant::arrayType arr{1, 5}; + ASSERT_TRUE(args.validateArray(arr, logger)); + ASSERT_EQ(Variant::arrayType({1, "5", true}), arr); + } + + { + Variant::arrayType arr{1}; + ASSERT_TRUE(args.validateArray(arr, logger)); + ASSERT_EQ(Variant::arrayType({1, "test", true}), arr); + } + + { + Variant::arrayType arr{}; + ASSERT_FALSE(args.validateArray(arr, logger)); + ASSERT_EQ(Variant::arrayType({0, "test", true}), arr); + } + + { + Variant::arrayType arr{1, "bla", false, 42}; + ASSERT_FALSE(args.validateArray(arr, logger)); + ASSERT_EQ(Variant::arrayType({1, "bla", false}), arr); + } +} + +TEST(Arguments, validateMap) +{ + Arguments args{Argument::Int("a"), Argument::String("b", "test"), + Argument::Bool("c", true)}; + + { + Variant::mapType map{{"a", 2}, {"b", 5}, {"c", true}}; + ASSERT_TRUE(args.validateMap(map, logger, false)); + ASSERT_EQ(Variant::mapType({{"a", 2}, {"b", "5"}, {"c", true}}), map); + } + + { + Variant::mapType map{{"a", 2}, {"c", false}}; + ASSERT_TRUE(args.validateMap(map, logger, false)); + ASSERT_EQ(Variant::mapType({{"a", 2}, {"b", "test"}, {"c", false}}), map); + } + + { + Variant::mapType map{{"a", 2}}; + ASSERT_TRUE(args.validateMap(map, logger, false)); + ASSERT_EQ(Variant::mapType({{"a", 2}, {"b", "test"}, {"c", true}}), map); + } + + { + Variant::mapType map{}; + ASSERT_FALSE(args.validateMap(map, logger, false)); + ASSERT_EQ(Variant::mapType({{"a", 0}, {"b", "test"}, {"c", true}}), map); + } + + { + Variant::mapType map{{"a", 2}, {"d", nullptr}}; + ASSERT_FALSE(args.validateMap(map, logger, false)); + ASSERT_EQ(Variant::mapType({{"a", 2}, {"b", "test"}, {"c", true}, {"d", nullptr}}), map); + } + + { + Variant::mapType map{{"a", 2}, {"d", nullptr}}; + ASSERT_TRUE(args.validateMap(map, logger, true)); + ASSERT_EQ(Variant::mapType({{"a", 2}, {"b", "test"}, {"c", true}, {"d", nullptr}}), map); + } +} } |