Home | History | Annotate | Download | only in src
      1 // Copyright 2016 The Weave Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/access_api_handler.h"
      6 
      7 #include <gtest/gtest.h>
      8 #include <weave/provider/test/fake_task_runner.h>
      9 #include <weave/test/mock_device.h>
     10 #include <weave/test/unittest_utils.h>
     11 
     12 #include "src/component_manager_impl.h"
     13 #include "src/access_black_list_manager.h"
     14 #include "src/data_encoding.h"
     15 
     16 using testing::_;
     17 using testing::AnyOf;
     18 using testing::Invoke;
     19 using testing::Return;
     20 using testing::StrictMock;
     21 using testing::WithArgs;
     22 
     23 namespace weave {
     24 
     25 class MockAccessBlackListManager : public AccessBlackListManager {
     26  public:
     27   MOCK_METHOD4(Block,
     28                void(const std::vector<uint8_t>&,
     29                     const std::vector<uint8_t>&,
     30                     const base::Time&,
     31                     const DoneCallback&));
     32   MOCK_METHOD3(Unblock,
     33                void(const std::vector<uint8_t>&,
     34                     const std::vector<uint8_t>&,
     35                     const DoneCallback&));
     36   MOCK_CONST_METHOD2(IsBlocked,
     37                      bool(const std::vector<uint8_t>&,
     38                           const std::vector<uint8_t>&));
     39   MOCK_CONST_METHOD0(GetEntries, std::vector<Entry>());
     40   MOCK_CONST_METHOD0(GetSize, size_t());
     41   MOCK_CONST_METHOD0(GetCapacity, size_t());
     42 };
     43 
     44 class AccessApiHandlerTest : public ::testing::Test {
     45  protected:
     46   void SetUp() override {
     47     EXPECT_CALL(device_, AddTraitDefinitionsFromJson(_))
     48         .WillRepeatedly(Invoke([this](const std::string& json) {
     49           EXPECT_TRUE(component_manager_.LoadTraits(json, nullptr));
     50         }));
     51     EXPECT_CALL(device_, SetStateProperties(_, _, _))
     52         .WillRepeatedly(
     53             Invoke(&component_manager_, &ComponentManager::SetStateProperties));
     54     EXPECT_CALL(device_, SetStateProperty(_, _, _, _))
     55         .WillRepeatedly(
     56             Invoke(&component_manager_, &ComponentManager::SetStateProperty));
     57     EXPECT_CALL(device_, AddComponent(_, _, _))
     58         .WillRepeatedly(Invoke([this](const std::string& name,
     59                                       const std::vector<std::string>& traits,
     60                                       ErrorPtr* error) {
     61           return component_manager_.AddComponent("", name, traits, error);
     62         }));
     63 
     64     EXPECT_CALL(device_,
     65                 AddCommandHandler(_, AnyOf("_accessControlBlackList.block",
     66                                            "_accessControlBlackList.unblock",
     67                                            "_accessControlBlackList.list"),
     68                                   _))
     69         .WillRepeatedly(
     70             Invoke(&component_manager_, &ComponentManager::AddCommandHandler));
     71 
     72     EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(0));
     73 
     74     EXPECT_CALL(access_manager_, GetCapacity()).WillRepeatedly(Return(10));
     75 
     76     handler_.reset(new AccessApiHandler{&device_, &access_manager_});
     77   }
     78 
     79   const base::DictionaryValue& AddCommand(const std::string& command) {
     80     std::string id;
     81     auto command_instance = component_manager_.ParseCommandInstance(
     82         *test::CreateDictionaryValue(command.c_str()), Command::Origin::kLocal,
     83         UserRole::kOwner, &id, nullptr);
     84     EXPECT_NE(nullptr, command_instance.get());
     85     component_manager_.AddCommand(std::move(command_instance));
     86     EXPECT_EQ(Command::State::kDone,
     87               component_manager_.FindCommand(id)->GetState());
     88     return component_manager_.FindCommand(id)->GetResults();
     89   }
     90 
     91   std::unique_ptr<base::DictionaryValue> GetState() {
     92     std::string path =
     93         component_manager_.FindComponentWithTrait("_accessControlBlackList");
     94     EXPECT_FALSE(path.empty());
     95     const auto* component = component_manager_.FindComponent(path, nullptr);
     96     EXPECT_TRUE(component);
     97     const base::DictionaryValue* state = nullptr;
     98     EXPECT_TRUE(
     99         component->GetDictionary("state._accessControlBlackList", &state));
    100     return std::unique_ptr<base::DictionaryValue>{state->DeepCopy()};
    101   }
    102 
    103   StrictMock<provider::test::FakeTaskRunner> task_runner_;
    104   ComponentManagerImpl component_manager_{&task_runner_};
    105   StrictMock<test::MockDevice> device_;
    106   StrictMock<MockAccessBlackListManager> access_manager_;
    107   std::unique_ptr<AccessApiHandler> handler_;
    108 };
    109 
    110 TEST_F(AccessApiHandlerTest, Initialization) {
    111   const base::DictionaryValue* trait = nullptr;
    112   ASSERT_TRUE(component_manager_.GetTraits().GetDictionary(
    113       "_accessControlBlackList", &trait));
    114 
    115   auto expected = R"({
    116     "commands": {
    117       "block": {
    118         "minimalRole": "owner",
    119         "parameters": {
    120           "userId": {
    121             "type": "string"
    122           },
    123           "applicationId": {
    124             "type": "string"
    125           },
    126           "expirationTimeoutSec": {
    127             "type": "integer"
    128           }
    129         }
    130       },
    131       "unblock": {
    132         "minimalRole": "owner",
    133         "parameters": {
    134           "userId": {
    135             "type": "string"
    136           },
    137           "applicationId": {
    138             "type": "string"
    139           }
    140         }
    141       },
    142       "list": {
    143         "minimalRole": "owner",
    144         "parameters": {},
    145         "results": {
    146           "blackList": {
    147             "type": "array",
    148             "items": {
    149               "type": "object",
    150               "properties": {
    151                 "userId": {
    152                   "type": "string"
    153                 },
    154                 "applicationId": {
    155                   "type": "string"
    156                 }
    157               },
    158               "additionalProperties": false
    159             }
    160           }
    161         }
    162       }
    163     },
    164     "state": {
    165       "size": {
    166         "type": "integer",
    167         "isRequired": true
    168       },
    169       "capacity": {
    170         "type": "integer",
    171         "isRequired": true
    172       }
    173     }
    174   })";
    175   EXPECT_JSON_EQ(expected, *trait);
    176 
    177   expected = R"({
    178     "capacity": 10,
    179     "size": 0
    180   })";
    181   EXPECT_JSON_EQ(expected, *GetState());
    182 }
    183 
    184 TEST_F(AccessApiHandlerTest, Block) {
    185   EXPECT_CALL(access_manager_, Block(std::vector<uint8_t>{1, 2, 3},
    186                                      std::vector<uint8_t>{3, 4, 5}, _, _))
    187       .WillOnce(WithArgs<3>(
    188           Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
    189   EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(1));
    190 
    191   AddCommand(R"({
    192     'name' : '_accessControlBlackList.block',
    193     'component': 'accessControl',
    194     'parameters': {
    195       'userId': 'AQID',
    196       'applicationId': 'AwQF',
    197       'expirationTimeoutSec': 1234
    198     }
    199   })");
    200 
    201   auto expected = R"({
    202     "capacity": 10,
    203     "size": 1
    204   })";
    205   EXPECT_JSON_EQ(expected, *GetState());
    206 }
    207 
    208 TEST_F(AccessApiHandlerTest, Unblock) {
    209   EXPECT_CALL(access_manager_, Unblock(std::vector<uint8_t>{1, 2, 3},
    210                                        std::vector<uint8_t>{3, 4, 5}, _))
    211       .WillOnce(WithArgs<2>(
    212           Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
    213   EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));
    214 
    215   AddCommand(R"({
    216     'name' : '_accessControlBlackList.unblock',
    217     'component': 'accessControl',
    218     'parameters': {
    219       'userId': 'AQID',
    220       'applicationId': 'AwQF',
    221       'expirationTimeoutSec': 1234
    222     }
    223   })");
    224 
    225   auto expected = R"({
    226     "capacity": 10,
    227     "size": 4
    228   })";
    229   EXPECT_JSON_EQ(expected, *GetState());
    230 }
    231 
    232 TEST_F(AccessApiHandlerTest, List) {
    233   std::vector<AccessBlackListManager::Entry> entries{
    234       {{11, 12, 13}, {21, 22, 23}, base::Time::FromTimeT(1410000000)},
    235       {{31, 32, 33}, {41, 42, 43}, base::Time::FromTimeT(1420000000)},
    236   };
    237   EXPECT_CALL(access_manager_, GetEntries()).WillOnce(Return(entries));
    238   EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));
    239 
    240   auto expected = R"({
    241     "blackList": [ {
    242       "applicationId": "FRYX",
    243       "userId": "CwwN"
    244     }, {
    245        "applicationId": "KSor",
    246        "userId": "HyAh"
    247     } ]
    248   })";
    249 
    250   const auto& results = AddCommand(R"({
    251     'name' : '_accessControlBlackList.list',
    252     'component': 'accessControl',
    253     'parameters': {
    254     }
    255   })");
    256 
    257   EXPECT_JSON_EQ(expected, results);
    258 }
    259 }  // namespace weave
    260