blob: c25245e361c838c9d5e51f1ef8f62d3d19a8bd13 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libweave/src/commands/dbus_conversion.h"
#include <memory>
#include <string>
#include <vector>
#include <base/values.h>
#include <chromeos/variant_dictionary.h>
#include <gtest/gtest.h>
#include "libweave/src/commands/object_schema.h"
#include "libweave/src/commands/unittest_utils.h"
namespace weave {
using chromeos::Any;
using chromeos::VariantDictionary;
using unittests::CreateDictionaryValue;
chromeos::VariantDictionary ToDBus(const base::DictionaryValue& object) {
return DictionaryToDBusVariantDictionary(object);
}
TEST(DBusConversionTest, PropValueToDBusVariant) {
IntPropType int_type;
auto prop_value = int_type.CreateValue(5, nullptr);
EXPECT_EQ(5, PropValueToDBusVariant(prop_value.get()).Get<int>());
BooleanPropType bool_type;
prop_value = bool_type.CreateValue(true, nullptr);
EXPECT_TRUE(PropValueToDBusVariant(prop_value.get()).Get<bool>());
DoublePropType dbl_type;
prop_value = dbl_type.CreateValue(5.5, nullptr);
EXPECT_DOUBLE_EQ(5.5, PropValueToDBusVariant(prop_value.get()).Get<double>());
StringPropType str_type;
prop_value = str_type.CreateValue(std::string{"foo"}, nullptr);
EXPECT_EQ("foo", PropValueToDBusVariant(prop_value.get()).Get<std::string>());
ObjectPropType obj_type;
ASSERT_TRUE(obj_type.FromJson(
CreateDictionaryValue(
"{'properties':{'width':'integer','height':'integer'},"
"'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
.get(),
nullptr, nullptr));
ValueMap obj{
{"width", int_type.CreateValue(10, nullptr)},
{"height", int_type.CreateValue(20, nullptr)},
};
prop_value = obj_type.CreateValue(obj, nullptr);
VariantDictionary dict =
PropValueToDBusVariant(prop_value.get()).Get<VariantDictionary>();
EXPECT_EQ(20, dict["height"].Get<int>());
EXPECT_EQ(10, dict["width"].Get<int>());
ArrayPropType arr_type;
arr_type.SetItemType(str_type.Clone());
ValueVector arr;
arr.push_back(str_type.CreateValue(std::string{"foo"}, nullptr));
arr.push_back(str_type.CreateValue(std::string{"bar"}, nullptr));
arr.push_back(str_type.CreateValue(std::string{"baz"}, nullptr));
prop_value = arr_type.CreateValue(arr, nullptr);
chromeos::Any any = PropValueToDBusVariant(prop_value.get());
ASSERT_TRUE(any.IsTypeCompatible<std::vector<std::string>>());
EXPECT_EQ((std::vector<std::string>{"foo", "bar", "baz"}),
any.Get<std::vector<std::string>>());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_Int) {
IntPropType int_type;
ASSERT_TRUE(int_type.FromJson(CreateDictionaryValue("{'enum':[1,2]}").get(),
nullptr, nullptr));
auto prop_value = PropValueFromDBusVariant(&int_type, 1, nullptr);
ASSERT_NE(nullptr, prop_value.get());
EXPECT_EQ(1, prop_value->GetValueAsAny().Get<int>());
chromeos::ErrorPtr error;
prop_value = PropValueFromDBusVariant(&int_type, 5, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_Bool) {
BooleanPropType bool_type;
ASSERT_TRUE(bool_type.FromJson(CreateDictionaryValue("{'enum':[true]}").get(),
nullptr, nullptr));
auto prop_value = PropValueFromDBusVariant(&bool_type, true, nullptr);
ASSERT_NE(nullptr, prop_value.get());
EXPECT_TRUE(prop_value->GetValueAsAny().Get<bool>());
chromeos::ErrorPtr error;
prop_value = PropValueFromDBusVariant(&bool_type, false, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_Double) {
DoublePropType dbl_type;
ASSERT_TRUE(dbl_type.FromJson(CreateDictionaryValue("{'maximum':2.0}").get(),
nullptr, nullptr));
auto prop_value = PropValueFromDBusVariant(&dbl_type, 1.0, nullptr);
ASSERT_NE(nullptr, prop_value.get());
EXPECT_DOUBLE_EQ(1.0, prop_value->GetValueAsAny().Get<double>());
chromeos::ErrorPtr error;
prop_value = PropValueFromDBusVariant(&dbl_type, 10.0, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_String) {
StringPropType str_type;
ASSERT_TRUE(str_type.FromJson(CreateDictionaryValue("{'minLength': 4}").get(),
nullptr, nullptr));
auto prop_value =
PropValueFromDBusVariant(&str_type, std::string{"blah"}, nullptr);
ASSERT_NE(nullptr, prop_value.get());
EXPECT_EQ("blah", prop_value->GetValueAsAny().Get<std::string>());
chromeos::ErrorPtr error;
prop_value = PropValueFromDBusVariant(&str_type, std::string{"foo"}, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_Object) {
ObjectPropType obj_type;
ASSERT_TRUE(obj_type.FromJson(
CreateDictionaryValue(
"{'properties':{'width':'integer','height':'integer'},"
"'enum':[{'width':10,'height':20},{'width':100,'height':200}]}")
.get(),
nullptr, nullptr));
VariantDictionary obj{
{"width", 100}, {"height", 200},
};
auto prop_value = PropValueFromDBusVariant(&obj_type, obj, nullptr);
ASSERT_NE(nullptr, prop_value.get());
auto value = prop_value->GetValueAsAny().Get<ValueMap>();
EXPECT_EQ(100, value["width"].get()->GetValueAsAny().Get<int>());
EXPECT_EQ(200, value["height"].get()->GetValueAsAny().Get<int>());
chromeos::ErrorPtr error;
obj["height"] = 20;
prop_value = PropValueFromDBusVariant(&obj_type, obj, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, PropValueFromDBusVariant_Array) {
ArrayPropType arr_type;
IntPropType int_type;
int_type.AddMinMaxConstraint(0, 100);
arr_type.SetItemType(int_type.Clone());
std::vector<int> data{0, 1, 1, 100};
auto prop_value = PropValueFromDBusVariant(&arr_type, data, nullptr);
ASSERT_NE(nullptr, prop_value.get());
auto arr = prop_value->GetValueAsAny().Get<ValueVector>();
ASSERT_EQ(4u, arr.size());
EXPECT_EQ(0, arr[0]->GetInt()->GetValue());
EXPECT_EQ(1, arr[1]->GetInt()->GetValue());
EXPECT_EQ(1, arr[2]->GetInt()->GetValue());
EXPECT_EQ(100, arr[3]->GetInt()->GetValue());
chromeos::ErrorPtr error;
data.push_back(-1); // This value is out of bounds for |int_type|.
prop_value = PropValueFromDBusVariant(&arr_type, data, &error);
EXPECT_EQ(nullptr, prop_value.get());
ASSERT_NE(nullptr, error.get());
EXPECT_EQ(errors::commands::kOutOfRange, error->GetCode());
}
TEST(DBusConversionTest, DictionaryToDBusVariantDictionary) {
EXPECT_EQ((VariantDictionary{{"bool", true}}),
ToDBus(*CreateDictionaryValue("{'bool': true}")));
EXPECT_EQ((VariantDictionary{{"int", 5}}),
ToDBus(*CreateDictionaryValue("{'int': 5}")));
EXPECT_EQ((VariantDictionary{{"double", 6.7}}),
ToDBus(*CreateDictionaryValue("{'double': 6.7}")));
EXPECT_EQ((VariantDictionary{{"string", std::string{"abc"}}}),
ToDBus(*CreateDictionaryValue("{'string': 'abc'}")));
EXPECT_EQ((VariantDictionary{{"object", VariantDictionary{{"bool", true}}}}),
ToDBus(*CreateDictionaryValue("{'object': {'bool': true}}")));
EXPECT_EQ((VariantDictionary{{"emptyList", std::vector<Any>{}}}),
ToDBus(*CreateDictionaryValue("{'emptyList': []}")));
EXPECT_EQ((VariantDictionary{{"intList", std::vector<int>{5}}}),
ToDBus(*CreateDictionaryValue("{'intList': [5]}")));
EXPECT_EQ((VariantDictionary{
{"intListList", std::vector<Any>{std::vector<int>{5},
std::vector<int>{6, 7}}}}),
ToDBus(*CreateDictionaryValue("{'intListList': [[5], [6, 7]]}")));
EXPECT_EQ((VariantDictionary{{"objList",
std::vector<VariantDictionary>{
{{"string", std::string{"abc"}}}}}}),
ToDBus(*CreateDictionaryValue("{'objList': [{'string': 'abc'}]}")));
}
} // namespace weave