buffet: Cleanup GCD command definition type system.

Moved a lot of duplicated code for different parameter types
into base classes. Split ParamType::FromJson into three separate
function (FromJson, ObjectSchemaFromJson, ConstraintsFromJson)
which allows more fine-grained control of deserializing various
pieces of schema amongst the members of type class hierarchy.
This way, "enum" constraint (applicable to all types) can be
handled in a base class while concrete type-specific properties
will be read in respective top-level classes.

Added error checking for invalid/unexpected object schema
properties when parsing type definition. This allows correct
reporting of unrecognized properties, as well as nice errors
when incompatible properties are specified (e.g. both "enum" and
"min/max" constraints at the same time).

BUG=chromium:374860
TEST=All unit tests pass.

Change-Id: I18b94338680b9b859ba964fd63b65273ca2521f6
Reviewed-on: https://chromium-review.googlesource.com/204971
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/buffet/commands/object_schema_unittest.cc b/buffet/commands/object_schema_unittest.cc
index be93073..64f4600 100644
--- a/buffet/commands/object_schema_unittest.cc
+++ b/buffet/commands/object_schema_unittest.cc
@@ -857,5 +857,21 @@
                                &error));
   EXPECT_EQ("type_mismatch", error->GetFirstError()->GetCode());
   error.reset();
+
+  schema_str = "{"
+  "'param1':{'minimum':1, 'enum':[1,2,3]}"  // can't have min/max & enum.
+  "}";
+  EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
+                               &error));
+  EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
+  error.reset();
+
+  schema_str = "{"
+  "'param1':{'maximum':1, 'blah':2}"  // 'blah' is unexpected.
+  "}";
+  EXPECT_FALSE(schema.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
+                               &error));
+  EXPECT_EQ("unexpected_parameter", error->GetFirstError()->GetCode());
+  error.reset();
 }