1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file.
4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/policy/core/common/schema.h"
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/strings/stringprintf.h"
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "components/policy/core/common/schema_internal.h"
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace policy {
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace {
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#define TestSchemaValidation(a, b, c, d) \
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidationHelper(          \
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        base::StringPrintf("%s:%i", __FILE__, __LINE__), a, b, c, d)
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kTestSchema[] =
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "{"
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "  \"type\": \"object\","
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "  \"properties\": {"
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Boolean\": { \"type\": \"boolean\" },"
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Integer\": { \"type\": \"integer\" },"
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Null\": { \"type\": \"null\" },"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Number\": { \"type\": \"number\" },"
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"String\": { \"type\": \"string\" },"
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Array\": {"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"type\": \"array\","
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"items\": { \"type\": \"string\" }"
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    },"
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"ArrayOfObjects\": {"
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"type\": \"array\","
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"items\": {"
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"type\": \"object\","
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"properties\": {"
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "          \"one\": { \"type\": \"string\" },"
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "          \"two\": { \"type\": \"integer\" }"
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        }"
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      }"
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    },"
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"ArrayOfArray\": {"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"type\": \"array\","
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"items\": {"
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"type\": \"array\","
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"items\": { \"type\": \"string\" }"
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      }"
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    },"
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    \"Object\": {"
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"type\": \"object\","
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"properties\": {"
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"one\": { \"type\": \"boolean\" },"
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "        \"two\": { \"type\": \"integer\" }"
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      },"
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "      \"additionalProperties\": { \"type\": \"string\" }"
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"ObjectOfObject\": {"
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"object\","
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"properties\": {"
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        \"Object\": {"
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          \"type\": \"object\","
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          \"properties\": {"
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "            \"one\": { \"type\": \"string\" },"
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "            \"two\": { \"type\": \"integer\" }"
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          }"
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        }"
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      }"
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"IntegerWithEnums\": {"
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"integer\","
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"enum\": [1, 2, 3]"
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"IntegerWithEnumsGaps\": {"
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"integer\","
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"enum\": [10, 20, 30]"
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"StringWithEnums\": {"
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"string\","
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"enum\": [\"one\", \"two\", \"three\"]"
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"IntegerWithRange\": {"
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"integer\","
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"minimum\": 1,"
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"maximum\": 3"
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"ObjectOfArray\": {"
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"object\","
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"properties\": {"
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        \"List\": {"
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          \"type\": \"array\","
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          \"items\": { \"type\": \"integer\" }"
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        }"
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      }"
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    },"
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "    \"ArrayOfObjectOfArray\": {"
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"type\": \"array\","
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      \"items\": {"
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        \"type\": \"object\","
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        \"properties\": {"
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          \"List\": {"
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "            \"type\": \"array\","
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "            \"items\": { \"type\": \"string\" }"
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "          }"
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "        }"
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "      }"
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "    },"
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "    \"StringWithPattern\": {"
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      \"type\": \"string\","
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      \"pattern\": \"^foo+$\""
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "    },"
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "    \"ObjectWithPatternProperties\": {"
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      \"type\": \"object\","
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      \"patternProperties\": {"
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "        \"^foo+$\": { \"type\": \"integer\" },"
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "        \"^bar+$\": {"
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "          \"type\": \"string\","
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "          \"enum\": [\"one\", \"two\"]"
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "        }"
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      },"
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      \"properties\": {"
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "        \"bar\": {"
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "          \"type\": \"string\","
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "          \"enum\": [\"one\", \"three\"]"
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "        }"
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "      }"
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "    }"
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "  }"
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    "}";
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool ParseFails(const std::string& content) {
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string error;
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Parse(content, &error);
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (schema.valid())
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(error.empty());
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return true;
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid TestSchemaValidationHelper(const std::string& source,
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                Schema schema,
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                const base::Value& value,
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                SchemaOnErrorStrategy strategy,
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                bool expected_return_value) {
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string error;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const char kNoErrorReturned[] = "No error returned.";
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Test that Schema::Validate() works as expected.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = kNoErrorReturned;
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool returned = schema.Validate(value, strategy, NULL, &error);
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_EQ(expected_return_value, returned) << source << ": " << error;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Test that Schema::Normalize() will return the same value as
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Schema::Validate().
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  error = kNoErrorReturned;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::Value> cloned_value(value.DeepCopy());
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool touched = false;
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  returned =
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      schema.Normalize(cloned_value.get(), strategy, NULL, &error, &touched);
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(expected_return_value, returned) << source << ": " << error;
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool strictly_valid = schema.Validate(value, SCHEMA_STRICT, NULL, &error);
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(touched, !strictly_valid && returned) << source;
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Test that Schema::Normalize() have actually dropped invalid and unknown
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // properties.
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (expected_return_value) {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    EXPECT_TRUE(
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        schema.Validate(*cloned_value.get(), SCHEMA_STRICT, NULL, &error))
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << source;
171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    EXPECT_TRUE(
172c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        schema.Normalize(cloned_value.get(), SCHEMA_STRICT, NULL, &error, NULL))
173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << source;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TestSchemaValidationWithPath(Schema schema,
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  const base::Value& value,
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  const std::string& expected_failure_path) {
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string error_path = "NOT_SET";
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string error;
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool returned = schema.Validate(value, SCHEMA_STRICT, &error_path, &error);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_FALSE(returned) << error_path;
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ(error_path, expected_failure_path);
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string SchemaObjectWrapper(const std::string& subschema) {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return "{"
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         "  \"type\": \"object\","
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         "  \"properties\": {"
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         "    \"SomePropertyName\":" + subschema +
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         "  }"
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         "}";
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST(SchemaTest, MinimalSchema) {
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_FALSE(ParseFails("{ \"type\": \"object\" }"));
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST(SchemaTest, InvalidSchemas) {
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(""));
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("omg"));
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("\"omg\""));
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("123"));
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("[]"));
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("null"));
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails("{}"));
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        "\"additionalProperties\": { \"type\":\"object\" }"
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}"));
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"patternProperties\": { \"a+b*\": { \"type\": \"object\" } }"
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}"));
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": { \"Policy\": { \"type\": \"bogus\" } }"
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}"));
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": { \"Policy\": { \"type\": [\"string\", \"number\"] } }"
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}"));
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(ParseFails(
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": { \"Policy\": { \"type\": \"any\" } }"
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}"));
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": { \"Policy\": 123 }"
246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
247a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_FALSE(ParseFails(
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"unknown attribute\": \"is ignored\""
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST(SchemaTest, Ownership) {
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string error;
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Parse(
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": {"
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"sub\": {"
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"type\": \"object\","
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"properties\": {"
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "        \"subsub\": { \"type\": \"string\" }"
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      }"
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  }"
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}", &error);
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema = schema.GetKnownProperty("sub");
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid());
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Schema::Iterator it = schema.GetPropertiesIterator();
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ASSERT_FALSE(it.IsAtEnd());
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_STREQ("subsub", it.key());
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    schema = it.schema();
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    it.Advance();
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_TRUE(it.IsAtEnd());
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid());
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, schema.type());
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // This test shouldn't leak nor use invalid memory.
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST(SchemaTest, ValidSchema) {
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string error;
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Parse(kTestSchema, &error);
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetProperty("invalid").valid());
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Schema sub = schema.GetProperty("Boolean");
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, sub.type());
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("Integer");
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_INTEGER, sub.type());
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("Null");
309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_NULL, sub.type());
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("Number");
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_DOUBLE, sub.type());
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("String");
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, sub.type());
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("Array");
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, sub.type());
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = sub.GetItems();
324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, sub.type());
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("ArrayOfObjects");
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, sub.type());
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = sub.GetItems();
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_DICTIONARY, sub.type());
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Schema subsub = sub.GetProperty("one");
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, subsub.type());
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  subsub = sub.GetProperty("two");
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_INTEGER, subsub.type());
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  subsub = sub.GetProperty("invalid");
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(subsub.valid());
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("ArrayOfArray");
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, sub.type());
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = sub.GetItems();
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, sub.type());
348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = sub.GetItems();
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, sub.type());
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  sub = schema.GetProperty("Object");
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, sub.type());
355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  subsub = sub.GetProperty("one");
356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, subsub.type());
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  subsub = sub.GetProperty("two");
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_INTEGER, subsub.type());
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  subsub = sub.GetProperty("undeclared");
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_STRING, subsub.type());
364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sub = schema.GetProperty("IntegerWithEnums");
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(sub.valid());
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_INTEGER, sub.type());
3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sub = schema.GetProperty("IntegerWithEnumsGaps");
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(sub.valid());
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_INTEGER, sub.type());
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sub = schema.GetProperty("StringWithEnums");
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(sub.valid());
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_STRING, sub.type());
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  sub = schema.GetProperty("IntegerWithRange");
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_TRUE(sub.valid());
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_INTEGER, sub.type());
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  sub = schema.GetProperty("StringWithPattern");
382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(sub.valid());
383c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_EQ(base::Value::TYPE_STRING, sub.type());
384c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
385c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  sub = schema.GetProperty("ObjectWithPatternProperties");
386c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(sub.valid());
387c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_EQ(base::Value::TYPE_DICTIONARY, sub.type());
388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct {
390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const char* expected_key;
391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::Value::Type expected_type;
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } kExpectedProperties[] = {
393c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Array",                       base::Value::TYPE_LIST },
394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ArrayOfArray",                base::Value::TYPE_LIST },
395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ArrayOfObjectOfArray",        base::Value::TYPE_LIST },
396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ArrayOfObjects",              base::Value::TYPE_LIST },
397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Boolean",                     base::Value::TYPE_BOOLEAN },
398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Integer",                     base::Value::TYPE_INTEGER },
399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "IntegerWithEnums",            base::Value::TYPE_INTEGER },
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "IntegerWithEnumsGaps",        base::Value::TYPE_INTEGER },
401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "IntegerWithRange",            base::Value::TYPE_INTEGER },
402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Null",                        base::Value::TYPE_NULL },
403c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Number",                      base::Value::TYPE_DOUBLE },
404c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "Object",                      base::Value::TYPE_DICTIONARY },
405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ObjectOfArray",               base::Value::TYPE_DICTIONARY },
406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ObjectOfObject",              base::Value::TYPE_DICTIONARY },
407c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "ObjectWithPatternProperties", base::Value::TYPE_DICTIONARY },
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "String",                      base::Value::TYPE_STRING },
409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "StringWithEnums",             base::Value::TYPE_STRING },
410c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "StringWithPattern",           base::Value::TYPE_STRING },
411d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Schema::Iterator it = schema.GetPropertiesIterator();
413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpectedProperties); ++i) {
414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_FALSE(it.IsAtEnd());
415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_STREQ(kExpectedProperties[i].expected_key, it.key());
416d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_TRUE(it.schema().valid());
417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kExpectedProperties[i].expected_type, it.schema().type());
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    it.Advance();
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(it.IsAtEnd());
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)TEST(SchemaTest, Lookups) {
424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string error;
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Parse("{ \"type\": \"object\" }", &error);
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // This empty schema should never find named properties.
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("").valid());
432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(schema.GetPropertiesIterator().IsAtEnd());
434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema = Schema::Parse(
436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": {"
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"Boolean\": { \"type\": \"boolean\" }"
440f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  }"
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}", &error);
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("").valid());
446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(schema.GetKnownProperty("Boolean").valid());
448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  schema = Schema::Parse(
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "{"
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"type\": \"object\","
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"properties\": {"
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"bb\" : { \"type\": \"null\" },"
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"aa\" : { \"type\": \"boolean\" },"
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"abab\" : { \"type\": \"string\" },"
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"ab\" : { \"type\": \"number\" },"
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    \"aba\" : { \"type\": \"integer\" }"
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  }"
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      "}", &error);
460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("").valid());
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_FALSE(schema.GetKnownProperty("xyz").valid());
465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct {
467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const char* expected_key;
468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    base::Value::Type expected_type;
469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  } kExpectedKeys[] = {
470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { "aa",     base::Value::TYPE_BOOLEAN },
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { "ab",     base::Value::TYPE_DOUBLE },
472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { "aba",    base::Value::TYPE_INTEGER },
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { "abab",   base::Value::TYPE_STRING },
474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    { "bb",     base::Value::TYPE_NULL },
475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpectedKeys); ++i) {
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Schema sub = schema.GetKnownProperty(kExpectedKeys[i].expected_key);
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_TRUE(sub.valid());
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    EXPECT_EQ(kExpectedKeys[i].expected_type, sub.type());
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST(SchemaTest, Wrap) {
484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const internal::SchemaNode kSchemas[] = {
485c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_DICTIONARY,   0 },    //  0: root node
486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_BOOLEAN,      -1 },   //  1
487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_INTEGER,      -1 },   //  2
488c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_DOUBLE,       -1 },   //  3
489c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_STRING,       -1 },   //  4
490c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_LIST,         4 },    //  5: list of strings.
491c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_LIST,         5 },    //  6: list of lists of strings.
492c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_INTEGER,      0 },    //  7: integer enumerations.
493c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_INTEGER,      1 },    //  8: ranged integers.
494c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_STRING,       2 },    //  9: string enumerations.
495c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { base::Value::TYPE_STRING,       3 },    // 10: string with pattern.
496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  const internal::PropertyNode kPropertyNodes[] = {
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "Boolean",   1 },  // 0
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "Integer",   2 },  // 1
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "Number",    3 },  // 2
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "String",    4 },  // 3
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "List",      5 },  // 4
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "IntEnum",   7 },  // 5
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "RangedInt", 8 },  // 6
5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "StrEnum",   9 },  // 7
507c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "StrPat",   10 },  // 8
508c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "bar+$",     4 },  // 9
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const internal::PropertiesNode kProperties[] = {
512c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // 0 to 9 (exclusive) are the known properties in kPropertyNodes, 9 is
513c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // patternProperties and 6 is the additionalProperties node.
514c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { 0, 9, 10, 6 },
5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const internal::RestrictionNode kRestriction[] = {
518c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    {{0, 3}},  // 0: [1, 2, 3]
519c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    {{5, 1}},  // 1: minimum = 1, maximum = 5
520c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    {{0, 3}},  // 2: ["one", "two", "three"]
521c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    {{3, 3}},  // 3: pattern "foo+"
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int kIntEnums[] = {1, 2, 3};
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char* kStringEnums[] = {
527c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "one",    // 0
528c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "two",    // 1
529c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "three",  // 2
530c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    "foo+",   // 3
531d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
532d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
533f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const internal::SchemaData kData = {
534f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    kSchemas,
535f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    kPropertyNodes,
536f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    kProperties,
5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    kRestriction,
5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    kIntEnums,
5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    kStringEnums,
540d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  };
541d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
542f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Wrap(&kData);
543d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ASSERT_TRUE(schema.valid());
544d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
545d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
546f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  struct {
547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char* key;
548f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::Value::Type type;
549f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } kExpectedProperties[] = {
550f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    { "Boolean", base::Value::TYPE_BOOLEAN },
551f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    { "Integer", base::Value::TYPE_INTEGER },
552f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    { "Number", base::Value::TYPE_DOUBLE },
553f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    { "String", base::Value::TYPE_STRING },
554f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    { "List", base::Value::TYPE_LIST },
5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "IntEnum", base::Value::TYPE_INTEGER },
5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    { "RangedInt", base::Value::TYPE_INTEGER },
557c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "StrEnum", base::Value::TYPE_STRING },
558c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    { "StrPat", base::Value::TYPE_STRING },
559f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
560f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
561d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  Schema::Iterator it = schema.GetPropertiesIterator();
562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExpectedProperties); ++i) {
563d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_FALSE(it.IsAtEnd());
564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_STREQ(kExpectedProperties[i].key, it.key());
565d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    Schema sub = it.schema();
566d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ASSERT_TRUE(sub.valid());
567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_EQ(kExpectedProperties[i].type, sub.type());
568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (sub.type() == base::Value::TYPE_LIST) {
570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      Schema items = sub.GetItems();
571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ASSERT_TRUE(items.valid());
572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      EXPECT_EQ(base::Value::TYPE_STRING, items.type());
573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
575d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    it.Advance();
576d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
577d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  EXPECT_TRUE(it.IsAtEnd());
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema sub = schema.GetAdditionalProperties();
580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(sub.valid());
581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, sub.type());
582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema subsub = sub.GetItems();
583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(subsub.valid());
584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, subsub.type());
585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema subsubsub = subsub.GetItems();
586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(subsubsub.valid());
587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_STRING, subsubsub.type());
588c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
589c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  SchemaList schema_list = schema.GetPatternProperties("barr");
590c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_EQ(1u, schema_list.size());
591c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  sub = schema_list[0];
592c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ASSERT_TRUE(sub.valid());
593c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_EQ(base::Value::TYPE_STRING, sub.type());
594c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
595c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(schema.GetPatternProperties("ba").empty());
596c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  EXPECT_TRUE(schema.GetPatternProperties("bar+$").empty());
597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST(SchemaTest, Validate) {
600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string error;
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Schema schema = Schema::Parse(kTestSchema, &error);
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::DictionaryValue bundle;
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wrong type, expected integer.
608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetBoolean("Integer", true);
6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wrong type, expected list of strings.
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Clear();
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ListValue list;
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.AppendInteger(1);
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("Array", list.DeepCopy());
6175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Wrong type in a sub-object.
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Clear();
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue dict;
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetString("one", "one");
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("Object", dict.DeepCopy());
6265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Unknown name.
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.Clear();
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetBoolean("Unknown", true);
6325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // All of these will be valid.
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.Clear();
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetBoolean("Boolean", true);
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetInteger("Integer", 123);
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.Set("Null", base::Value::CreateNullValue());
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bundle.Set("Number", new base::FundamentalValue(3.14));
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetString("String", "omg");
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ListValue list;
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.AppendString("a string");
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.AppendString("another string");
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("Array", list.DeepCopy());
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue dict;
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetString("one", "string");
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetInteger("two", 2);
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ListValue list;
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.Append(dict.DeepCopy());
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.Append(dict.DeepCopy());
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("ArrayOfObjects", list.DeepCopy());
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ListValue list;
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.AppendString("a string");
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    list.AppendString("another string");
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::ListValue listlist;
664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    listlist.Append(list.DeepCopy());
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    listlist.Append(list.DeepCopy());
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("ArrayOfArray", listlist.DeepCopy());
667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
669f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  {
670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::DictionaryValue dict;
671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetBoolean("one", true);
672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetInteger("two", 2);
673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetString("additionally", "a string");
674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    dict.SetString("and also", "another string");
675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bundle.Set("Object", dict.DeepCopy());
676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
677f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnums", 1);
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 20);
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetString("StringWithEnums", "two");
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithRange", 3);
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
6845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnums", 0);
6865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnums", 1);
6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 0);
6905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
6915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 9);
6925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
6935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 10);
6945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
6955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 11);
6965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 19);
6985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
6995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 21);
7005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 29);
7025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 30);
7045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
7055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 31);
7065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 100);
7085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithEnumsGaps", 20);
7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetString("StringWithEnums", "FOUR");
7125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetString("StringWithEnums", "two");
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithRange", 4);
7165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("IntegerWithRange", 3);
7185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Unknown top level property.
720f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bundle.SetString("boom", "bang");
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_UNKNOWN, true);
7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidationWithPath(schema, bundle, "");
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.Remove("boom", NULL);
7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Invalid top level property.
7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("Boolean", 12345);
7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, false);
7305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_ALLOW_INVALID, true);
7325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidationWithPath(schema, bundle, "Boolean");
7335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetBoolean("Boolean", true);
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tests on ObjectOfObject.
7365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
7375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Schema subschema = schema.GetProperty("ObjectOfObject");
7385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(subschema.valid());
7395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue root;
7405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Unknown property.
7425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.SetBoolean("Object.three", false);
7435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
7445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
7455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
7465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
7475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
7485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "Object");
7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Remove("Object.three", NULL);
7505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Invalid property.
7525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.SetInteger("Object.one", 12345);
7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
7545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
7555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
7575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
7585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "Object.one");
7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Remove("Object.one", NULL);
7605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tests on ArrayOfObjects.
7635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Schema subschema = schema.GetProperty("ArrayOfObjects");
7655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(subschema.valid());
7665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue root;
7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Unknown property.
7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict_value = new base::DictionaryValue();
7705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict_value->SetBoolean("three", true);
7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Append(dict_value);  // Pass ownership to root.
7725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
7745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
7765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
7775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "items[0]");
7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Remove(root.GetSize() - 1, NULL);
7795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Invalid property.
7815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict_value = new base::DictionaryValue();
7825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict_value->SetBoolean("two", true);
7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Append(dict_value);  // Pass ownership to root.
7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
7855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
7865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "items[0].two");
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Remove(root.GetSize() - 1, NULL);
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tests on ObjectOfArray.
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Schema subschema = schema.GetProperty("ObjectOfArray");
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(subschema.valid());
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue root;
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* list_value = new base::ListValue();
8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Set("List", list_value);  // Pass ownership to root.
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Test that there are not errors here.
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    list_value->Append(new base::FundamentalValue(12345));
8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Invalid list item.
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    list_value->Append(new base::StringValue("blabla"));
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "List.items[1]");
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Tests on ArrayOfObjectOfArray.
8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  {
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    Schema subschema = schema.GetProperty("ArrayOfObjectOfArray");
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ASSERT_TRUE(subschema.valid());
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue root;
8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::ListValue* list_value = new base::ListValue();
8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* dict_value = new base::DictionaryValue();
8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict_value->Set("List", list_value);  // Pass ownership to dict_value.
8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    root.Append(dict_value);  // Pass ownership to root.
8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Test that there are not errors here.
8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    list_value->Append(new base::StringValue("blabla"));
8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, true);
8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Invalid list item.
8405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    list_value->Append(new base::FundamentalValue(12345));
8415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
8425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN_TOPLEVEL, false);
8435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, false);
8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID_TOPLEVEL, true);
8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_INVALID, true);
8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TestSchemaValidationWithPath(subschema, root, "items[0].List.items[1]");
8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
849c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Tests on StringWithPattern.
850c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  {
851c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Schema subschema = schema.GetProperty("StringWithPattern");
852c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_TRUE(subschema.valid());
853c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
854c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(
855c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        subschema, base::StringValue("foobar"), SCHEMA_STRICT, false);
856c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(
857c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        subschema, base::StringValue("foo"), SCHEMA_STRICT, true);
858c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(
859c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        subschema, base::StringValue("fo"), SCHEMA_STRICT, false);
860c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(
861c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        subschema, base::StringValue("fooo"), SCHEMA_STRICT, true);
862c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(
863c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        subschema, base::StringValue("^foo+$"), SCHEMA_STRICT, false);
864c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
865c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
866c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Tests on ObjectWithPatternProperties.
867c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  {
868c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Schema subschema = schema.GetProperty("ObjectWithPatternProperties");
869c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_TRUE(subschema.valid());
870c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::DictionaryValue root;
871c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
872c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetPatternProperties("fooo").size());
873c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetPatternProperties("foo").size());
874c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetPatternProperties("barr").size());
875c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetPatternProperties("bar").size());
876c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetMatchingProperties("fooo").size());
877c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetMatchingProperties("foo").size());
878c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(1u, subschema.GetMatchingProperties("barr").size());
879c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_EQ(2u, subschema.GetMatchingProperties("bar").size());
880c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ASSERT_TRUE(subschema.GetPatternProperties("foobar").empty());
881c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
882c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetInteger("fooo", 123);
883c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
884c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetBoolean("fooo", false);
885c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
886c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.Remove("fooo", NULL);
887c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
888c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetInteger("foo", 123);
889c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
890c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetBoolean("foo", false);
891c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
892c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.Remove("foo", NULL);
893c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
894c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetString("barr", "one");
895c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
896c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetString("barr", "three");
897c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
898c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetBoolean("barr", false);
899c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
900c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.Remove("barr", NULL);
901c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
902c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetString("bar", "one");
903c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, true);
904c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetString("bar", "two");
905c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
906c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetString("bar", "three");
907c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
908c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.Remove("bar", NULL);
909c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
910c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.SetInteger("foobar", 123);
911c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_STRICT, false);
912c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    TestSchemaValidation(subschema, root, SCHEMA_ALLOW_UNKNOWN, true);
913c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    root.Remove("foobar", NULL);
914c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
915c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Test that integer to double promotion is allowed.
9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bundle.SetInteger("Number", 31415);
9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestSchemaValidation(schema, bundle, SCHEMA_STRICT, true);
919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
921a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(SchemaTest, InvalidReferences) {
922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // References to undeclared schemas fail.
923a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
924a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
925a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
926a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
927a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"name\": { \"$ref\": \"undeclared\" }"
928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
929a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
930a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
931a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Can't refer to self.
932a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
933a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
934a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
936a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"name\": {"
937a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"self\","
938a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"$ref\": \"self\""
939a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    }"
940a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
941a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
942a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
943a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Duplicated IDs are invalid.
944a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
945a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
946a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
947a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"name\": {"
949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"x\","
950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"string\""
951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    },"
952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"another\": {"
953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"x\","
954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"string\""
955a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    }"
956a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
957a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
958a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
959a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Main object can't be a reference.
960a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
961a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
962a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
963a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"id\": \"main\","
964a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"$ref\": \"main\""
965a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
966a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
967a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(
968a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
969a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
970a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"$ref\": \"main\""
971a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}"));
972a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
973a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
974a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(SchemaTest, RecursiveReferences) {
975a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Verifies that references can go to a parent schema, to define a
976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // recursive type.
977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string error;
978a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema schema = Schema::Parse(
979a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
981a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"bookmarks\": {"
983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"array\","
984a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"ListOfBookmarks\","
985a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"items\": {"
986a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "        \"type\": \"object\","
987a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "        \"properties\": {"
988a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "          \"name\": { \"type\": \"string\" },"
989a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "          \"url\": { \"type\": \"string\" },"
990a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "          \"children\": { \"$ref\": \"ListOfBookmarks\" }"
991a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "        }"
992a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      }"
993a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    }"
994a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
995a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}", &error);
996a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
997a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
998a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema parent = schema.GetKnownProperty("bookmarks");
1000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(parent.valid());
1001a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, parent.type());
1002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Check the recursive type a number of times.
1004a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (int i = 0; i < 10; ++i) {
1005a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Schema items = parent.GetItems();
1006a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(items.valid());
1007a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(base::Value::TYPE_DICTIONARY, items.type());
1008a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Schema prop = items.GetKnownProperty("name");
1010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(prop.valid());
1011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(base::Value::TYPE_STRING, prop.type());
1012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    prop = items.GetKnownProperty("url");
1014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(prop.valid());
1015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(base::Value::TYPE_STRING, prop.type());
1016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    prop = items.GetKnownProperty("children");
1018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(prop.valid());
1019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(base::Value::TYPE_LIST, prop.type());
1020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    parent = prop;
1022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1024a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(SchemaTest, UnorderedReferences) {
1026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Verifies that references and IDs can come in any order.
1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string error;
1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema schema = Schema::Parse(
1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"a\": { \"$ref\": \"shared\" },"
1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"b\": { \"$ref\": \"shared\" },"
1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"c\": { \"$ref\": \"shared\" },"
1035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"d\": { \"$ref\": \"shared\" },"
1036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"e\": {"
1037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"boolean\","
1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"shared\""
1039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    },"
1040a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"f\": { \"$ref\": \"shared\" },"
1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"g\": { \"$ref\": \"shared\" },"
1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"h\": { \"$ref\": \"shared\" },"
1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"i\": { \"$ref\": \"shared\" }"
1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}", &error);
1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
1047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (char c = 'a'; c <= 'i'; ++c) {
1050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Schema sub = schema.GetKnownProperty(std::string(1, c));
1051a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_TRUE(sub.valid()) << c;
1052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ASSERT_EQ(base::Value::TYPE_BOOLEAN, sub.type()) << c;
1053a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1054d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1055d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1056a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(SchemaTest, AdditionalPropertiesReference) {
1057a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Verifies that "additionalProperties" can be a reference.
1058a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string error;
1059a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema schema = Schema::Parse(
1060a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
1061a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
1062a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
1063a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"policy\": {"
1064a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"object\","
1065a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"properties\": {"
1066a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "        \"foo\": {"
1067a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "          \"type\": \"boolean\","
1068a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "          \"id\": \"FooId\""
1069a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "        }"
1070a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      },"
1071a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"additionalProperties\": { \"$ref\": \"FooId\" }"
1072a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    }"
1073a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
1074a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}", &error);
1075a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
1076a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
1077a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1078a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema policy = schema.GetKnownProperty("policy");
1079a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(policy.valid());
1080a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, policy.type());
1081a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1082a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema foo = policy.GetKnownProperty("foo");
1083a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(foo.valid());
1084a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, foo.type());
1085a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1086a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema additional = policy.GetAdditionalProperties();
1087a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(additional.valid());
1088a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, additional.type());
1089a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1090a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema x = policy.GetProperty("x");
1091a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(x.valid());
1092a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, x.type());
1093a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1094a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1095a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TEST(SchemaTest, ItemsReference) {
1096a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Verifies that "items" can be a reference.
1097a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string error;
1098a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema schema = Schema::Parse(
1099a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "{"
1100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"type\": \"object\","
1101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  \"properties\": {"
1102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"foo\": {"
1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"boolean\","
1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"id\": \"FooId\""
1105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    },"
1106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    \"list\": {"
1107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"type\": \"array\","
1108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "      \"items\": { \"$ref\": \"FooId\" }"
1109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "    }"
1110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "  }"
1111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      "}", &error);
1112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(schema.valid()) << error;
1113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema.type());
1114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema foo = schema.GetKnownProperty("foo");
1116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(foo.valid());
1117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EXPECT_EQ(base::Value::TYPE_BOOLEAN, foo.type());
1118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema list = schema.GetKnownProperty("list");
1120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(list.valid());
1121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_LIST, list.type());
1122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  Schema items = list.GetItems();
1124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_TRUE(items.valid());
1125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ASSERT_EQ(base::Value::TYPE_BOOLEAN, items.type());
1126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(SchemaTest, EnumerationRestriction) {
11295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Enum attribute is a list.
11305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(SchemaObjectWrapper(
11315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"string\","
11335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"enum\": 12"
11345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Empty enum attributes is not allowed.
11375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(SchemaObjectWrapper(
11385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"integer\","
11405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"enum\": []"
11415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Enum elements type should be same as stated.
11445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(SchemaObjectWrapper(
11455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"string\","
11475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"enum\": [1, 2, 3]"
11485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(ParseFails(SchemaObjectWrapper(
11515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"integer\","
11535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"enum\": [1, 2, 3]"
11545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(ParseFails(SchemaObjectWrapper(
11575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"string\","
11595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"enum\": [\"1\", \"2\", \"3\"]"
11605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
11625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST(SchemaTest, RangedRestriction) {
11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_TRUE(ParseFails(SchemaObjectWrapper(
11655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"integer\","
11675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"minimum\": 10,"
11685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"maximum\": 5"
11695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
11715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_FALSE(ParseFails(SchemaObjectWrapper(
11725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "{"
11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"type\": \"integer\","
11745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"minimum\": 10,"
11755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "  \"maximum\": 20"
11765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "}")));
11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}  // namespace policy
1180