1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "tools/json_schema_compiler/test/error_generation.h"
6
7#include "base/json/json_writer.h"
8#include "base/strings/utf_string_conversions.h"
9#include "testing/gtest/include/gtest/gtest.h"
10#include "tools/json_schema_compiler/test/test_util.h"
11
12using namespace test::api::error_generation;
13using base::FundamentalValue;
14using json_schema_compiler::test_util::Dictionary;
15using json_schema_compiler::test_util::List;
16
17template <typename T>
18base::string16 GetPopulateError(const base::Value& value) {
19  base::string16 error;
20  T test_type;
21  T::Populate(value, &test_type, &error);
22  return error;
23}
24
25testing::AssertionResult EqualsUtf16(const std::string& expected,
26                                     const base::string16& actual) {
27  if (base::ASCIIToUTF16(expected) != actual)
28    return testing::AssertionFailure() << expected << " != " << actual;
29  return testing::AssertionSuccess();
30}
31
32// GenerateTypePopulate errors
33
34TEST(JsonSchemaCompilerErrorTest, RequiredPropertyPopulate) {
35  {
36    scoped_ptr<base::DictionaryValue> value = Dictionary(
37        "string", new base::StringValue("bling"));
38    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<TestType>(*value)));
39  }
40  {
41    scoped_ptr<base::BinaryValue> value(new base::BinaryValue());
42    EXPECT_TRUE(EqualsUtf16("expected dictionary, got binary",
43        GetPopulateError<TestType>(*value)));
44  }
45}
46
47TEST(JsonSchemaCompilerErrorTest, UnexpectedTypePopulation) {
48  {
49    scoped_ptr<base::ListValue> value(new base::ListValue());
50    EXPECT_TRUE(EqualsUtf16("",
51        GetPopulateError<ChoiceType::Integers>(*value)));
52  }
53  {
54    scoped_ptr<base::BinaryValue> value(new base::BinaryValue());
55    EXPECT_TRUE(EqualsUtf16("expected integers or integer, got binary",
56        GetPopulateError<ChoiceType::Integers>(*value)));
57  }
58}
59
60// GenerateTypePopulateProperty errors
61
62TEST(JsonSchemaCompilerErrorTest, TypeIsRequired) {
63  {
64    scoped_ptr<base::DictionaryValue> value = Dictionary(
65        "integers", new FundamentalValue(5));
66    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<ChoiceType>(*value)));
67  }
68  {
69    scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
70    EXPECT_TRUE(EqualsUtf16("'integers' is required",
71        GetPopulateError<ChoiceType>(*value)));
72  }
73}
74
75// GenerateParamsCheck errors
76
77TEST(JsonSchemaCompilerErrorTest, TooManyParameters) {
78  {
79    scoped_ptr<base::ListValue> params_value = List(
80        new FundamentalValue(5));
81    base::string16 error;
82    EXPECT_TRUE(TestFunction::Params::Create(*params_value, &error));
83  }
84  {
85    scoped_ptr<base::ListValue> params_value = List(
86        new FundamentalValue(5),
87        new FundamentalValue(5));
88    base::string16 error;
89    EXPECT_FALSE(TestFunction::Params::Create(*params_value, &error));
90    EXPECT_TRUE(EqualsUtf16("expected 1 arguments, got 2", error));
91  }
92}
93
94// GenerateFunctionParamsCreate errors
95
96TEST(JsonSchemaCompilerErrorTest, ParamIsRequired) {
97  {
98    scoped_ptr<base::ListValue> params_value = List(
99        new FundamentalValue(5));
100    base::string16 error;
101    EXPECT_TRUE(TestFunction::Params::Create(*params_value, &error));
102  }
103  {
104    scoped_ptr<base::ListValue> params_value = List(
105        base::Value::CreateNullValue());
106    base::string16 error;
107    EXPECT_FALSE(TestFunction::Params::Create(*params_value, &error));
108    EXPECT_TRUE(EqualsUtf16("'num' is required", error));
109  }
110}
111
112// GeneratePopulateVariableFromValue errors
113
114TEST(JsonSchemaCompilerErrorTest, WrongPropertyValueType) {
115  {
116    scoped_ptr<base::DictionaryValue> value = Dictionary(
117      "string", new base::StringValue("yes"));
118    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<TestType>(*value)));
119  }
120  {
121    scoped_ptr<base::DictionaryValue> value = Dictionary(
122        "string", new FundamentalValue(1.1));
123    EXPECT_TRUE(EqualsUtf16("'string': expected string, got number",
124        GetPopulateError<TestType>(*value)));
125  }
126}
127
128TEST(JsonSchemaCompilerErrorTest, WrongParameterCreationType) {
129  {
130    base::string16 error;
131    scoped_ptr<base::ListValue> params_value = List(
132        new base::StringValue("Yeah!"));
133    EXPECT_TRUE(TestString::Params::Create(*params_value, &error));
134  }
135  {
136    scoped_ptr<base::ListValue> params_value = List(
137        new FundamentalValue(5));
138    base::string16 error;
139    EXPECT_FALSE(TestTypeInObject::Params::Create(*params_value, &error));
140    EXPECT_TRUE(EqualsUtf16("'paramObject': expected dictionary, got integer",
141        error));
142  }
143}
144
145TEST(JsonSchemaCompilerErrorTest, WrongTypeValueType) {
146  {
147    scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
148    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<ObjectType>(*value)));
149  }
150  {
151    scoped_ptr<base::DictionaryValue> value = Dictionary(
152        "otherType", new FundamentalValue(1.1));
153    ObjectType out;
154    base::string16 error;
155    EXPECT_TRUE(ObjectType::Populate(*value, &out, &error));
156    EXPECT_TRUE(EqualsUtf16("'otherType': expected dictionary, got number",
157        error));
158    EXPECT_EQ(NULL, out.other_type.get());
159  }
160}
161
162TEST(JsonSchemaCompilerErrorTest, UnableToPopulateArray) {
163  {
164    scoped_ptr<base::ListValue> params_value = List(
165        new FundamentalValue(5));
166    EXPECT_TRUE(EqualsUtf16("",
167        GetPopulateError<ChoiceType::Integers>(*params_value)));
168  }
169  {
170    scoped_ptr<base::ListValue> params_value = List(
171        new FundamentalValue(5),
172        new FundamentalValue(false));
173    EXPECT_TRUE(EqualsUtf16("unable to populate array 'integers'",
174        GetPopulateError<ChoiceType::Integers>(*params_value)));
175  }
176}
177
178TEST(JsonSchemaCompilerErrorTest, BinaryTypeExpected) {
179  {
180    scoped_ptr<base::DictionaryValue> value = Dictionary(
181        "data", new base::BinaryValue());
182    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<BinaryData>(*value)));
183  }
184  {
185    scoped_ptr<base::DictionaryValue> value = Dictionary(
186        "data", new FundamentalValue(1.1));
187    EXPECT_TRUE(EqualsUtf16("'data': expected binary, got number",
188        GetPopulateError<BinaryData>(*value)));
189  }
190}
191
192TEST(JsonSchemaCompilerErrorTest, ListExpected) {
193  {
194    scoped_ptr<base::DictionaryValue> value = Dictionary(
195        "TheArray", new base::ListValue());
196    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<ArrayObject>(*value)));
197  }
198  {
199    scoped_ptr<base::DictionaryValue> value = Dictionary(
200        "TheArray", new FundamentalValue(5));
201    EXPECT_TRUE(EqualsUtf16("'TheArray': expected list, got integer",
202        GetPopulateError<ArrayObject>(*value)));
203  }
204}
205
206// GenerateStringToEnumConversion errors
207
208TEST(JsonSchemaCompilerErrorTest, BadEnumValue) {
209  {
210    scoped_ptr<base::DictionaryValue> value = Dictionary(
211        "enumeration", new base::StringValue("one"));
212    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<HasEnumeration>(*value)));
213  }
214  {
215    scoped_ptr<base::DictionaryValue> value = Dictionary(
216        "enumeration", new base::StringValue("bad sauce"));
217    EXPECT_TRUE(EqualsUtf16("'Enumeration': expected \"one\" or \"two\" "
218              "or \"three\", got \"bad sauce\"",
219        GetPopulateError<HasEnumeration>(*value)));
220  }
221}
222
223// Warn but don't fail out errors
224
225TEST(JsonSchemaCompilerErrorTest, WarnOnOptionalFailure) {
226  {
227    scoped_ptr<base::DictionaryValue> value = Dictionary(
228        "string", new base::StringValue("bling"));
229    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<OptionalTestType>(*value)));
230  }
231  {
232    scoped_ptr<base::DictionaryValue> value = Dictionary(
233        "string", new base::FundamentalValue(1));
234
235    OptionalTestType out;
236    base::string16 error;
237    EXPECT_TRUE(OptionalTestType::Populate(*value, &out, &error));
238    EXPECT_TRUE(EqualsUtf16("'string': expected string, got integer",
239        error));
240    EXPECT_EQ(NULL, out.string.get());
241  }
242}
243
244TEST(JsonSchemaCompilerErrorTest, OptionalBinaryTypeFailure) {
245  {
246    scoped_ptr<base::DictionaryValue> value = Dictionary(
247        "data", new base::BinaryValue());
248    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<OptionalBinaryData>(*value)));
249  }
250  {
251    // There's a bug with silent failures if the key doesn't exist.
252    scoped_ptr<base::DictionaryValue> value = Dictionary("data",
253        new base::FundamentalValue(1));
254
255    OptionalBinaryData out;
256    base::string16 error;
257    EXPECT_TRUE(OptionalBinaryData::Populate(*value, &out, &error));
258    EXPECT_TRUE(EqualsUtf16("'data': expected binary, got integer",
259        error));
260    EXPECT_EQ(NULL, out.data.get());
261  }
262}
263
264TEST(JsonSchemaCompilerErrorTest, OptionalArrayTypeFailure) {
265  {
266    scoped_ptr<base::DictionaryValue> value = Dictionary(
267        "TheArray", new base::ListValue());
268    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<ArrayObject>(*value)));
269  }
270  {
271    scoped_ptr<base::DictionaryValue> value = Dictionary(
272        "TheArray", new FundamentalValue(5));
273    ArrayObject out;
274    base::string16 error;
275    EXPECT_TRUE(ArrayObject::Populate(*value, &out, &error));
276    EXPECT_TRUE(EqualsUtf16("'TheArray': expected list, got integer",
277        error));
278    EXPECT_EQ(NULL, out.the_array.get());
279  }
280}
281
282TEST(JsonSchemaCompilerErrorTest, OptionalUnableToPopulateArray) {
283  {
284    scoped_ptr<base::ListValue> params_value = List(
285        new FundamentalValue(5));
286    EXPECT_TRUE(EqualsUtf16("",
287        GetPopulateError<OptionalChoiceType::Integers>(*params_value)));
288  }
289  {
290    scoped_ptr<base::ListValue> params_value = List(
291        new FundamentalValue(5),
292        new FundamentalValue(false));
293    OptionalChoiceType::Integers out;
294    base::string16 error;
295    EXPECT_TRUE(OptionalChoiceType::Integers::Populate(*params_value, &out,
296        &error));
297    EXPECT_TRUE(EqualsUtf16("unable to populate array 'integers'",
298        error));
299    EXPECT_EQ(NULL, out.as_integer.get());
300  }
301}
302
303TEST(JsonSchemaCompilerErrorTest, MultiplePopulationErrors) {
304  {
305
306    scoped_ptr<base::DictionaryValue> value = Dictionary(
307        "TheArray", new FundamentalValue(5));
308    ArrayObject out;
309    base::string16 error;
310    EXPECT_TRUE(ArrayObject::Populate(*value, &out, &error));
311    EXPECT_TRUE(EqualsUtf16("'TheArray': expected list, got integer",
312        error));
313    EXPECT_EQ(NULL, out.the_array.get());
314
315    EXPECT_TRUE(ArrayObject::Populate(*value, &out, &error));
316    EXPECT_TRUE(EqualsUtf16("'TheArray': expected list, got integer; "
317        "'TheArray': expected list, got integer",
318        error));
319    EXPECT_EQ(NULL, out.the_array.get());
320  }
321}
322
323TEST(JsonSchemaCompilerErrorTest, TooManyKeys) {
324  {
325    scoped_ptr<base::DictionaryValue> value = Dictionary(
326      "string", new base::StringValue("yes"));
327    EXPECT_TRUE(EqualsUtf16("", GetPopulateError<TestType>(*value)));
328  }
329  {
330    scoped_ptr<base::DictionaryValue> value = Dictionary(
331        "string", new base::StringValue("yes"),
332        "ohno", new base::StringValue("many values"));
333    EXPECT_TRUE(EqualsUtf16("found unexpected key 'ohno'",
334        GetPopulateError<TestType>(*value)));
335  }
336}
337