Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: extensions/renderer/argument_spec_unittest.cc

Issue 2837023003: [Extensions Bindings] Add argument parsing errors (Closed)
Patch Set: nits Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/renderer/argument_spec.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/argument_spec.h"
5 #include "base/memory/ptr_util.h" 6 #include "base/memory/ptr_util.h"
6 #include "base/values.h" 7 #include "base/values.h"
7 #include "extensions/renderer/api_binding_test_util.h" 8 #include "extensions/renderer/api_binding_test_util.h"
9 #include "extensions/renderer/api_invocation_errors.h"
8 #include "extensions/renderer/api_type_reference_map.h" 10 #include "extensions/renderer/api_type_reference_map.h"
9 #include "extensions/renderer/argument_spec.h"
10 #include "gin/converter.h" 11 #include "gin/converter.h"
11 #include "gin/public/isolate_holder.h" 12 #include "gin/public/isolate_holder.h"
12 #include "gin/test/v8_test.h" 13 #include "gin/test/v8_test.h"
13 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
14 #include "v8/include/v8.h" 15 #include "v8/include/v8.h"
15 16
16 namespace extensions { 17 namespace extensions {
17 18
18 class ArgumentSpecUnitTest : public gin::V8Test { 19 class ArgumentSpecUnitTest : public gin::V8Test {
19 protected: 20 protected:
20 ArgumentSpecUnitTest() 21 ArgumentSpecUnitTest()
21 : type_refs_(APITypeReferenceMap::InitializeTypeCallback()) {} 22 : type_refs_(APITypeReferenceMap::InitializeTypeCallback()) {}
22 ~ArgumentSpecUnitTest() override {} 23 ~ArgumentSpecUnitTest() override {}
24
25 enum class TestResult {
26 PASS,
27 FAIL,
28 THROW,
29 };
30
31 struct RunTestParams {
32 RunTestParams(const ArgumentSpec& spec,
33 base::StringPiece script_source,
34 TestResult result)
35 : spec(spec), script_source(script_source), expected_result(result) {}
36
37 const ArgumentSpec& spec;
38 base::StringPiece script_source;
39 TestResult expected_result;
40 base::StringPiece expected_json;
41 base::StringPiece expected_error;
42 base::StringPiece expected_thrown_message;
43 const base::Value* expected_value = nullptr;
44 bool should_convert = true;
45 };
46
23 void ExpectSuccess(const ArgumentSpec& spec, 47 void ExpectSuccess(const ArgumentSpec& spec,
24 const std::string& script_source, 48 const std::string& script_source,
25 const std::string& expected_json_single_quotes) { 49 const std::string& expected_json_single_quotes) {
26 RunTest(spec, script_source, true, TestResult::PASS, 50 RunTestParams params(spec, script_source, TestResult::PASS);
27 ReplaceSingleQuotes(expected_json_single_quotes), nullptr, 51 std::string expected_json =
28 std::string()); 52 ReplaceSingleQuotes(expected_json_single_quotes);
53 params.expected_json = expected_json;
54 RunTest(params);
29 } 55 }
30 56
31 void ExpectSuccess(const ArgumentSpec& spec, 57 void ExpectSuccess(const ArgumentSpec& spec,
32 const std::string& script_source, 58 const std::string& script_source,
33 const base::Value& expected_value) { 59 const base::Value& expected_value) {
34 RunTest(spec, script_source, true, TestResult::PASS, std::string(), 60 RunTestParams params(spec, script_source, TestResult::PASS);
35 &expected_value, std::string()); 61 params.expected_value = &expected_value;
62 RunTest(params);
36 } 63 }
37 64
38 void ExpectSuccessWithNoConversion(const ArgumentSpec& spec, 65 void ExpectSuccessWithNoConversion(const ArgumentSpec& spec,
39 const std::string& script_source) { 66 const std::string& script_source) {
40 RunTest(spec, script_source, false, TestResult::PASS, std::string(), 67 RunTestParams params(spec, script_source, TestResult::PASS);
41 nullptr, std::string()); 68 params.should_convert = false;
69 RunTest(params);
42 } 70 }
43 71
44 void ExpectFailure(const ArgumentSpec& spec, 72 void ExpectFailure(const ArgumentSpec& spec,
45 const std::string& script_source) { 73 const std::string& script_source,
46 RunTest(spec, script_source, true, TestResult::FAIL, std::string(), nullptr, 74 const std::string& expected_error) {
47 std::string()); 75 RunTestParams params(spec, script_source, TestResult::FAIL);
76 params.expected_error = expected_error;
77 RunTest(params);
48 } 78 }
49 79
50 void ExpectFailureWithNoConversion(const ArgumentSpec& spec, 80 void ExpectFailureWithNoConversion(const ArgumentSpec& spec,
51 const std::string& script_source) { 81 const std::string& script_source,
52 RunTest(spec, script_source, false, TestResult::FAIL, std::string(), 82 const std::string& expected_error) {
53 nullptr, std::string()); 83 RunTestParams params(spec, script_source, TestResult::FAIL);
84 params.should_convert = false;
85 params.expected_error = expected_error;
86 RunTest(params);
54 } 87 }
55 88
56 void ExpectThrow(const ArgumentSpec& spec, 89 void ExpectThrow(const ArgumentSpec& spec,
57 const std::string& script_source, 90 const std::string& script_source,
58 const std::string& expected_thrown_message) { 91 const std::string& expected_thrown_message) {
59 RunTest(spec, script_source, true, TestResult::THROW, std::string(), 92 RunTestParams params(spec, script_source, TestResult::THROW);
60 nullptr, expected_thrown_message); 93 params.expected_thrown_message = expected_thrown_message;
94 RunTest(params);
61 } 95 }
62 96
63 void AddTypeRef(const std::string& id, std::unique_ptr<ArgumentSpec> spec) { 97 void AddTypeRef(const std::string& id, std::unique_ptr<ArgumentSpec> spec) {
64 type_refs_.AddSpec(id, std::move(spec)); 98 type_refs_.AddSpec(id, std::move(spec));
65 } 99 }
66 100
67 private: 101 private:
68 enum class TestResult { PASS, FAIL, THROW, }; 102 void RunTest(const RunTestParams& params);
69
70 void RunTest(const ArgumentSpec& spec,
71 const std::string& script_source,
72 bool should_convert,
73 TestResult expected_result,
74 const std::string& expected_json,
75 const base::Value* expected_value,
76 const std::string& expected_thrown_message);
77 103
78 APITypeReferenceMap type_refs_; 104 APITypeReferenceMap type_refs_;
79 105
80 DISALLOW_COPY_AND_ASSIGN(ArgumentSpecUnitTest); 106 DISALLOW_COPY_AND_ASSIGN(ArgumentSpecUnitTest);
81 }; 107 };
82 108
83 void ArgumentSpecUnitTest::RunTest(const ArgumentSpec& spec, 109 void ArgumentSpecUnitTest::RunTest(const RunTestParams& params) {
84 const std::string& script_source,
85 bool should_convert,
86 TestResult expected_result,
87 const std::string& expected_json,
88 const base::Value* expected_value,
89 const std::string& expected_thrown_message) {
90 v8::Isolate* isolate = instance_->isolate(); 110 v8::Isolate* isolate = instance_->isolate();
91 v8::HandleScope handle_scope(instance_->isolate()); 111 v8::HandleScope handle_scope(instance_->isolate());
92 112
93 v8::Local<v8::Context> context = 113 v8::Local<v8::Context> context =
94 v8::Local<v8::Context>::New(instance_->isolate(), context_); 114 v8::Local<v8::Context>::New(instance_->isolate(), context_);
95 v8::TryCatch try_catch(isolate); 115 v8::TryCatch try_catch(isolate);
96 v8::Local<v8::Value> val = V8ValueFromScriptSource(context, script_source); 116 v8::Local<v8::Value> val =
97 ASSERT_FALSE(val.IsEmpty()) << script_source; 117 V8ValueFromScriptSource(context, params.script_source);
118 ASSERT_FALSE(val.IsEmpty()) << params.script_source;
98 119
99 std::string error; 120 std::string error;
100 std::unique_ptr<base::Value> out_value; 121 std::unique_ptr<base::Value> out_value;
101 bool did_succeed = 122 bool did_succeed = params.spec.ParseArgument(
102 spec.ParseArgument(context, val, type_refs_, 123 context, val, type_refs_, params.should_convert ? &out_value : nullptr,
103 should_convert ? &out_value : nullptr, &error); 124 &error);
104 bool should_succeed = expected_result == TestResult::PASS; 125 bool should_succeed = params.expected_result == TestResult::PASS;
105 ASSERT_EQ(should_succeed, did_succeed) << script_source << ", " << error; 126 ASSERT_EQ(should_succeed, did_succeed)
106 ASSERT_EQ(did_succeed && should_convert, !!out_value); 127 << params.script_source << ", " << error;
107 bool should_throw = expected_result == TestResult::THROW; 128 ASSERT_EQ(did_succeed && params.should_convert, !!out_value);
108 ASSERT_EQ(should_throw, try_catch.HasCaught()) << script_source; 129 bool should_throw = params.expected_result == TestResult::THROW;
109 if (should_succeed && should_convert) { 130 ASSERT_EQ(should_throw, try_catch.HasCaught()) << params.script_source;
131
132 if (!params.expected_error.empty())
133 EXPECT_EQ(params.expected_error, error) << params.script_source;
134
135 if (should_succeed && params.should_convert) {
110 ASSERT_TRUE(out_value); 136 ASSERT_TRUE(out_value);
111 if (expected_value) 137 if (params.expected_value)
112 EXPECT_TRUE(expected_value->Equals(out_value.get())) << script_source; 138 EXPECT_TRUE(params.expected_value->Equals(out_value.get()))
139 << params.script_source;
113 else 140 else
114 EXPECT_EQ(expected_json, ValueToString(*out_value)); 141 EXPECT_EQ(params.expected_json, ValueToString(*out_value));
115 } else if (should_throw) { 142 } else if (should_throw) {
116 EXPECT_EQ(expected_thrown_message, 143 EXPECT_EQ(params.expected_thrown_message,
117 gin::V8ToString(try_catch.Message()->Get())); 144 gin::V8ToString(try_catch.Message()->Get()));
118 } 145 }
119 } 146 }
120 147
121 TEST_F(ArgumentSpecUnitTest, Test) { 148 TEST_F(ArgumentSpecUnitTest, Test) {
149 using namespace api_errors;
150
122 { 151 {
123 ArgumentSpec spec(*ValueFromString("{'type': 'integer'}")); 152 ArgumentSpec spec(*ValueFromString("{'type': 'integer'}"));
124 ExpectSuccess(spec, "1", "1"); 153 ExpectSuccess(spec, "1", "1");
125 ExpectSuccess(spec, "-1", "-1"); 154 ExpectSuccess(spec, "-1", "-1");
126 ExpectSuccess(spec, "0", "0"); 155 ExpectSuccess(spec, "0", "0");
127 ExpectSuccess(spec, "0.0", "0"); 156 ExpectSuccess(spec, "0.0", "0");
128 ExpectFailure(spec, "undefined"); 157 ExpectFailure(spec, "undefined", InvalidType(kTypeInteger, kTypeUndefined));
129 ExpectFailure(spec, "null"); 158 ExpectFailure(spec, "null", InvalidType(kTypeInteger, kTypeNull));
130 ExpectFailure(spec, "1.1"); 159 ExpectFailure(spec, "1.1", InvalidType(kTypeInteger, kTypeDouble));
131 ExpectFailure(spec, "'foo'"); 160 ExpectFailure(spec, "'foo'", InvalidType(kTypeInteger, kTypeString));
132 ExpectFailure(spec, "'1'"); 161 ExpectFailure(spec, "'1'", InvalidType(kTypeInteger, kTypeString));
133 ExpectFailure(spec, "{}"); 162 ExpectFailure(spec, "({})", InvalidType(kTypeInteger, kTypeObject));
134 ExpectFailure(spec, "[1]"); 163 ExpectFailure(spec, "[1]", InvalidType(kTypeInteger, kTypeList));
135 } 164 }
136 165
137 { 166 {
138 ArgumentSpec spec(*ValueFromString("{'type': 'number'}")); 167 ArgumentSpec spec(*ValueFromString("{'type': 'number'}"));
139 ExpectSuccess(spec, "1", "1.0"); 168 ExpectSuccess(spec, "1", "1.0");
140 ExpectSuccess(spec, "-1", "-1.0"); 169 ExpectSuccess(spec, "-1", "-1.0");
141 ExpectSuccess(spec, "0", "0.0"); 170 ExpectSuccess(spec, "0", "0.0");
142 ExpectSuccess(spec, "1.1", "1.1"); 171 ExpectSuccess(spec, "1.1", "1.1");
143 ExpectSuccess(spec, "1.", "1.0"); 172 ExpectSuccess(spec, "1.", "1.0");
144 ExpectSuccess(spec, ".1", "0.1"); 173 ExpectSuccess(spec, ".1", "0.1");
145 ExpectFailure(spec, "undefined"); 174 ExpectFailure(spec, "undefined", InvalidType(kTypeDouble, kTypeUndefined));
146 ExpectFailure(spec, "null"); 175 ExpectFailure(spec, "null", InvalidType(kTypeDouble, kTypeNull));
147 ExpectFailure(spec, "'foo'"); 176 ExpectFailure(spec, "'foo'", InvalidType(kTypeDouble, kTypeString));
148 ExpectFailure(spec, "'1.1'"); 177 ExpectFailure(spec, "'1.1'", InvalidType(kTypeDouble, kTypeString));
149 ExpectFailure(spec, "{}"); 178 ExpectFailure(spec, "({})", InvalidType(kTypeDouble, kTypeObject));
150 ExpectFailure(spec, "[1.1]"); 179 ExpectFailure(spec, "[1.1]", InvalidType(kTypeDouble, kTypeList));
151 } 180 }
152 181
153 { 182 {
154 ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'minimum': 1}")); 183 ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'minimum': 1}"));
155 ExpectSuccess(spec, "2", "2"); 184 ExpectSuccess(spec, "2", "2");
156 ExpectSuccess(spec, "1", "1"); 185 ExpectSuccess(spec, "1", "1");
157 ExpectFailure(spec, "0"); 186 ExpectFailure(spec, "0", NumberTooSmall(1));
158 ExpectFailure(spec, "-1"); 187 ExpectFailure(spec, "-1", NumberTooSmall(1));
159 } 188 }
160 189
161 { 190 {
162 ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'maximum': 10}")); 191 ArgumentSpec spec(*ValueFromString("{'type': 'integer', 'maximum': 10}"));
163 ExpectSuccess(spec, "10", "10"); 192 ExpectSuccess(spec, "10", "10");
164 ExpectSuccess(spec, "1", "1"); 193 ExpectSuccess(spec, "1", "1");
165 ExpectFailure(spec, "11"); 194 ExpectFailure(spec, "11", NumberTooLarge(10));
166 } 195 }
167 196
168 { 197 {
169 ArgumentSpec spec(*ValueFromString("{'type': 'string'}")); 198 ArgumentSpec spec(*ValueFromString("{'type': 'string'}"));
170 ExpectSuccess(spec, "'foo'", "'foo'"); 199 ExpectSuccess(spec, "'foo'", "'foo'");
171 ExpectSuccess(spec, "''", "''"); 200 ExpectSuccess(spec, "''", "''");
172 ExpectFailure(spec, "1"); 201 ExpectFailure(spec, "1", InvalidType(kTypeString, kTypeInteger));
173 ExpectFailure(spec, "{}"); 202 ExpectFailure(spec, "({})", InvalidType(kTypeString, kTypeObject));
174 ExpectFailure(spec, "['foo']"); 203 ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
175 } 204 }
176 205
177 { 206 {
178 ArgumentSpec spec( 207 ArgumentSpec spec(
179 *ValueFromString("{'type': 'string', 'enum': ['foo', 'bar']}")); 208 *ValueFromString("{'type': 'string', 'enum': ['foo', 'bar']}"));
209 std::set<std::string> valid_enums = {"foo", "bar"};
180 ExpectSuccess(spec, "'foo'", "'foo'"); 210 ExpectSuccess(spec, "'foo'", "'foo'");
181 ExpectSuccess(spec, "'bar'", "'bar'"); 211 ExpectSuccess(spec, "'bar'", "'bar'");
182 ExpectFailure(spec, "['foo']"); 212 ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
183 ExpectFailure(spec, "'fo'"); 213 ExpectFailure(spec, "'fo'", InvalidEnumValue(valid_enums));
184 ExpectFailure(spec, "'foobar'"); 214 ExpectFailure(spec, "'foobar'", InvalidEnumValue(valid_enums));
185 ExpectFailure(spec, "'baz'"); 215 ExpectFailure(spec, "'baz'", InvalidEnumValue(valid_enums));
186 ExpectFailure(spec, "''"); 216 ExpectFailure(spec, "''", InvalidEnumValue(valid_enums));
187 } 217 }
188 218
189 { 219 {
190 ArgumentSpec spec(*ValueFromString( 220 ArgumentSpec spec(*ValueFromString(
191 "{'type': 'string', 'enum': [{'name': 'foo'}, {'name': 'bar'}]}")); 221 "{'type': 'string', 'enum': [{'name': 'foo'}, {'name': 'bar'}]}"));
222 std::set<std::string> valid_enums = {"foo", "bar"};
192 ExpectSuccess(spec, "'foo'", "'foo'"); 223 ExpectSuccess(spec, "'foo'", "'foo'");
193 ExpectSuccess(spec, "'bar'", "'bar'"); 224 ExpectSuccess(spec, "'bar'", "'bar'");
194 ExpectFailure(spec, "['foo']"); 225 ExpectFailure(spec, "['foo']", InvalidType(kTypeString, kTypeList));
195 ExpectFailure(spec, "'fo'"); 226 ExpectFailure(spec, "'fo'", InvalidEnumValue(valid_enums));
196 ExpectFailure(spec, "'foobar'"); 227 ExpectFailure(spec, "'foobar'", InvalidEnumValue(valid_enums));
197 ExpectFailure(spec, "'baz'"); 228 ExpectFailure(spec, "'baz'", InvalidEnumValue(valid_enums));
198 ExpectFailure(spec, "''"); 229 ExpectFailure(spec, "''", InvalidEnumValue(valid_enums));
199 } 230 }
200 231
201 { 232 {
202 ArgumentSpec spec(*ValueFromString("{'type': 'boolean'}")); 233 ArgumentSpec spec(*ValueFromString("{'type': 'boolean'}"));
203 ExpectSuccess(spec, "true", "true"); 234 ExpectSuccess(spec, "true", "true");
204 ExpectSuccess(spec, "false", "false"); 235 ExpectSuccess(spec, "false", "false");
205 ExpectFailure(spec, "1"); 236 ExpectFailure(spec, "1", InvalidType(kTypeBoolean, kTypeInteger));
206 ExpectFailure(spec, "'true'"); 237 ExpectFailure(spec, "'true'", InvalidType(kTypeBoolean, kTypeString));
207 ExpectFailure(spec, "null"); 238 ExpectFailure(spec, "null", InvalidType(kTypeBoolean, kTypeNull));
208 } 239 }
209 240
210 { 241 {
211 ArgumentSpec spec( 242 ArgumentSpec spec(
212 *ValueFromString("{'type': 'array', 'items': {'type': 'string'}}")); 243 *ValueFromString("{'type': 'array', 'items': {'type': 'string'}}"));
213 ExpectSuccess(spec, "[]", "[]"); 244 ExpectSuccess(spec, "[]", "[]");
214 ExpectSuccess(spec, "['foo']", "['foo']"); 245 ExpectSuccess(spec, "['foo']", "['foo']");
215 ExpectSuccess(spec, "['foo', 'bar']", "['foo','bar']"); 246 ExpectSuccess(spec, "['foo', 'bar']", "['foo','bar']");
216 ExpectSuccess(spec, "var x = new Array(); x[0] = 'foo'; x;", "['foo']"); 247 ExpectSuccess(spec, "var x = new Array(); x[0] = 'foo'; x;", "['foo']");
217 ExpectFailure(spec, "'foo'"); 248 ExpectFailure(spec, "'foo'", InvalidType(kTypeList, kTypeString));
218 ExpectFailure(spec, "[1, 2]"); 249 ExpectFailure(spec, "[1, 2]",
219 ExpectFailure(spec, "['foo', 1]"); 250 IndexError(0u, InvalidType(kTypeString, kTypeInteger)));
251 ExpectFailure(spec, "['foo', 1]",
252 IndexError(1u, InvalidType(kTypeString, kTypeInteger)));
220 ExpectFailure(spec, 253 ExpectFailure(spec,
221 "var x = ['a', 'b', 'c'];" 254 "var x = ['a', 'b', 'c'];"
222 "x[4] = 'd';" // x[3] is undefined, violating the spec. 255 "x[4] = 'd';" // x[3] is undefined, violating the spec.
223 "x;"); 256 "x;",
257 IndexError(3u, InvalidType(kTypeString, kTypeUndefined)));
224 ExpectThrow( 258 ExpectThrow(
225 spec, 259 spec,
226 "var x = [];" 260 "var x = [];"
227 "Object.defineProperty(" 261 "Object.defineProperty("
228 " x, 0," 262 " x, 0,"
229 " { get: () => { throw new Error('Badness'); } });" 263 " { get: () => { throw new Error('Badness'); } });"
230 "x;", 264 "x;",
231 "Uncaught Error: Badness"); 265 "Uncaught Error: Badness");
232 } 266 }
233 267
234 { 268 {
235 const char kObjectSpec[] = 269 const char kObjectSpec[] =
236 "{" 270 "{"
237 " 'type': 'object'," 271 " 'type': 'object',"
238 " 'properties': {" 272 " 'properties': {"
239 " 'prop1': {'type': 'string'}," 273 " 'prop1': {'type': 'string'},"
240 " 'prop2': {'type': 'integer', 'optional': true}" 274 " 'prop2': {'type': 'integer', 'optional': true}"
241 " }" 275 " }"
242 "}"; 276 "}";
243 ArgumentSpec spec(*ValueFromString(kObjectSpec)); 277 ArgumentSpec spec(*ValueFromString(kObjectSpec));
244 ExpectSuccess(spec, "({prop1: 'foo', prop2: 2})", 278 ExpectSuccess(spec, "({prop1: 'foo', prop2: 2})",
245 "{'prop1':'foo','prop2':2}"); 279 "{'prop1':'foo','prop2':2}");
246 ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}"); 280 ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}");
247 ExpectSuccess(spec, "({prop1: 'foo', prop2: null})", "{'prop1':'foo'}"); 281 ExpectSuccess(spec, "({prop1: 'foo', prop2: null})", "{'prop1':'foo'}");
248 ExpectSuccess(spec, "x = {}; x.prop1 = 'foo'; x;", "{'prop1':'foo'}"); 282 ExpectSuccess(spec, "x = {}; x.prop1 = 'foo'; x;", "{'prop1':'foo'}");
249 ExpectFailure(spec, "({prop1: 'foo', prop2: 'bar'})"); 283 ExpectFailure(
250 ExpectFailure(spec, "({prop2: 2})"); 284 spec, "({prop1: 'foo', prop2: 'bar'})",
285 PropertyError("prop2", InvalidType(kTypeInteger, kTypeString)));
286 ExpectFailure(spec, "({prop2: 2})", MissingRequiredProperty("prop1"));
251 // Unknown properties are not allowed. 287 // Unknown properties are not allowed.
252 ExpectFailure(spec, "({prop1: 'foo', prop2: 2, prop3: 'blah'})"); 288 ExpectFailure(spec, "({prop1: 'foo', prop2: 2, prop3: 'blah'})",
289 UnexpectedProperty("prop3"));
253 // We only consider properties on the object itself, not its prototype 290 // We only consider properties on the object itself, not its prototype
254 // chain. 291 // chain.
255 ExpectFailure(spec, 292 ExpectFailure(spec,
256 "function X() {}\n" 293 "function X() {}\n"
257 "X.prototype = { prop1: 'foo' };\n" 294 "X.prototype = { prop1: 'foo' };\n"
258 "var x = new X();\n" 295 "var x = new X();\n"
259 "x;"); 296 "x;",
297 MissingRequiredProperty("prop1"));
260 ExpectFailure(spec, 298 ExpectFailure(spec,
261 "function X() {}\n" 299 "function X() {}\n"
262 "X.prototype = { prop1: 'foo' };\n" 300 "X.prototype = { prop1: 'foo' };\n"
263 "function Y() { this.__proto__ = X.prototype; }\n" 301 "function Y() { this.__proto__ = X.prototype; }\n"
264 "var z = new Y();\n" 302 "var z = new Y();\n"
265 "z;"); 303 "z;",
304 MissingRequiredProperty("prop1"));
266 // Self-referential fun. Currently we don't have to worry about these much 305 // Self-referential fun. Currently we don't have to worry about these much
267 // because the spec won't match at some point (and V8ValueConverter has 306 // because the spec won't match at some point (and V8ValueConverter has
268 // cycle detection and will fail). 307 // cycle detection and will fail).
269 ExpectFailure(spec, "x = {}; x.prop1 = x; x;"); 308 ExpectFailure(
309 spec, "x = {}; x.prop1 = x; x;",
310 PropertyError("prop1", InvalidType(kTypeString, kTypeObject)));
270 ExpectThrow( 311 ExpectThrow(
271 spec, 312 spec,
272 "({ get prop1() { throw new Error('Badness'); }});", 313 "({ get prop1() { throw new Error('Badness'); }});",
273 "Uncaught Error: Badness"); 314 "Uncaught Error: Badness");
274 ExpectThrow(spec, 315 ExpectThrow(spec,
275 "x = {prop1: 'foo'};\n" 316 "x = {prop1: 'foo'};\n"
276 "Object.defineProperty(\n" 317 "Object.defineProperty(\n"
277 " x, 'prop2',\n" 318 " x, 'prop2',\n"
278 " {\n" 319 " {\n"
279 " get: () => { throw new Error('Badness'); },\n" 320 " get: () => { throw new Error('Badness'); },\n"
(...skipping 13 matching lines...) Expand all
293 } 334 }
294 335
295 { 336 {
296 const char kFunctionSpec[] = "{ 'type': 'function' }"; 337 const char kFunctionSpec[] = "{ 'type': 'function' }";
297 ArgumentSpec spec(*ValueFromString(kFunctionSpec)); 338 ArgumentSpec spec(*ValueFromString(kFunctionSpec));
298 // Functions are serialized as empty dictionaries. 339 // Functions are serialized as empty dictionaries.
299 ExpectSuccess(spec, "(function() {})", "{}"); 340 ExpectSuccess(spec, "(function() {})", "{}");
300 ExpectSuccessWithNoConversion(spec, "(function() {})"); 341 ExpectSuccessWithNoConversion(spec, "(function() {})");
301 ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })"); 342 ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })");
302 ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })"); 343 ExpectSuccessWithNoConversion(spec, "(function(a, b) { a(); b(); })");
303 ExpectFailureWithNoConversion(spec, "({a: function() {}})"); 344 ExpectFailureWithNoConversion(spec, "({a: function() {}})",
304 ExpectFailureWithNoConversion(spec, "([function() {}])"); 345 InvalidType(kTypeFunction, kTypeObject));
305 ExpectFailureWithNoConversion(spec, "1"); 346 ExpectFailureWithNoConversion(spec, "([function() {}])",
347 InvalidType(kTypeFunction, kTypeList));
348 ExpectFailureWithNoConversion(spec, "1",
349 InvalidType(kTypeFunction, kTypeInteger));
306 } 350 }
307 351
308 { 352 {
309 const char kBinarySpec[] = "{ 'type': 'binary' }"; 353 const char kBinarySpec[] = "{ 'type': 'binary' }";
310 ArgumentSpec spec(*ValueFromString(kBinarySpec)); 354 ArgumentSpec spec(*ValueFromString(kBinarySpec));
311 // Simple case: empty ArrayBuffer -> empty BinaryValue. 355 // Simple case: empty ArrayBuffer -> empty BinaryValue.
312 ExpectSuccess(spec, "(new ArrayBuffer())", 356 ExpectSuccess(spec, "(new ArrayBuffer())",
313 base::Value(base::Value::Type::BINARY)); 357 base::Value(base::Value::Type::BINARY));
314 { 358 {
315 // A non-empty (but zero-filled) ArrayBufferView. 359 // A non-empty (but zero-filled) ArrayBufferView.
(...skipping 11 matching lines...) Expand all
327 ASSERT_TRUE(expected_value); 371 ASSERT_TRUE(expected_value);
328 ExpectSuccess(spec, 372 ExpectSuccess(spec,
329 "var b = new ArrayBuffer(4);\n" 373 "var b = new ArrayBuffer(4);\n"
330 "var v = new Uint8Array(b);\n" 374 "var v = new Uint8Array(b);\n"
331 "var s = 'ping';\n" 375 "var s = 'ping';\n"
332 "for (var i = 0; i < s.length; ++i)\n" 376 "for (var i = 0; i < s.length; ++i)\n"
333 " v[i] = s.charCodeAt(i);\n" 377 " v[i] = s.charCodeAt(i);\n"
334 "b;", 378 "b;",
335 *expected_value); 379 *expected_value);
336 } 380 }
337 ExpectFailure(spec, "1"); 381 ExpectFailure(spec, "1", InvalidType(kTypeBinary, kTypeInteger));
338 } 382 }
339 { 383 {
340 const char kAnySpec[] = "{ 'type': 'any' }"; 384 const char kAnySpec[] = "{ 'type': 'any' }";
341 ArgumentSpec spec(*ValueFromString(kAnySpec)); 385 ArgumentSpec spec(*ValueFromString(kAnySpec));
342 ExpectSuccess(spec, "42", "42"); 386 ExpectSuccess(spec, "42", "42");
343 ExpectSuccess(spec, "'foo'", "'foo'"); 387 ExpectSuccess(spec, "'foo'", "'foo'");
344 ExpectSuccess(spec, "({prop1:'bar'})", "{'prop1':'bar'}"); 388 ExpectSuccess(spec, "({prop1:'bar'})", "{'prop1':'bar'}");
345 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]"); 389 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]");
346 ExpectSuccess(spec, "[1, 'a']", "[1,'a']"); 390 ExpectSuccess(spec, "[1, 'a']", "[1,'a']");
347 ExpectSuccess(spec, "null", base::Value()); 391 ExpectSuccess(spec, "null", base::Value());
348 ExpectSuccess(spec, "({prop1: 'alpha', prop2: null})", 392 ExpectSuccess(spec, "({prop1: 'alpha', prop2: null})",
349 "{'prop1':'alpha','prop2':null}"); 393 "{'prop1':'alpha','prop2':null}");
350 ExpectSuccess(spec, 394 ExpectSuccess(spec,
351 "x = {alpha: 'alpha'};\n" 395 "x = {alpha: 'alpha'};\n"
352 "y = {beta: 'beta', x: x};\n" 396 "y = {beta: 'beta', x: x};\n"
353 "y;", 397 "y;",
354 "{'beta':'beta','x':{'alpha':'alpha'}}"); 398 "{'beta':'beta','x':{'alpha':'alpha'}}");
355 // We don't serialize undefined. 399 // We don't serialize undefined.
356 // TODO(devlin): This matches current behavior, but should it? Part of the 400 // TODO(devlin): This matches current behavior, but should it? Part of the
357 // problem is that base::Values don't differentiate between undefined and 401 // problem is that base::Values don't differentiate between undefined and
358 // null, which is a potentially important distinction. However, this means 402 // null, which is a potentially important distinction. However, this means
359 // that in serialization of an object {a: 1, foo:undefined}, we lose the 403 // that in serialization of an object {a: 1, foo:undefined}, we lose the
360 // 'foo' property. 404 // 'foo' property.
361 ExpectFailure(spec, "undefined"); 405 ExpectFailure(spec, "undefined", UnserializableValue());
406
362 ExpectSuccess(spec, "({prop1: 1, prop2: undefined})", "{'prop1':1}"); 407 ExpectSuccess(spec, "({prop1: 1, prop2: undefined})", "{'prop1':1}");
363 } 408 }
364 } 409 }
365 410
366 TEST_F(ArgumentSpecUnitTest, TypeRefsTest) { 411 TEST_F(ArgumentSpecUnitTest, TypeRefsTest) {
412 using namespace api_errors;
367 const char kObjectType[] = 413 const char kObjectType[] =
368 "{" 414 "{"
369 " 'id': 'refObj'," 415 " 'id': 'refObj',"
370 " 'type': 'object'," 416 " 'type': 'object',"
371 " 'properties': {" 417 " 'properties': {"
372 " 'prop1': {'type': 'string'}," 418 " 'prop1': {'type': 'string'},"
373 " 'prop2': {'type': 'integer', 'optional': true}" 419 " 'prop2': {'type': 'integer', 'optional': true}"
374 " }" 420 " }"
375 "}"; 421 "}";
376 const char kEnumType[] = 422 const char kEnumType[] =
377 "{'id': 'refEnum', 'type': 'string', 'enum': ['alpha', 'beta']}"; 423 "{'id': 'refEnum', 'type': 'string', 'enum': ['alpha', 'beta']}";
378 AddTypeRef("refObj", 424 AddTypeRef("refObj",
379 base::MakeUnique<ArgumentSpec>(*ValueFromString(kObjectType))); 425 base::MakeUnique<ArgumentSpec>(*ValueFromString(kObjectType)));
380 AddTypeRef("refEnum", 426 AddTypeRef("refEnum",
381 base::MakeUnique<ArgumentSpec>(*ValueFromString(kEnumType))); 427 base::MakeUnique<ArgumentSpec>(*ValueFromString(kEnumType)));
428 std::set<std::string> valid_enums = {"alpha", "beta"};
382 429
383 { 430 {
384 const char kObjectWithRefEnumSpec[] = 431 const char kObjectWithRefEnumSpec[] =
385 "{" 432 "{"
386 " 'name': 'objWithRefEnum'," 433 " 'name': 'objWithRefEnum',"
387 " 'type': 'object'," 434 " 'type': 'object',"
388 " 'properties': {" 435 " 'properties': {"
389 " 'e': {'$ref': 'refEnum'}," 436 " 'e': {'$ref': 'refEnum'},"
390 " 'sub': {'type': 'integer'}" 437 " 'sub': {'type': 'integer'}"
391 " }" 438 " }"
392 "}"; 439 "}";
393 ArgumentSpec spec(*ValueFromString(kObjectWithRefEnumSpec)); 440 ArgumentSpec spec(*ValueFromString(kObjectWithRefEnumSpec));
394 ExpectSuccess(spec, "({e: 'alpha', sub: 1})", "{'e':'alpha','sub':1}"); 441 ExpectSuccess(spec, "({e: 'alpha', sub: 1})", "{'e':'alpha','sub':1}");
395 ExpectSuccess(spec, "({e: 'beta', sub: 1})", "{'e':'beta','sub':1}"); 442 ExpectSuccess(spec, "({e: 'beta', sub: 1})", "{'e':'beta','sub':1}");
396 ExpectFailure(spec, "({e: 'gamma', sub: 1})"); 443 ExpectFailure(spec, "({e: 'gamma', sub: 1})",
397 ExpectFailure(spec, "({e: 'alpha'})"); 444 PropertyError("e", InvalidEnumValue(valid_enums)));
445 ExpectFailure(spec, "({e: 'alpha'})", MissingRequiredProperty("sub"));
398 } 446 }
399 447
400 { 448 {
401 const char kObjectWithRefObjectSpec[] = 449 const char kObjectWithRefObjectSpec[] =
402 "{" 450 "{"
403 " 'name': 'objWithRefObject'," 451 " 'name': 'objWithRefObject',"
404 " 'type': 'object'," 452 " 'type': 'object',"
405 " 'properties': {" 453 " 'properties': {"
406 " 'o': {'$ref': 'refObj'}" 454 " 'o': {'$ref': 'refObj'}"
407 " }" 455 " }"
408 "}"; 456 "}";
409 ArgumentSpec spec(*ValueFromString(kObjectWithRefObjectSpec)); 457 ArgumentSpec spec(*ValueFromString(kObjectWithRefObjectSpec));
410 ExpectSuccess(spec, "({o: {prop1: 'foo'}})", "{'o':{'prop1':'foo'}}"); 458 ExpectSuccess(spec, "({o: {prop1: 'foo'}})", "{'o':{'prop1':'foo'}}");
411 ExpectSuccess(spec, "({o: {prop1: 'foo', prop2: 2}})", 459 ExpectSuccess(spec, "({o: {prop1: 'foo', prop2: 2}})",
412 "{'o':{'prop1':'foo','prop2':2}}"); 460 "{'o':{'prop1':'foo','prop2':2}}");
413 ExpectFailure(spec, "({o: {prop1: 1}})"); 461 ExpectFailure(
462 spec, "({o: {prop1: 1}})",
463 PropertyError("o", PropertyError("prop1", InvalidType(kTypeString,
464 kTypeInteger))));
414 } 465 }
415 466
416 { 467 {
417 const char kRefEnumListSpec[] = 468 const char kRefEnumListSpec[] =
418 "{'type': 'array', 'items': {'$ref': 'refEnum'}}"; 469 "{'type': 'array', 'items': {'$ref': 'refEnum'}}";
419 ArgumentSpec spec(*ValueFromString(kRefEnumListSpec)); 470 ArgumentSpec spec(*ValueFromString(kRefEnumListSpec));
420 ExpectSuccess(spec, "['alpha']", "['alpha']"); 471 ExpectSuccess(spec, "['alpha']", "['alpha']");
421 ExpectSuccess(spec, "['alpha', 'alpha']", "['alpha','alpha']"); 472 ExpectSuccess(spec, "['alpha', 'alpha']", "['alpha','alpha']");
422 ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']"); 473 ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']");
423 ExpectFailure(spec, "['alpha', 'beta', 'gamma']"); 474 ExpectFailure(spec, "['alpha', 'beta', 'gamma']",
475 IndexError(2u, InvalidEnumValue(valid_enums)));
424 } 476 }
425 } 477 }
426 478
427 TEST_F(ArgumentSpecUnitTest, TypeChoicesTest) { 479 TEST_F(ArgumentSpecUnitTest, TypeChoicesTest) {
480 using namespace api_errors;
428 { 481 {
429 const char kSimpleChoices[] = 482 const char kSimpleChoices[] =
430 "{'choices': [{'type': 'string'}, {'type': 'integer'}]}"; 483 "{'choices': [{'type': 'string'}, {'type': 'integer'}]}";
431 ArgumentSpec spec(*ValueFromString(kSimpleChoices)); 484 ArgumentSpec spec(*ValueFromString(kSimpleChoices));
432 ExpectSuccess(spec, "'alpha'", "'alpha'"); 485 ExpectSuccess(spec, "'alpha'", "'alpha'");
433 ExpectSuccess(spec, "42", "42"); 486 ExpectSuccess(spec, "42", "42");
434 ExpectFailure(spec, "true"); 487 ExpectFailure(spec, "true", InvalidChoice());
435 } 488 }
436 489
437 { 490 {
438 const char kComplexChoices[] = 491 const char kComplexChoices[] =
439 "{" 492 "{"
440 " 'choices': [" 493 " 'choices': ["
441 " {'type': 'array', 'items': {'type': 'string'}}," 494 " {'type': 'array', 'items': {'type': 'string'}},"
442 " {'type': 'object', 'properties': {'prop1': {'type': 'string'}}}" 495 " {'type': 'object', 'properties': {'prop1': {'type': 'string'}}}"
443 " ]" 496 " ]"
444 "}"; 497 "}";
445 ArgumentSpec spec(*ValueFromString(kComplexChoices)); 498 ArgumentSpec spec(*ValueFromString(kComplexChoices));
446 ExpectSuccess(spec, "['alpha']", "['alpha']"); 499 ExpectSuccess(spec, "['alpha']", "['alpha']");
447 ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']"); 500 ExpectSuccess(spec, "['alpha', 'beta']", "['alpha','beta']");
448 ExpectSuccess(spec, "({prop1: 'alpha'})", "{'prop1':'alpha'}"); 501 ExpectSuccess(spec, "({prop1: 'alpha'})", "{'prop1':'alpha'}");
449 ExpectFailure(spec, "({prop1: 1})"); 502 ExpectFailure(spec, "({prop1: 1})", InvalidChoice());
450 ExpectFailure(spec, "'alpha'"); 503 ExpectFailure(spec, "'alpha'", InvalidChoice());
451 ExpectFailure(spec, "42"); 504 ExpectFailure(spec, "42", InvalidChoice());
452 } 505 }
453 } 506 }
454 507
455 TEST_F(ArgumentSpecUnitTest, AdditionalPropertiesTest) { 508 TEST_F(ArgumentSpecUnitTest, AdditionalPropertiesTest) {
509 using namespace api_errors;
456 { 510 {
457 const char kOnlyAnyAdditionalProperties[] = 511 const char kOnlyAnyAdditionalProperties[] =
458 "{" 512 "{"
459 " 'type': 'object'," 513 " 'type': 'object',"
460 " 'additionalProperties': {'type': 'any'}" 514 " 'additionalProperties': {'type': 'any'}"
461 "}"; 515 "}";
462 ArgumentSpec spec(*ValueFromString(kOnlyAnyAdditionalProperties)); 516 ArgumentSpec spec(*ValueFromString(kOnlyAnyAdditionalProperties));
463 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 42, prop3: {foo: 'bar'}})", 517 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 42, prop3: {foo: 'bar'}})",
464 "{'prop1':'alpha','prop2':42,'prop3':{'foo':'bar'}}"); 518 "{'prop1':'alpha','prop2':42,'prop3':{'foo':'bar'}}");
465 ExpectSuccess(spec, "({})", "{}"); 519 ExpectSuccess(spec, "({})", "{}");
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 " 'properties': {" 580 " 'properties': {"
527 " 'prop1': {'type': 'string'}" 581 " 'prop1': {'type': 'string'}"
528 " }," 582 " },"
529 " 'additionalProperties': {'type': 'any'}" 583 " 'additionalProperties': {'type': 'any'}"
530 "}"; 584 "}";
531 ArgumentSpec spec(*ValueFromString(kPropertiesAndAnyAdditionalProperties)); 585 ArgumentSpec spec(*ValueFromString(kPropertiesAndAnyAdditionalProperties));
532 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 42, prop3: {foo: 'bar'}})", 586 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 42, prop3: {foo: 'bar'}})",
533 "{'prop1':'alpha','prop2':42,'prop3':{'foo':'bar'}}"); 587 "{'prop1':'alpha','prop2':42,'prop3':{'foo':'bar'}}");
534 // Additional properties are optional. 588 // Additional properties are optional.
535 ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}"); 589 ExpectSuccess(spec, "({prop1: 'foo'})", "{'prop1':'foo'}");
536 ExpectFailure(spec, "({prop2: 42, prop3: {foo: 'bar'}})"); 590 ExpectFailure(spec, "({prop2: 42, prop3: {foo: 'bar'}})",
537 ExpectFailure(spec, "({prop1: 42})"); 591 MissingRequiredProperty("prop1"));
592 ExpectFailure(
593 spec, "({prop1: 42})",
594 PropertyError("prop1", InvalidType(kTypeString, kTypeInteger)));
538 } 595 }
539 { 596 {
540 const char kTypedAdditionalProperties[] = 597 const char kTypedAdditionalProperties[] =
541 "{" 598 "{"
542 " 'type': 'object'," 599 " 'type': 'object',"
543 " 'additionalProperties': {'type': 'string'}" 600 " 'additionalProperties': {'type': 'string'}"
544 "}"; 601 "}";
545 ArgumentSpec spec(*ValueFromString(kTypedAdditionalProperties)); 602 ArgumentSpec spec(*ValueFromString(kTypedAdditionalProperties));
546 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 'beta', prop3: 'gamma'})", 603 ExpectSuccess(spec, "({prop1: 'alpha', prop2: 'beta', prop3: 'gamma'})",
547 "{'prop1':'alpha','prop2':'beta','prop3':'gamma'}"); 604 "{'prop1':'alpha','prop2':'beta','prop3':'gamma'}");
548 ExpectFailure(spec, "({prop1: 'alpha', prop2: 42})"); 605 ExpectFailure(
606 spec, "({prop1: 'alpha', prop2: 42})",
607 PropertyError("prop2", InvalidType(kTypeString, kTypeInteger)));
549 } 608 }
550 } 609 }
551 610
552 TEST_F(ArgumentSpecUnitTest, InstanceOfTest) { 611 TEST_F(ArgumentSpecUnitTest, InstanceOfTest) {
612 using namespace api_errors;
553 { 613 {
554 const char kInstanceOfRegExp[] = 614 const char kInstanceOfRegExp[] =
555 "{" 615 "{"
556 " 'type': 'object'," 616 " 'type': 'object',"
557 " 'isInstanceOf': 'RegExp'" 617 " 'isInstanceOf': 'RegExp'"
558 "}"; 618 "}";
559 ArgumentSpec spec(*ValueFromString(kInstanceOfRegExp)); 619 ArgumentSpec spec(*ValueFromString(kInstanceOfRegExp));
560 ExpectSuccess(spec, "(new RegExp())", "{}"); 620 ExpectSuccess(spec, "(new RegExp())", "{}");
561 ExpectSuccess(spec, "({ __proto__: RegExp.prototype })", "{}"); 621 ExpectSuccess(spec, "({ __proto__: RegExp.prototype })", "{}");
562 ExpectSuccess(spec, 622 ExpectSuccess(spec,
563 "(function() {\n" 623 "(function() {\n"
564 " function subRegExp() {}\n" 624 " function subRegExp() {}\n"
565 " subRegExp.prototype = { __proto__: RegExp.prototype };\n" 625 " subRegExp.prototype = { __proto__: RegExp.prototype };\n"
566 " return new subRegExp();\n" 626 " return new subRegExp();\n"
567 "})()", 627 "})()",
568 "{}"); 628 "{}");
569 ExpectSuccess(spec, 629 ExpectSuccess(spec,
570 "(function() {\n" 630 "(function() {\n"
571 " function RegExp() {}\n" 631 " function RegExp() {}\n"
572 " return new RegExp();\n" 632 " return new RegExp();\n"
573 "})()", 633 "})()",
574 "{}"); 634 "{}");
575 ExpectFailure(spec, "({})"); 635 ExpectFailure(spec, "({})", NotAnInstance("RegExp"));
576 ExpectFailure(spec, "('')"); 636 ExpectFailure(spec, "('')", InvalidType("RegExp", kTypeString));
577 ExpectFailure(spec, "('.*')"); 637 ExpectFailure(spec, "('.*')", InvalidType("RegExp", kTypeString));
578 ExpectFailure(spec, "({ __proto__: Date.prototype })"); 638 ExpectFailure(spec, "({ __proto__: Date.prototype })",
639 NotAnInstance("RegExp"));
579 } 640 }
580 641
581 { 642 {
582 const char kInstanceOfCustomClass[] = 643 const char kInstanceOfCustomClass[] =
583 "{" 644 "{"
584 " 'type': 'object'," 645 " 'type': 'object',"
585 " 'isInstanceOf': 'customClass'" 646 " 'isInstanceOf': 'customClass'"
586 "}"; 647 "}";
587 ArgumentSpec spec(*ValueFromString(kInstanceOfCustomClass)); 648 ArgumentSpec spec(*ValueFromString(kInstanceOfCustomClass));
588 ExpectSuccess(spec, 649 ExpectSuccess(spec,
589 "(function() {\n" 650 "(function() {\n"
590 " function customClass() {}\n" 651 " function customClass() {}\n"
591 " return new customClass();\n" 652 " return new customClass();\n"
592 "})()", 653 "})()",
593 "{}"); 654 "{}");
594 ExpectSuccess(spec, 655 ExpectSuccess(spec,
595 "(function() {\n" 656 "(function() {\n"
596 " function customClass() {}\n" 657 " function customClass() {}\n"
597 " function otherClass() {}\n" 658 " function otherClass() {}\n"
598 " otherClass.prototype = \n" 659 " otherClass.prototype = \n"
599 " { __proto__: customClass.prototype };\n" 660 " { __proto__: customClass.prototype };\n"
600 " return new otherClass();\n" 661 " return new otherClass();\n"
601 "})()", 662 "})()",
602 "{}"); 663 "{}");
603 ExpectFailure(spec, "({})"); 664 ExpectFailure(spec, "({})", NotAnInstance("customClass"));
604 ExpectFailure(spec, 665 ExpectFailure(spec,
605 "(function() {\n" 666 "(function() {\n"
606 " function otherClass() {}\n" 667 " function otherClass() {}\n"
607 " return new otherClass();\n" 668 " return new otherClass();\n"
608 "})()"); 669 "})()",
670 NotAnInstance("customClass"));
609 } 671 }
610 } 672 }
611 673
612 TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) { 674 TEST_F(ArgumentSpecUnitTest, MinAndMaxLengths) {
675 using namespace api_errors;
613 { 676 {
614 const char kMinLengthString[] = "{'type': 'string', 'minLength': 3}"; 677 const char kMinLengthString[] = "{'type': 'string', 'minLength': 3}";
615 ArgumentSpec spec(*ValueFromString(kMinLengthString)); 678 ArgumentSpec spec(*ValueFromString(kMinLengthString));
616 ExpectSuccess(spec, "'aaa'", "'aaa'"); 679 ExpectSuccess(spec, "'aaa'", "'aaa'");
617 ExpectSuccess(spec, "'aaaa'", "'aaaa'"); 680 ExpectSuccess(spec, "'aaaa'", "'aaaa'");
618 ExpectFailure(spec, "'aa'"); 681 ExpectFailure(spec, "'aa'", TooFewStringChars(3, 2));
619 ExpectFailure(spec, "''"); 682 ExpectFailure(spec, "''", TooFewStringChars(3, 0));
620 } 683 }
621 684
622 { 685 {
623 const char kMaxLengthString[] = "{'type': 'string', 'maxLength': 3}"; 686 const char kMaxLengthString[] = "{'type': 'string', 'maxLength': 3}";
624 ArgumentSpec spec(*ValueFromString(kMaxLengthString)); 687 ArgumentSpec spec(*ValueFromString(kMaxLengthString));
625 ExpectSuccess(spec, "'aaa'", "'aaa'"); 688 ExpectSuccess(spec, "'aaa'", "'aaa'");
626 ExpectSuccess(spec, "'aa'", "'aa'"); 689 ExpectSuccess(spec, "'aa'", "'aa'");
627 ExpectSuccess(spec, "''", "''"); 690 ExpectSuccess(spec, "''", "''");
628 ExpectFailure(spec, "'aaaa'"); 691 ExpectFailure(spec, "'aaaa'", TooManyStringChars(3, 4));
629 } 692 }
630 693
631 { 694 {
632 const char kMinLengthArray[] = 695 const char kMinLengthArray[] =
633 "{'type': 'array', 'items': {'type': 'integer'}, 'minItems': 3}"; 696 "{'type': 'array', 'items': {'type': 'integer'}, 'minItems': 3}";
634 ArgumentSpec spec(*ValueFromString(kMinLengthArray)); 697 ArgumentSpec spec(*ValueFromString(kMinLengthArray));
635 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]"); 698 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]");
636 ExpectSuccess(spec, "[1, 2, 3, 4]", "[1,2,3,4]"); 699 ExpectSuccess(spec, "[1, 2, 3, 4]", "[1,2,3,4]");
637 ExpectFailure(spec, "[1, 2]"); 700 ExpectFailure(spec, "[1, 2]", TooFewArrayItems(3, 2));
638 ExpectFailure(spec, "[]"); 701 ExpectFailure(spec, "[]", TooFewArrayItems(3, 0));
639 } 702 }
640 703
641 { 704 {
642 const char kMaxLengthArray[] = 705 const char kMaxLengthArray[] =
643 "{'type': 'array', 'items': {'type': 'integer'}, 'maxItems': 3}"; 706 "{'type': 'array', 'items': {'type': 'integer'}, 'maxItems': 3}";
644 ArgumentSpec spec(*ValueFromString(kMaxLengthArray)); 707 ArgumentSpec spec(*ValueFromString(kMaxLengthArray));
645 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]"); 708 ExpectSuccess(spec, "[1, 2, 3]", "[1,2,3]");
646 ExpectSuccess(spec, "[1, 2]", "[1,2]"); 709 ExpectSuccess(spec, "[1, 2]", "[1,2]");
647 ExpectSuccess(spec, "[]", "[]"); 710 ExpectSuccess(spec, "[]", "[]");
648 ExpectFailure(spec, "[1, 2, 3, 4]"); 711 ExpectFailure(spec, "[1, 2, 3, 4]", TooManyArrayItems(3, 4));
649 } 712 }
650 } 713 }
651 714
652 } // namespace extensions 715 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/argument_spec.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698