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