libweave: Cleanup creation of PropValues
Hide some constructors and test only methods.
BUG=brillo:1246
TEST='FEATURES=test emerge-gizmo buffet'
Change-Id: I1343809f94999795f8f162e3464ac22413b0dbd5
Reviewed-on: https://chromium-review.googlesource.com/289645
Reviewed-by: Vitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Vitaly Buka <vitalybuka@chromium.org>
Tested-by: Vitaly Buka <vitalybuka@chromium.org>
diff --git a/libweave/src/commands/object_schema_unittest.cc b/libweave/src/commands/object_schema_unittest.cc
index 018c28f..fc04dd5 100644
--- a/libweave/src/commands/object_schema_unittest.cc
+++ b/libweave/src/commands/object_schema_unittest.cc
@@ -47,6 +47,13 @@
return GetArrayValues<T>(one_of->set_.value);
}
+bool ValidateValue(const PropType& type,
+ const base::Value& value,
+ chromeos::ErrorPtr* error) {
+ std::unique_ptr<PropValue> val = type.CreatePropValue(value, error);
+ return val != nullptr;
+}
+
} // anonymous namespace
TEST(CommandSchema, IntPropType_Empty) {
@@ -123,31 +130,31 @@
IntPropType prop;
prop.AddMinMaxConstraint(2, 4);
chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-1").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("0").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("0"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("2").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("2"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("3").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("3"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("4").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("4"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("5").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("5"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
}
@@ -225,18 +232,18 @@
BooleanPropType prop;
prop.FromJson(CreateDictionaryValue("{'enum':[true]}").get(), &prop, nullptr);
chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("false").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("false"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("true").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("true"), &error));
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("1"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("3.0").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("3.0"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'3'").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'3'"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
}
@@ -335,25 +342,25 @@
DoublePropType prop;
prop.AddMinMaxConstraint(-1.2, 1.3);
chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-2").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("-2"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("-1.3").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("-1.3"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("-1.2").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("-1.2"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("0.0").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("0.0"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("1.3").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("1.3"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("1.31").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("1.31"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("true").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("true"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'0.0'").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'0.0'"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
}
@@ -454,30 +461,30 @@
StringPropType prop;
prop.AddLengthConstraint(1, 3);
chromeos::ErrorPtr error;
- EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
prop.AddLengthConstraint(2, 3);
- EXPECT_FALSE(prop.ValidateValue(CreateValue("''").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("''"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'a'").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'a'"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'ab'").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("'ab'"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
EXPECT_EQ(nullptr, error.get());
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'abcd'").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'abcd'"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
prop.FromJson(CreateDictionaryValue("{'enum':['abc','def','xyz!!']}").get(),
nullptr, &error);
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'abc'").get(), &error));
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'def'").get(), &error));
- EXPECT_TRUE(prop.ValidateValue(CreateValue("'xyz!!'").get(), &error));
- EXPECT_FALSE(prop.ValidateValue(CreateValue("'xyz'").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("'abc'"), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("'def'"), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("'xyz!!'"), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("'xyz'"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
}
@@ -676,30 +683,30 @@
"'required':['expires','password']}").get(),
nullptr, nullptr);
chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(
- CreateValue("{'expires':10,'password':'abcdef'}").get(), &error));
+ EXPECT_TRUE(ValidateValue(
+ prop, *CreateValue("{'expires':10,'password':'abcdef'}"), &error));
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("{'expires':10}").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("{'expires':10}"), &error));
EXPECT_EQ("parameter_missing", error->GetCode());
error.reset();
EXPECT_FALSE(
- prop.ValidateValue(CreateValue("{'password':'abcdef'}").get(), &error));
+ ValidateValue(prop, *CreateValue("{'password':'abcdef'}"), &error));
EXPECT_EQ("parameter_missing", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(
- CreateValue("{'expires':10,'password':'abcde'}").get(), &error));
+ EXPECT_FALSE(ValidateValue(
+ prop, *CreateValue("{'expires':10,'password':'abcde'}"), &error));
EXPECT_EQ("out_of_range", error->GetFirstError()->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("2").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("2"), &error));
EXPECT_EQ("type_mismatch", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(
- CreateValue("{'expires':10,'password':'abcdef','retry':true}").get(),
+ EXPECT_FALSE(ValidateValue(
+ prop, *CreateValue("{'expires':10,'password':'abcdef','retry':true}"),
&error));
EXPECT_EQ("unexpected_parameter", error->GetCode());
error.reset();
@@ -714,16 +721,16 @@
.get(),
nullptr, nullptr));
chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue("{'height':20,'width':10}").get(),
- &error));
+ EXPECT_TRUE(
+ ValidateValue(prop, *CreateValue("{'height':20,'width':10}"), &error));
error.reset();
- EXPECT_TRUE(prop.ValidateValue(
- CreateValue("{'height':200,'width':100}").get(), &error));
+ EXPECT_TRUE(
+ ValidateValue(prop, *CreateValue("{'height':200,'width':100}"), &error));
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("{'height':12,'width':10}").get(),
- &error));
+ EXPECT_FALSE(
+ ValidateValue(prop, *CreateValue("{'height':12,'width':10}"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
}
@@ -825,14 +832,14 @@
nullptr, nullptr);
chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue("[3,4,10.5]").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("[3,4,10.5]"), &error));
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2]").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[4, 5, 20]").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("[4, 5, 20]"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
}
@@ -845,14 +852,14 @@
nullptr, nullptr);
chromeos::ErrorPtr error;
- EXPECT_TRUE(prop.ValidateValue(CreateValue("[2,3]").get(), &error));
+ EXPECT_TRUE(ValidateValue(prop, *CreateValue("[2,3]"), &error));
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2]").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2]"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
- EXPECT_FALSE(prop.ValidateValue(CreateValue("[2,3,4]").get(), &error));
+ EXPECT_FALSE(ValidateValue(prop, *CreateValue("[2,3,4]"), &error));
EXPECT_EQ("out_of_range", error->GetCode());
error.reset();
}
@@ -1267,8 +1274,9 @@
prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr, nullptr));
// Omit all.
- auto value = prop.CreateValue();
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue("{}").get(), nullptr));
+ auto value =
+ prop.CreatePropValue(*CreateDictionaryValue("{}").get(), nullptr);
+ ASSERT_NE(nullptr, value);
ValueMap obj = value->GetObject()->GetValue();
EXPECT_TRUE(obj["param1"]->GetBoolean()->GetValue());
EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
@@ -1281,14 +1289,14 @@
EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
// Specify some.
- value = prop.CreateValue();
const char* val_json =
"{"
"'param1':false,"
"'param3':33.3,"
"'param5':{'x':-5,'y':-6}"
"}";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
+ value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
+ ASSERT_NE(nullptr, value);
obj = value->GetObject()->GetValue();
EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
EXPECT_EQ(2, obj["param2"]->GetInt()->GetValue());
@@ -1301,7 +1309,6 @@
EXPECT_EQ((std::vector<int>{1, 2, 3}), GetArrayValues<int>(param6));
// Specify all.
- value = prop.CreateValue();
val_json =
"{"
"'param1':false,"
@@ -1311,7 +1318,8 @@
"'param5':{'x':-55,'y':66},"
"'param6':[-1, 0]"
"}";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
+ value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
+ ASSERT_NE(nullptr, value);
obj = value->GetObject()->GetValue();
EXPECT_FALSE(obj["param1"]->GetBoolean()->GetValue());
EXPECT_EQ(22, obj["param2"]->GetInt()->GetValue());
@@ -1638,23 +1646,24 @@
ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
nullptr));
- auto value = prop.CreateValue();
auto val_json = R"({
'param1':10,
'param2':20,
'param3':30,
'param4':40
})";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
+ auto value =
+ prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
+ ASSERT_NE(nullptr, value);
ValueMap obj = value->GetObject()->GetValue();
EXPECT_EQ(10, obj["param1"]->GetInt()->GetValue());
EXPECT_EQ(20, obj["param2"]->GetInt()->GetValue());
EXPECT_EQ(30, obj["param3"]->GetInt()->GetValue());
EXPECT_EQ(40, obj["param4"]->GetInt()->GetValue());
- value = prop.CreateValue();
val_json = "{'param1':100}";
- ASSERT_TRUE(value->FromJson(CreateDictionaryValue(val_json).get(), nullptr));
+ value = prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), nullptr);
+ ASSERT_NE(nullptr, value);
obj = value->GetObject()->GetValue();
EXPECT_EQ(3, obj.size());
@@ -1678,10 +1687,11 @@
ASSERT_TRUE(prop.FromJson(CreateDictionaryValue(schema_str).get(), nullptr,
nullptr));
- auto value = prop.CreateValue();
auto val_json = "{'param2':20}";
chromeos::ErrorPtr error;
- ASSERT_FALSE(value->FromJson(CreateDictionaryValue(val_json).get(), &error));
+ auto value =
+ prop.CreatePropValue(*CreateDictionaryValue(val_json).get(), &error);
+ ASSERT_EQ(nullptr, value);
EXPECT_EQ(errors::commands::kPropertyMissing, error->GetCode());
}
diff --git a/libweave/src/commands/prop_types.cc b/libweave/src/commands/prop_types.cc
index 4ddfc00..6daabc0 100644
--- a/libweave/src/commands/prop_types.cc
+++ b/libweave/src/commands/prop_types.cc
@@ -185,8 +185,8 @@
// so we can parse and validate the value of the default.
const base::Value* defval = nullptr; // Owned by value
if (value->GetWithoutPathExpansion(commands::attributes::kDefault, &defval)) {
- std::unique_ptr<PropValue> prop_value = CreateValue();
- if (!prop_value->FromJson(defval, error)) {
+ std::unique_ptr<PropValue> prop_value = CreatePropValue(*defval, error);
+ if (!prop_value) {
chromeos::Error::AddToPrintf(error, FROM_HERE, errors::commands::kDomain,
errors::commands::kInvalidPropValue,
"Invalid value for property '%s'",
@@ -231,13 +231,6 @@
return p != constraints_.end() ? p->second.get() : nullptr;
}
-bool PropType::ValidateValue(const base::Value* value,
- chromeos::ErrorPtr* error) const {
- std::unique_ptr<PropValue> val = CreateValue();
- CHECK(val) << "Failed to create value object";
- return val->FromJson(value, error);
-}
-
bool PropType::ValidateConstraints(const PropValue& value,
chromeos::ErrorPtr* error) const {
for (const auto& pair : constraints_) {
diff --git a/libweave/src/commands/prop_types.h b/libweave/src/commands/prop_types.h
index 71de94d..c8b1338 100644
--- a/libweave/src/commands/prop_types.h
+++ b/libweave/src/commands/prop_types.h
@@ -85,9 +85,10 @@
// Makes a full copy of this type definition.
virtual std::unique_ptr<PropType> Clone() const;
- // Creates an instance of associated value object, using the parameter
- // type as a factory class.
- virtual std::unique_ptr<PropValue> CreateValue() const = 0;
+ // Creates an instance of associated value object.
+ virtual std::unique_ptr<PropValue> CreatePropValue(
+ const base::Value& value,
+ chromeos::ErrorPtr* error) const = 0;
// Saves the parameter type definition as a JSON object.
// If |full_schema| is set to true, the full type definition is saved,
@@ -125,13 +126,6 @@
return true;
}
- // Validates a JSON value for the parameter type to make sure it satisfies
- // the parameter type definition including any specified constraints.
- // Returns false if the |value| does not meet the requirements of the type
- // definition and returns additional information about the failure via
- // the |error| parameter.
- bool ValidateValue(const base::Value* value, chromeos::ErrorPtr* error) const;
-
// Additional helper static methods to help with converting a type enum
// value into a string and back.
using TypeMap = std::vector<std::pair<ValueType, std::string>>;
@@ -162,6 +156,9 @@
chromeos::ErrorPtr* error) const;
protected:
+ friend class StatePackage;
+ virtual std::unique_ptr<PropValue> CreateDefaultValue() const = 0;
+
// Specifies if this parameter definition is derived from a base
// object schema.
bool based_on_schema_ = false;
@@ -188,23 +185,27 @@
// Overrides from PropType.
ValueType GetType() const override { return GetValueType<T>(); }
- std::unique_ptr<PropValue> CreateValue() const override {
- if (GetDefaultValue())
- return GetDefaultValue()->Clone();
- return std::unique_ptr<PropValue>{new Value{Clone()}};
+ std::unique_ptr<PropValue> CreatePropValue(
+ const base::Value& value,
+ chromeos::ErrorPtr* error) const override {
+ return CreateValue(value, error);
}
std::unique_ptr<Value> CreateValue(const base::Value& value,
chromeos::ErrorPtr* error) const {
- std::unique_ptr<Value> prop_value{new Value{Clone()}};
- if (!prop_value->FromJson(&value, error))
- return nullptr;
- return prop_value;
+ return Value::CreateFromJson(value, *this, error);
}
bool ConstraintsFromJson(const base::DictionaryValue* value,
std::set<std::string>* processed_keys,
chromeos::ErrorPtr* error) override;
+
+ protected:
+ std::unique_ptr<PropValue> CreateDefaultValue() const override {
+ if (GetDefaultValue())
+ return GetDefaultValue()->Clone();
+ return std::unique_ptr<PropValue>{new Value{*this}};
+ }
};
// Helper base class for Int and Double parameter types.
diff --git a/libweave/src/commands/prop_values.cc b/libweave/src/commands/prop_values.cc
index 813f9c6..cc70948 100644
--- a/libweave/src/commands/prop_values.cc
+++ b/libweave/src/commands/prop_values.cc
@@ -8,12 +8,9 @@
namespace weave {
-PropValue::PropValue(std::unique_ptr<const PropType> type)
- : type_{std::move(type)} {
-}
+PropValue::PropValue(const PropType& type) : type_{type.Clone()} {}
-PropValue::PropValue(const PropValue& other)
- : PropValue{other.type_->Clone()} {}
+PropValue::PropValue(const PropValue& other) : PropValue{*other.type_} {}
PropValue::~PropValue() {
}
diff --git a/libweave/src/commands/prop_values.h b/libweave/src/commands/prop_values.h
index d50c1a4..939356a 100644
--- a/libweave/src/commands/prop_values.h
+++ b/libweave/src/commands/prop_values.h
@@ -83,7 +83,8 @@
// This is used to validate the values against "enum"/"one of" constraints.
class PropValue {
public:
- explicit PropValue(std::unique_ptr<const PropType> type);
+ // Only CreateDefaultValue should use this constructor.
+ explicit PropValue(const PropType& type);
virtual ~PropValue();
// Gets the type of the value.
@@ -108,11 +109,6 @@
// Saves the value as a JSON object. Never fails.
virtual std::unique_ptr<base::Value> ToJson() const = 0;
- // Parses a value from JSON.
- // If it fails, it returns false and provides additional information
- // via the |error| parameter.
- virtual bool FromJson(const base::Value* value,
- chromeos::ErrorPtr* error) = 0;
// Return the type definition of this value.
const PropType* GetPropType() const { return type_.get(); }
@@ -134,9 +130,6 @@
template <typename T>
class TypedValueBase : public PropValue {
public:
- // To help refer to this base class from derived classes, define Base to
- // be this class.
- using Base = TypedValueBase<T>;
using PropValue::PropValue;
// Overrides from PropValue base class.
@@ -146,34 +139,23 @@
return TypedValueToJson(value_);
}
- bool FromJson(const base::Value* value, chromeos::ErrorPtr* error) override {
- T tmp_value;
- if (!TypedValueFromJson(value, GetPropType(), &tmp_value, error))
- return false;
- return SetValue(tmp_value, error);
- }
-
bool IsEqual(const PropValue* value) const override {
if (GetType() != value->GetType())
return false;
- const Base* value_base = static_cast<const Base*>(value);
- return CompareValue(GetValue(), value_base->GetValue());
+ return CompareValue(GetValue(),
+ static_cast<const TypedValueBase*>(value)->GetValue());
}
// Helper methods to get and set the C++ representation of the value.
const T& GetValue() const { return value_; }
- bool SetValue(T value, chromeos::ErrorPtr* error) {
- std::swap(value_, value); // Backup.
- if (GetPropType()->ValidateConstraints(*this, error))
- return true;
- std::swap(value_, value); // Restore.
- return false;
- }
protected:
explicit TypedValueBase(const TypedValueBase& other)
: PropValue(other), value_(other.value_) {}
+ TypedValueBase(const PropType& type, T value)
+ : PropValue(type), value_(value) {}
+
private:
T value_{}; // The value of the parameter in C++ data representation.
};
@@ -192,12 +174,28 @@
return std::unique_ptr<PropValue>{
new Derived{*static_cast<const Derived*>(this)}};
}
+
+ static std::unique_ptr<Derived> CreateFromJson(const base::Value& value,
+ const PropType& type,
+ chromeos::ErrorPtr* error) {
+ T tmp_value;
+ if (!TypedValueFromJson(&value, &type, &tmp_value, error))
+ return nullptr;
+
+ // Only place where invalid value can exist.
+ std::unique_ptr<Derived> result{new Derived{type, tmp_value}};
+ if (!result->GetPropType()->ValidateConstraints(*result, error))
+ return nullptr;
+
+ return result;
+ }
};
// Value of type Integer.
class IntValue final : public TypedValueWithClone<IntValue, int> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<IntValue, int>;
IntValue* GetInt() override { return this; }
IntValue const* GetInt() const override { return this; }
};
@@ -205,7 +203,8 @@
// Value of type Number.
class DoubleValue final : public TypedValueWithClone<DoubleValue, double> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<DoubleValue, double>;
DoubleValue* GetDouble() override { return this; }
DoubleValue const* GetDouble() const override { return this; }
};
@@ -213,7 +212,8 @@
// Value of type String.
class StringValue final : public TypedValueWithClone<StringValue, std::string> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<StringValue, std::string>;
StringValue* GetString() override { return this; }
StringValue const* GetString() const override { return this; }
};
@@ -221,7 +221,8 @@
// Value of type Boolean.
class BooleanValue final : public TypedValueWithClone<BooleanValue, bool> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<BooleanValue, bool>;
BooleanValue* GetBoolean() override { return this; }
BooleanValue const* GetBoolean() const override { return this; }
};
@@ -229,7 +230,8 @@
// Value of type Object.
class ObjectValue final : public TypedValueWithClone<ObjectValue, ValueMap> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<ObjectValue, ValueMap>;
ObjectValue* GetObject() override { return this; }
ObjectValue const* GetObject() const override { return this; }
};
@@ -237,7 +239,8 @@
// Value of type Array.
class ArrayValue final : public TypedValueWithClone<ArrayValue, ValueVector> {
public:
- using Base::Base; // Expose the custom constructor of the base class.
+ using Base::Base;
+ friend class TypedValueWithClone<ArrayValue, ValueVector>;
ArrayValue* GetArray() override { return this; }
ArrayValue const* GetArray() const override { return this; }
};
diff --git a/libweave/src/commands/schema_utils.cc b/libweave/src/commands/schema_utils.cc
index 034eca9..e2c8293 100644
--- a/libweave/src/commands/schema_utils.cc
+++ b/libweave/src/commands/schema_utils.cc
@@ -143,11 +143,11 @@
for (const auto& pair : object_schema->GetProps()) {
const PropValue* def_value = pair.second->GetDefaultValue();
if (dict->HasKey(pair.first)) {
- auto value = pair.second->CreateValue();
const base::Value* param_value = nullptr;
CHECK(dict->GetWithoutPathExpansion(pair.first, ¶m_value))
<< "Unable to get parameter";
- if (!value->FromJson(param_value, error)) {
+ auto value = pair.second->CreatePropValue(*param_value, error);
+ if (!value) {
chromeos::Error::AddToPrintf(
error, FROM_HERE, errors::commands::kDomain,
errors::commands::kInvalidPropValue,
@@ -213,10 +213,10 @@
value_out->clear();
value_out->reserve(list->GetSize());
for (const base::Value* item : *list) {
- std::unique_ptr<PropValue> prop_value = item_type->CreateValue();
- if (!prop_value->FromJson(item, error)) {
+ std::unique_ptr<PropValue> prop_value =
+ item_type->CreatePropValue(*item, error);
+ if (!prop_value)
return false;
- }
value_out->push_back(std::move(prop_value));
}
return true;
diff --git a/libweave/src/commands/unittest_utils.h b/libweave/src/commands/unittest_utils.h
index d0d39ee..043bace 100644
--- a/libweave/src/commands/unittest_utils.h
+++ b/libweave/src/commands/unittest_utils.h
@@ -30,30 +30,27 @@
return val1.Equals(&val2);
}
-template <typename PropVal, typename T>
-std::unique_ptr<const PropVal> make_prop_value(const T& value) {
- std::unique_ptr<PropVal> result{
- new PropVal{PropType::Create(GetValueType<T>())}};
- if (!result->SetValue(value, nullptr))
- return nullptr;
- return std::move(result);
+template <typename T>
+std::unique_ptr<const PropValue> make_prop_value(const base::Value& value) {
+ auto prop_type = PropType::Create(GetValueType<T>());
+ return prop_type->CreatePropValue(value, nullptr);
}
-inline std::unique_ptr<const IntValue> make_int_prop_value(int value) {
- return make_prop_value<IntValue, int>(value);
+inline std::unique_ptr<const PropValue> make_int_prop_value(int value) {
+ return make_prop_value<int>(base::FundamentalValue{value});
}
-inline std::unique_ptr<const DoubleValue> make_double_prop_value(double value) {
- return make_prop_value<DoubleValue, double>(value);
+inline std::unique_ptr<const PropValue> make_double_prop_value(double value) {
+ return make_prop_value<double>(base::FundamentalValue{value});
}
-inline std::unique_ptr<const BooleanValue> make_bool_prop_value(bool value) {
- return make_prop_value<BooleanValue, bool>(value);
+inline std::unique_ptr<const PropValue> make_bool_prop_value(bool value) {
+ return make_prop_value<bool>(base::FundamentalValue{value});
}
-inline std::unique_ptr<const StringValue> make_string_prop_value(
+inline std::unique_ptr<const PropValue> make_string_prop_value(
const std::string& value) {
- return make_prop_value<StringValue, std::string>(value);
+ return make_prop_value<std::string>(base::StringValue{value});
}
} // namespace unittests
diff --git a/libweave/src/states/state_package.cc b/libweave/src/states/state_package.cc
index 170b03c..e20d267 100644
--- a/libweave/src/states/state_package.cc
+++ b/libweave/src/states/state_package.cc
@@ -38,7 +38,7 @@
for (const auto& pair : schema.GetProps()) {
types_.AddProp(pair.first, pair.second->Clone());
// Create default value for this state property.
- values_.emplace(pair.first, pair.second->CreateValue());
+ values_.emplace(pair.first, pair.second->CreateDefaultValue());
}
return true;
@@ -89,8 +89,8 @@
name_.c_str(), property_name.c_str());
return false;
}
- auto new_value = it->second->GetPropType()->CreateValue();
- if (!new_value->FromJson(&value, error))
+ auto new_value = it->second->GetPropType()->CreatePropValue(value, error);
+ if (!new_value)
return false;
it->second = std::move(new_value);
return true;
diff --git a/libweave/src/states/state_package_unittest.cc b/libweave/src/states/state_package_unittest.cc
index 0bd4be8..d6978c0 100644
--- a/libweave/src/states/state_package_unittest.cc
+++ b/libweave/src/states/state_package_unittest.cc
@@ -330,10 +330,17 @@
EXPECT_EQ(errors::commands::kUnknownProperty, error->GetCode());
}
+TEST_F(StatePackageTest, SetPropertyValue_Object_OptionalProperty) {
+ EXPECT_JSON_EQ("{'altitude': 89.9, 'azimuth': 57.2957795}",
+ *package_->GetProperty("direction")->ToJson());
+ ASSERT_TRUE(package_->SetPropertyValue(
+ "direction", *CreateDictionaryValue("{'azimuth': 10.0}"), nullptr));
+ EXPECT_JSON_EQ("{'azimuth': 10.0}",
+ *package_->GetProperty("direction")->ToJson());
+}
+
TEST_F(StatePackageTest, SetPropertyValue_Error_Object_MissingProperty) {
chromeos::ErrorPtr error;
- ASSERT_TRUE(package_->SetPropertyValue(
- "direction", *CreateDictionaryValue("{'azimuth': 10.0}"), &error));
ASSERT_FALSE(package_->SetPropertyValue(
"direction", *CreateDictionaryValue("{'altitude': 10.0}"), &error));
EXPECT_EQ(errors::commands::kDomain, error->GetDomain());