buffet: Add inheritance command parameters, progress and result

Redefinition of standard commands may omit parameters, progress or
result. In case if property is omitted, definition from base will be
used.

BUG=brillo:808
TEST=`FEATURES=test emerge-gizmo buffet`

Change-Id: I157b939d0ab6ccf16289c64720a2322378c9be32
Reviewed-on: https://chromium-review.googlesource.com/274232
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/buffet/commands/command_dictionary.cc b/buffet/commands/command_dictionary.cc
index 4f66c7d..2de0f36 100644
--- a/buffet/commands/command_dictionary.cc
+++ b/buffet/commands/command_dictionary.cc
@@ -196,6 +196,8 @@
   const base::DictionaryValue* schema_def = nullptr;
   if (!command_def_json->GetDictionaryWithoutPathExpansion(property_name,
                                                            &schema_def)) {
+    if (base_def)
+      return base_def->Clone();
     return object_schema;
   }
 
diff --git a/buffet/commands/command_dictionary_unittest.cc b/buffet/commands/command_dictionary_unittest.cc
index aeae236..7b649a5 100644
--- a/buffet/commands/command_dictionary_unittest.cc
+++ b/buffet/commands/command_dictionary_unittest.cc
@@ -58,6 +58,47 @@
   EXPECT_EQ(expected_commands, dict.GetCommandNamesByCategory("powerd"));
 }
 
+TEST(CommandDictionary, LoadWithInheritance) {
+  auto json = CreateDictionaryValue(R"({
+    'robot': {
+      'jump': {
+        'minimalRole': 'viewer',
+        'visibility':'local',
+        'parameters': {
+          'height': 'integer'
+        },
+        'progress': {
+          'progress': 'integer'
+        },
+        'results': {
+          'success': 'boolean'
+        }
+      }
+    }
+  })");
+  CommandDictionary base_dict;
+  EXPECT_TRUE(base_dict.LoadCommands(*json, "test1", nullptr, nullptr));
+  EXPECT_EQ(1, base_dict.GetSize());
+  json = CreateDictionaryValue(R"({'robot': {'jump': {}}})");
+
+  CommandDictionary dict;
+  EXPECT_TRUE(dict.LoadCommands(*json, "test2", &base_dict, nullptr));
+  EXPECT_EQ(1, dict.GetSize());
+
+  auto cmd = dict.FindCommand("robot.jump");
+  EXPECT_NE(nullptr, cmd);
+
+  EXPECT_EQ("local", cmd->GetVisibility().ToString());
+  EXPECT_EQ(UserRole::kViewer, cmd->GetMinimalRole());
+
+  EXPECT_JSON_EQ("{'height': {'type': 'integer'}}",
+                 *cmd->GetParameters()->ToJson(true, nullptr));
+  EXPECT_JSON_EQ("{'progress': {'type': 'integer'}}",
+                 *cmd->GetProgress()->ToJson(true, nullptr));
+  EXPECT_JSON_EQ("{'success': {'type': 'boolean'}}",
+                 *cmd->GetResults()->ToJson(true, nullptr));
+}
+
 TEST(CommandDictionary, LoadCommands_Failures) {
   CommandDictionary dict;
   chromeos::ErrorPtr error;
diff --git a/buffet/etc/buffet/commands/buffet.json b/buffet/etc/buffet/commands/buffet.json
index 612c59b..4196a22 100644
--- a/buffet/etc/buffet/commands/buffet.json
+++ b/buffet/etc/buffet/commands/buffet.json
@@ -1,20 +1,6 @@
 {
   "base": {
-    "updateBaseConfiguration": {
-      "parameters": {
-        "localDiscoveryEnabled": "boolean",
-        "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
-        "localPairingEnabled": "boolean"
-      },
-      "results": {}
-    },
-
-    "updateDeviceInfo": {
-      "parameters": {
-        "description": "string",
-        "name": "string"
-      },
-      "results": {}
-    }
+    "updateBaseConfiguration": { },
+    "updateDeviceInfo": { }
   }
 }