| Index: extensions/renderer/argument_spec_unittest.cc
|
| diff --git a/extensions/renderer/argument_spec_unittest.cc b/extensions/renderer/argument_spec_unittest.cc
|
| index 4bf8d256907215398643ac866457d2cf37a0de30..2b2e491bb528c49e21aa8deb75b674feebab38fe 100644
|
| --- a/extensions/renderer/argument_spec_unittest.cc
|
| +++ b/extensions/renderer/argument_spec_unittest.cc
|
| @@ -2,11 +2,12 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include "extensions/renderer/argument_spec.h"
|
| #include "base/memory/ptr_util.h"
|
| #include "base/values.h"
|
| #include "extensions/renderer/api_binding_test_util.h"
|
| +#include "extensions/renderer/api_invocation_errors.h"
|
| #include "extensions/renderer/api_type_reference_map.h"
|
| -#include "extensions/renderer/argument_spec.h"
|
| #include "gin/converter.h"
|
| #include "gin/public/isolate_holder.h"
|
| #include "gin/test/v8_test.h"
|
| @@ -20,44 +21,77 @@ class ArgumentSpecUnitTest : public gin::V8Test {
|
| ArgumentSpecUnitTest()
|
| : type_refs_(APITypeReferenceMap::InitializeTypeCallback()) {}
|
| ~ArgumentSpecUnitTest() override {}
|
| +
|
| + enum class TestResult {
|
| + PASS,
|
| + FAIL,
|
| + THROW,
|
| + };
|
| +
|
| + struct RunTestParams {
|
| + RunTestParams(const ArgumentSpec& spec,
|
| + base::StringPiece script_source,
|
| + TestResult result)
|
| + : spec(spec), script_source(script_source), expected_result(result) {}
|
| +
|
| + const ArgumentSpec& spec;
|
| + base::StringPiece script_source;
|
| + TestResult expected_result;
|
| + base::StringPiece expected_json;
|
| + base::StringPiece expected_error;
|
| + base::StringPiece expected_thrown_message;
|
| + const base::Value* expected_value = nullptr;
|
| + bool should_convert = true;
|
| + };
|
| +
|
| void ExpectSuccess(const ArgumentSpec& spec,
|
| const std::string& script_source,
|
| const std::string& expected_json_single_quotes) {
|
| - RunTest(spec, script_source, true, TestResult::PASS,
|
| - ReplaceSingleQuotes(expected_json_single_quotes), nullptr,
|
| - std::string());
|
| + RunTestParams params(spec, script_source, TestResult::PASS);
|
| + std::string expected_json =
|
| + ReplaceSingleQuotes(expected_json_single_quotes);
|
| + params.expected_json = expected_json;
|
| + RunTest(params);
|
| }
|
|
|
| void ExpectSuccess(const ArgumentSpec& spec,
|
| const std::string& script_source,
|
| const base::Value& expected_value) {
|
| - RunTest(spec, script_source, true, TestResult::PASS, std::string(),
|
| - &expected_value, std::string());
|
| + RunTestParams params(spec, script_source, TestResult::PASS);
|
| + params.expected_value = &expected_value;
|
| + RunTest(params);
|
| }
|
|
|
| void ExpectSuccessWithNoConversion(const ArgumentSpec& spec,
|
| const std::string& script_source) {
|
| - RunTest(spec, script_source, false, TestResult::PASS, std::string(),
|
| - nullptr, std::string());
|
| + RunTestParams params(spec, script_source, TestResult::PASS);
|
| + params.should_convert = false;
|
| + RunTest(params);
|
| }
|
|
|
| void ExpectFailure(const ArgumentSpec& spec,
|
| - const std::string& script_source) {
|
| - RunTest(spec, script_source, true, TestResult::FAIL, std::string(), nullptr,
|
| - std::string());
|
| + const std::string& script_source,
|
| + const std::string& expected_error) {
|
| + RunTestParams params(spec, script_source, TestResult::FAIL);
|
| + params.expected_error = expected_error;
|
| + RunTest(params);
|
| }
|
|
|
| void ExpectFailureWithNoConversion(const ArgumentSpec& spec,
|
| - const std::string& script_source) {
|
| - RunTest(spec, script_source, false, TestResult::FAIL, std::string(),
|
| - nullptr, std::string());
|
| + const std::string& script_source,
|
| + const std::string& expected_error) {
|
| + RunTestParams params(spec, script_source, TestResult::FAIL);
|
| + params.should_convert = false;
|
| + params.expected_error = expected_error;
|
| + RunTest(params);
|
| }
|
|
|
| void ExpectThrow(const ArgumentSpec& spec,
|
| const std::string& script_source,
|
| const std::string& expected_thrown_message) {
|
| - RunTest(spec, script_source, true, TestResult::THROW, std::string(),
|
| - nullptr, expected_thrown_message);
|
| + RunTestParams params(spec, script_source, TestResult::THROW);
|
| + params.expected_thrown_message = expected_thrown_message;
|
| + RunTest(params);
|
| }
|
|
|
| void AddTypeRef(const std::string& id, std::unique_ptr<ArgumentSpec> spec) {
|
| @@ -65,73 +99,68 @@ class ArgumentSpecUnitTest : public gin::V8Test {
|
| }
|
|
|
| private:
|
| - enum class TestResult { PASS, FAIL, THROW, };
|
| -
|
| - void RunTest(const ArgumentSpec& spec,
|
| - const std::string& script_source,
|
| - bool should_convert,
|
| - TestResult expected_result,
|
| - const std::string& expected_json,
|
| - const base::Value* expected_value,
|
| - const std::string& expected_thrown_message);
|
| + void RunTest(const RunTestParams& params);
|
|
|
| APITypeReferenceMap type_refs_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ArgumentSpecUnitTest);
|
| };
|
|
|
| -void ArgumentSpecUnitTest::RunTest(const ArgumentSpec& spec,
|
| - const std::string& script_source,
|
| - bool should_convert,
|
| - TestResult expected_result,
|
| - const std::string& expected_json,
|
| - const base::Value* expected_value,
|
| - const std::string& expected_thrown_message) {
|
| +void ArgumentSpecUnitTest::RunTest(const RunTestParams& params) {
|
| v8::Isolate* isolate = instance_->isolate();
|
| v8::HandleScope handle_scope(instance_->isolate());
|
|
|
| v8::Local<v8::Context> context =
|
| v8::Local<v8::Context>::New(instance_->isolate(), context_);
|
| v8::TryCatch try_catch(isolate);
|
| - v8::Local<v8::Value> val = V8ValueFromScriptSource(context, script_source);
|
| - ASSERT_FALSE(val.IsEmpty()) << script_source;
|
| + v8::Local<v8::Value> val =
|
| + V8ValueFromScriptSource(context, params.script_source);
|
| + ASSERT_FALSE(val.IsEmpty()) << params.script_source;
|
|
|
| std::string error;
|
| std::unique_ptr<base::Value> out_value;
|
| - bool did_succeed =
|
| - spec.ParseArgument(context, val, type_refs_,
|
| - should_convert ? &out_value : nullptr, &error);
|
| - bool should_succeed = expected_result == TestResult::PASS;
|
| - ASSERT_EQ(should_succeed, did_succeed) << script_source << ", " << error;
|
| - ASSERT_EQ(did_succeed && should_convert, !!out_value);
|
| - bool should_throw = expected_result == TestResult::THROW;
|
| - ASSERT_EQ(should_throw, try_catch.HasCaught()) << script_source;
|
| - if (should_succeed && should_convert) {
|
| + bool did_succeed = params.spec.ParseArgument(
|
| + context, val, type_refs_, params.should_convert ? &out_value : nullptr,
|
| + &error);
|
| + bool should_succeed = params.expected_result == TestResult::PASS;
|
| + ASSERT_EQ(should_succeed, did_succeed)
|
| + << params.script_source << ", " << error;
|
| + ASSERT_EQ(did_succeed && params.should_convert, !!out_value);
|
| + bool should_throw = params.expected_result == TestResult::THROW;
|
| + ASSERT_EQ(should_throw, try_catch.HasCaught()) << params.script_source;
|
| +
|
| + if (!params.expected_error.empty())
|
| + EXPECT_EQ(params.expected_error, error) << params.script_source;
|
| +
|
| + if (should_succeed && params.should_convert) {
|
| ASSERT_TRUE(out_value);
|
| - if (expected_value)
|
| - EXPECT_TRUE(expected_value->Equals(out_value.get())) << script_source;
|
| + if (params.expected_value)
|
| + EXPECT_TRUE(params.expected_value->Equals(out_value.get()))
|
| + << params.script_source;
|
| else
|
| - EXPECT_EQ(expected_json, ValueToString(*out_value));
|
| + EXPECT_EQ(params.expected_json, ValueToString(*out_value));
|
| } else if (should_throw) {
|
| - EXPECT_EQ(expected_thrown_message,
|
| + EXPECT_EQ(params.expected_thrown_message,
|
| gin::V8ToString(try_catch.Message()->Get()));
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, Test) {
|
| + using namespace api_errors;
|
| +
|
| {
|
| ArgumentSpec spec(*ValueFromString("{'type': 'integer'}"));
|
| ExpectSuccess(spec, "1", "1");
|
| ExpectSuccess(spec, "-1", "-1");
|
| ExpectSuccess(spec, "0", "0");
|
| ExpectSuccess(spec, "0.0", "0");
|
| - ExpectFailure(spec, "undefined");
|
| - ExpectFailure(spec, "null");
|
| - ExpectFailure(spec, "1.1");
|
| - ExpectFailure(spec, "'foo'");
|
| - ExpectFailure(spec, "'1'");
|
| - ExpectFailure(spec, "{}");
|
| - ExpectFailure(spec, "[1]");
|
| + ExpectFailure(spec, "undefined", InvalidType(kTypeInteger, kTypeUndefined));
|
| + ExpectFailure(spec, "null", InvalidType(kTypeInteger, kTypeNull));
|
| + ExpectFailure(spec, "1.1", InvalidType(kTypeInteger, kTypeDouble));
|
| + ExpectFailure(spec, "'foo'", InvalidType(kTypeInteger, kTypeString));
|
| + ExpectFailure(spec, "'1'", InvalidType(kTypeInteger, kTypeString));
|
| + ExpectFailure(spec, "({})", InvalidType(kTypeInteger, kTypeObject));
|
| + ExpectFailure(spec, "[1]", InvalidType(kTypeInteger, kTypeList));
|
| }
|
|
|
| {
|
| @@ -142,69 +171,71 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| ExpectSuccess(spec, "1.1", "1.1");
|
| ExpectSuccess(spec, "1.", "1.0");
|
| ExpectSuccess(spec, ".1", "0.1");
|
| - ExpectFailure(spec, "undefined");
|
| - ExpectFailure(spec, "null");
|
| - ExpectFailure(spec, "'foo'");
|
| - ExpectFailure(spec, "'1.1'");
|
| - ExpectFailure(spec, "{}");
|
| - ExpectFailure(spec, "[1.1]");
|
| + ExpectFailure(spec, "undefined", InvalidType(kTypeDouble, kTypeUndefined));
|
| + ExpectFailure(spec, "null", InvalidType(kTypeDouble, kTypeNull));
|
| + ExpectFailure(spec, "'foo'", InvalidType(kTypeDouble, kTypeString));
|
| + ExpectFailure(spec, "'1.1'", InvalidType(kTypeDouble, kTypeString));
|
| + ExpectFailure(spec, "({})", InvalidType(kTypeDouble, kTypeObject));
|
| + ExpectFailure(spec, "[1.1]", InvalidType(kTypeDouble, kTypeList));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'minimum': 1}"));
|
| ExpectSuccess(spec, "2", "2");
|
| ExpectSuccess(spec, "1", "1");
|
| - ExpectFailure(spec, "0");
|
| - ExpectFailure(spec, "-1");
|
| + ExpectFailure(spec, "0", NumberTooSmall(1));
|
| + ExpectFailure(spec, "-1", NumberTooSmall(1));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'maximum': 10}"));
|
| ExpectSuccess(spec, "10", "10");
|
| ExpectSuccess(spec, "1", "1");
|
| - ExpectFailure(spec, "11");
|
| + ExpectFailure(spec, "11", NumberTooLarge(10));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(*ValueFromString("{'type': 'string'}"));
|
| ExpectSuccess(spec, "'foo'", "'foo'");
|
| ExpectSuccess(spec, "''", "''");
|
| - ExpectFailure(spec, "1");
|
| - ExpectFailure(spec, "{}");
|
| - ExpectFailure(spec, "['foo']");
|
| + ExpectFailure(spec, "1", InvalidType(kTypeString, kTypeInteger));
|
| + ExpectFailure(spec, "({})", InvalidType(kTypeString, kTypeObject));
|
| + ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(
|
| *ValueFromString("{'type': 'string', 'enum': ['foo', 'bar']}"));
|
| + std::set<std::string> valid_enums = {"foo", "bar"};
|
| ExpectSuccess(spec, "'foo'", "'foo'");
|
| ExpectSuccess(spec, "'bar'", "'bar'");
|
| - ExpectFailure(spec, "['foo']");
|
| - ExpectFailure(spec, "'fo'");
|
| - ExpectFailure(spec, "'foobar'");
|
| - ExpectFailure(spec, "'baz'");
|
| - ExpectFailure(spec, "''");
|
| + ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
|
| + ExpectFailure(spec, "'fo'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "'foobar'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "'baz'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "''", InvalidEnumValue(valid_enums));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(*ValueFromString(
|
| "{'type': 'string', 'enum': [{'name': 'foo'}, {'name': 'bar'}]}"));
|
| + std::set<std::string> valid_enums = {"foo", "bar"};
|
| ExpectSuccess(spec, "'foo'", "'foo'");
|
| ExpectSuccess(spec, "'bar'", "'bar'");
|
| - ExpectFailure(spec, "['foo']");
|
| - ExpectFailure(spec, "'fo'");
|
| - ExpectFailure(spec, "'foobar'");
|
| - ExpectFailure(spec, "'baz'");
|
| - ExpectFailure(spec, "''");
|
| + ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
|
| + ExpectFailure(spec, "'fo'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "'foobar'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "'baz'", InvalidEnumValue(valid_enums));
|
| + ExpectFailure(spec, "''", InvalidEnumValue(valid_enums));
|
| }
|
|
|
| {
|
| ArgumentSpec spec(*ValueFromString("{'type': 'boolean'}"));
|
| ExpectSuccess(spec, "true", "true");
|
| ExpectSuccess(spec, "false", "false");
|
| - ExpectFailure(spec, "1");
|
| - ExpectFailure(spec, "'true'");
|
| - ExpectFailure(spec, "null");
|
| + ExpectFailure(spec, "1", InvalidType(kTypeBoolean, kTypeInteger));
|
| + ExpectFailure(spec, "'true'", InvalidType(kTypeBoolean, kTypeString));
|
| + ExpectFailure(spec, "null", InvalidType(kTypeBoolean, kTypeNull));
|
| }
|
|
|
| {
|
| @@ -214,13 +245,16 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| ExpectSuccess(spec, "['foo']", "['foo']");
|
| ExpectSuccess(spec, "['foo', 'bar']", "['foo','bar']");
|
| ExpectSuccess(spec, "var x = new Array(); x[0] = 'foo'; x;", "['foo']");
|
| - ExpectFailure(spec, "'foo'");
|
| - ExpectFailure(spec, "[1, 2]");
|
| - ExpectFailure(spec, "['foo', 1]");
|
| + ExpectFailure(spec, "'foo'", InvalidType(kTypeList, kTypeString));
|
| + ExpectFailure(spec, "[1, 2]",
|
| + IndexError(0u, InvalidType(kTypeString, kTypeInteger)));
|
| + ExpectFailure(spec, "['foo', 1]",
|
| + IndexError(1u, InvalidType(kTypeString, kTypeInteger)));
|
| ExpectFailure(spec,
|
| "var x = ['a', 'b', 'c'];"
|
| "x[4] = 'd';" // x[3] is undefined, violating the spec.
|
| - "x;");
|
| + "x;",
|
| + IndexError(3u, InvalidType(kTypeString, kTypeUndefined)));
|
| ExpectThrow(
|
| spec,
|
| "var x = [];"
|
| @@ -246,27 +280,34 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}");
|
| ExpectSuccess(spec, "({prop1: 'foo', prop2: null})", "{'prop1':'foo'}");
|
| ExpectSuccess(spec, "x = {}; x.prop1 = 'foo'; x;", "{'prop1':'foo'}");
|
| - ExpectFailure(spec, "({prop1: 'foo', prop2: 'bar'})");
|
| - ExpectFailure(spec, "({prop2: 2})");
|
| + ExpectFailure(
|
| + spec, "({prop1: 'foo', prop2: 'bar'})",
|
| + PropertyError("prop2", InvalidType(kTypeInteger, kTypeString)));
|
| + ExpectFailure(spec, "({prop2: 2})", MissingRequiredProperty("prop1"));
|
| // Unknown properties are not allowed.
|
| - ExpectFailure(spec, "({prop1: 'foo', prop2: 2, prop3: 'blah'})");
|
| + ExpectFailure(spec, "({prop1: 'foo', prop2: 2, prop3: 'blah'})",
|
| + UnexpectedProperty("prop3"));
|
| // We only consider properties on the object itself, not its prototype
|
| // chain.
|
| ExpectFailure(spec,
|
| "function X() {}\n"
|
| "X.prototype = { prop1: 'foo' };\n"
|
| "var x = new X();\n"
|
| - "x;");
|
| + "x;",
|
| + MissingRequiredProperty("prop1"));
|
| ExpectFailure(spec,
|
| "function X() {}\n"
|
| "X.prototype = { prop1: 'foo' };\n"
|
| "function Y() { this.__proto__ = X.prototype; }\n"
|
| "var z = new Y();\n"
|
| - "z;");
|
| + "z;",
|
| + MissingRequiredProperty("prop1"));
|
| // Self-referential fun. Currently we don't have to worry about these much
|
| // because the spec won't match at some point (and V8ValueConverter has
|
| // cycle detection and will fail).
|
| - ExpectFailure(spec, "x = {}; x.prop1 = x; x;");
|
| + ExpectFailure(
|
| + spec, "x = {}; x.prop1 = x; x;",
|
| + PropertyError("prop1", InvalidType(kTypeString, kTypeObject)));
|
| ExpectThrow(
|
| spec,
|
| "({ get prop1() { throw new Error('Badness'); }});",
|
| @@ -300,9 +341,12 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| ExpectSuccessWithNoConversion(spec, "(function() {})");
|
| ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })");
|
| ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })");
|
| - ExpectFailureWithNoConversion(spec, "({a: function() {}})");
|
| - ExpectFailureWithNoConversion(spec, "([function() {}])");
|
| - ExpectFailureWithNoConversion(spec, "1");
|
| + ExpectFailureWithNoConversion(spec, "({a: function() {}})",
|
| + InvalidType(kTypeFunction, kTypeObject));
|
| + ExpectFailureWithNoConversion(spec, "([function() {}])",
|
| + InvalidType(kTypeFunction, kTypeList));
|
| + ExpectFailureWithNoConversion(spec, "1",
|
| + InvalidType(kTypeFunction, kTypeInteger));
|
| }
|
|
|
| {
|
| @@ -334,7 +378,7 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| "b;",
|
| *expected_value);
|
| }
|
| - ExpectFailure(spec, "1");
|
| + ExpectFailure(spec, "1", InvalidType(kTypeBinary, kTypeInteger));
|
| }
|
| {
|
| const char kAnySpec[] = "{ 'type': 'any' }";
|
| @@ -358,12 +402,14 @@ TEST_F(ArgumentSpecUnitTest, Test) {
|
| // null, which is a potentially important distinction. However, this means
|
| // that in serialization of an object {a: 1, foo:undefined}, we lose the
|
| // 'foo' property.
|
| - ExpectFailure(spec, "undefined");
|
| + ExpectFailure(spec, "undefined", UnserializableValue());
|
| +
|
| ExpectSuccess(spec, "({prop1: 1, prop2: undefined})", "{'prop1':1}");
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
|
| + using namespace api_errors;
|
| const char kObjectType[] =
|
| "{"
|
| " 'id': 'refObj',"
|
| @@ -379,6 +425,7 @@ TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
|
| base::MakeUnique<ArgumentSpec>(*ValueFromString(kObjectType)));
|
| AddTypeRef("refEnum",
|
| base::MakeUnique<ArgumentSpec>(*ValueFromString(kEnumType)));
|
| + std::set<std::string> valid_enums = {"alpha", "beta"};
|
|
|
| {
|
| const char kObjectWithRefEnumSpec[] =
|
| @@ -393,8 +440,9 @@ TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
|
| ArgumentSpec spec(*ValueFromString(kObjectWithRefEnumSpec));
|
| ExpectSuccess(spec, "({e: 'alpha', sub: 1})", "{'e':'alpha','sub':1}");
|
| ExpectSuccess(spec, "({e: 'beta', sub: 1})", "{'e':'beta','sub':1}");
|
| - ExpectFailure(spec, "({e: 'gamma', sub: 1})");
|
| - ExpectFailure(spec, "({e: 'alpha'})");
|
| + ExpectFailure(spec, "({e: 'gamma', sub: 1})",
|
| + PropertyError("e", InvalidEnumValue(valid_enums)));
|
| + ExpectFailure(spec, "({e: 'alpha'})", MissingRequiredProperty("sub"));
|
| }
|
|
|
| {
|
| @@ -410,7 +458,10 @@ TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
|
| ExpectSuccess(spec, "({o: {prop1: 'foo'}})", "{'o':{'prop1':'foo'}}");
|
| ExpectSuccess(spec, "({o: {prop1: 'foo', prop2: 2}})",
|
| "{'o':{'prop1':'foo','prop2':2}}");
|
| - ExpectFailure(spec, "({o: {prop1: 1}})");
|
| + ExpectFailure(
|
| + spec, "({o: {prop1: 1}})",
|
| + PropertyError("o", PropertyError("prop1", InvalidType(kTypeString,
|
| + kTypeInteger))));
|
| }
|
|
|
| {
|
| @@ -420,18 +471,20 @@ TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
|
| ExpectSuccess(spec, "['alpha']", "['alpha']");
|
| ExpectSuccess(spec, "['alpha', 'alpha']", "['alpha','alpha']");
|
| ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']");
|
| - ExpectFailure(spec, "['alpha', 'beta', 'gamma']");
|
| + ExpectFailure(spec, "['alpha', 'beta', 'gamma']",
|
| + IndexError(2u, InvalidEnumValue(valid_enums)));
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, TypeChoicesTest) {
|
| + using namespace api_errors;
|
| {
|
| const char kSimpleChoices[] =
|
| "{'choices': [{'type': 'string'}, {'type': 'integer'}]}";
|
| ArgumentSpec spec(*ValueFromString(kSimpleChoices));
|
| ExpectSuccess(spec, "'alpha'", "'alpha'");
|
| ExpectSuccess(spec, "42", "42");
|
| - ExpectFailure(spec, "true");
|
| + ExpectFailure(spec, "true", InvalidChoice());
|
| }
|
|
|
| {
|
| @@ -446,13 +499,14 @@ TEST_F(ArgumentSpecUnitTest, TypeChoicesTest) {
|
| ExpectSuccess(spec, "['alpha']", "['alpha']");
|
| ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']");
|
| ExpectSuccess(spec, "({prop1: 'alpha'})", "{'prop1':'alpha'}");
|
| - ExpectFailure(spec, "({prop1: 1})");
|
| - ExpectFailure(spec, "'alpha'");
|
| - ExpectFailure(spec, "42");
|
| + ExpectFailure(spec, "({prop1: 1})", InvalidChoice());
|
| + ExpectFailure(spec, "'alpha'", InvalidChoice());
|
| + ExpectFailure(spec, "42", InvalidChoice());
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, AdditionalPropertiesTest) {
|
| + using namespace api_errors;
|
| {
|
| const char kOnlyAnyAdditionalProperties[] =
|
| "{"
|
| @@ -533,8 +587,11 @@ TEST_F(ArgumentSpecUnitTest, AdditionalPropertiesTest) {
|
| "{'prop1':'alpha','prop2':42,'prop3':{'foo':'bar'}}");
|
| // Additional properties are optional.
|
| ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}");
|
| - ExpectFailure(spec, "({prop2: 42, prop3: {foo: 'bar'}})");
|
| - ExpectFailure(spec, "({prop1: 42})");
|
| + ExpectFailure(spec, "({prop2: 42, prop3: {foo: 'bar'}})",
|
| + MissingRequiredProperty("prop1"));
|
| + ExpectFailure(
|
| + spec, "({prop1: 42})",
|
| + PropertyError("prop1", InvalidType(kTypeString, kTypeInteger)));
|
| }
|
| {
|
| const char kTypedAdditionalProperties[] =
|
| @@ -545,11 +602,14 @@ TEST_F(ArgumentSpecUnitTest, AdditionalPropertiesTest) {
|
| ArgumentSpec spec(*ValueFromString(kTypedAdditionalProperties));
|
| ExpectSuccess(spec, "({prop1: 'alpha', prop2: 'beta', prop3: 'gamma'})",
|
| "{'prop1':'alpha','prop2':'beta','prop3':'gamma'}");
|
| - ExpectFailure(spec, "({prop1: 'alpha', prop2: 42})");
|
| + ExpectFailure(
|
| + spec, "({prop1: 'alpha', prop2: 42})",
|
| + PropertyError("prop2", InvalidType(kTypeString, kTypeInteger)));
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, InstanceOfTest) {
|
| + using namespace api_errors;
|
| {
|
| const char kInstanceOfRegExp[] =
|
| "{"
|
| @@ -572,10 +632,11 @@ TEST_F(ArgumentSpecUnitTest, InstanceOfTest) {
|
| " return new RegExp();\n"
|
| "})()",
|
| "{}");
|
| - ExpectFailure(spec, "({})");
|
| - ExpectFailure(spec, "('')");
|
| - ExpectFailure(spec, "('.*')");
|
| - ExpectFailure(spec, "({ __proto__: Date.prototype })");
|
| + ExpectFailure(spec, "({})", NotAnInstance("RegExp"));
|
| + ExpectFailure(spec, "('')", InvalidType("RegExp", kTypeString));
|
| + ExpectFailure(spec, "('.*')", InvalidType("RegExp", kTypeString));
|
| + ExpectFailure(spec, "({ __proto__: Date.prototype })",
|
| + NotAnInstance("RegExp"));
|
| }
|
|
|
| {
|
| @@ -600,23 +661,25 @@ TEST_F(ArgumentSpecUnitTest, InstanceOfTest) {
|
| " return new otherClass();\n"
|
| "})()",
|
| "{}");
|
| - ExpectFailure(spec, "({})");
|
| + ExpectFailure(spec, "({})", NotAnInstance("customClass"));
|
| ExpectFailure(spec,
|
| "(function() {\n"
|
| " function otherClass() {}\n"
|
| " return new otherClass();\n"
|
| - "})()");
|
| + "})()",
|
| + NotAnInstance("customClass"));
|
| }
|
| }
|
|
|
| TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) {
|
| + using namespace api_errors;
|
| {
|
| const char kMinLengthString[] = "{'type': 'string', 'minLength': 3}";
|
| ArgumentSpec spec(*ValueFromString(kMinLengthString));
|
| ExpectSuccess(spec, "'aaa'", "'aaa'");
|
| ExpectSuccess(spec, "'aaaa'", "'aaaa'");
|
| - ExpectFailure(spec, "'aa'");
|
| - ExpectFailure(spec, "''");
|
| + ExpectFailure(spec, "'aa'", TooFewStringChars(3, 2));
|
| + ExpectFailure(spec, "''", TooFewStringChars(3, 0));
|
| }
|
|
|
| {
|
| @@ -625,7 +688,7 @@ TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) {
|
| ExpectSuccess(spec, "'aaa'", "'aaa'");
|
| ExpectSuccess(spec, "'aa'", "'aa'");
|
| ExpectSuccess(spec, "''", "''");
|
| - ExpectFailure(spec, "'aaaa'");
|
| + ExpectFailure(spec, "'aaaa'", TooManyStringChars(3, 4));
|
| }
|
|
|
| {
|
| @@ -634,8 +697,8 @@ TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) {
|
| ArgumentSpec spec(*ValueFromString(kMinLengthArray));
|
| ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]");
|
| ExpectSuccess(spec, "[1, 2, 3, 4]", "[1,2,3,4]");
|
| - ExpectFailure(spec, "[1, 2]");
|
| - ExpectFailure(spec, "[]");
|
| + ExpectFailure(spec, "[1, 2]", TooFewArrayItems(3, 2));
|
| + ExpectFailure(spec, "[]", TooFewArrayItems(3, 0));
|
| }
|
|
|
| {
|
| @@ -645,7 +708,7 @@ TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) {
|
| ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]");
|
| ExpectSuccess(spec, "[1, 2]", "[1,2]");
|
| ExpectSuccess(spec, "[]", "[]");
|
| - ExpectFailure(spec, "[1, 2, 3, 4]");
|
| + ExpectFailure(spec, "[1, 2, 3, 4]", TooManyArrayItems(3, 4));
|
| }
|
| }
|
|
|
|
|