普通文本  |  260行  |  7.86 KB

// Copyright 2016 The Weave 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 "src/access_api_handler.h"

#include <gtest/gtest.h>
#include <weave/provider/test/fake_task_runner.h>
#include <weave/test/mock_device.h>
#include <weave/test/unittest_utils.h>

#include "src/component_manager_impl.h"
#include "src/access_black_list_manager.h"
#include "src/data_encoding.h"

using testing::_;
using testing::AnyOf;
using testing::Invoke;
using testing::Return;
using testing::StrictMock;
using testing::WithArgs;

namespace weave {

class MockAccessBlackListManager : public AccessBlackListManager {
 public:
  MOCK_METHOD4(Block,
               void(const std::vector<uint8_t>&,
                    const std::vector<uint8_t>&,
                    const base::Time&,
                    const DoneCallback&));
  MOCK_METHOD3(Unblock,
               void(const std::vector<uint8_t>&,
                    const std::vector<uint8_t>&,
                    const DoneCallback&));
  MOCK_CONST_METHOD2(IsBlocked,
                     bool(const std::vector<uint8_t>&,
                          const std::vector<uint8_t>&));
  MOCK_CONST_METHOD0(GetEntries, std::vector<Entry>());
  MOCK_CONST_METHOD0(GetSize, size_t());
  MOCK_CONST_METHOD0(GetCapacity, size_t());
};

class AccessApiHandlerTest : public ::testing::Test {
 protected:
  void SetUp() override {
    EXPECT_CALL(device_, AddTraitDefinitionsFromJson(_))
        .WillRepeatedly(Invoke([this](const std::string& json) {
          EXPECT_TRUE(component_manager_.LoadTraits(json, nullptr));
        }));
    EXPECT_CALL(device_, SetStateProperties(_, _, _))
        .WillRepeatedly(
            Invoke(&component_manager_, &ComponentManager::SetStateProperties));
    EXPECT_CALL(device_, SetStateProperty(_, _, _, _))
        .WillRepeatedly(
            Invoke(&component_manager_, &ComponentManager::SetStateProperty));
    EXPECT_CALL(device_, AddComponent(_, _, _))
        .WillRepeatedly(Invoke([this](const std::string& name,
                                      const std::vector<std::string>& traits,
                                      ErrorPtr* error) {
          return component_manager_.AddComponent("", name, traits, error);
        }));

    EXPECT_CALL(device_,
                AddCommandHandler(_, AnyOf("_accessControlBlackList.block",
                                           "_accessControlBlackList.unblock",
                                           "_accessControlBlackList.list"),
                                  _))
        .WillRepeatedly(
            Invoke(&component_manager_, &ComponentManager::AddCommandHandler));

    EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(0));

    EXPECT_CALL(access_manager_, GetCapacity()).WillRepeatedly(Return(10));

    handler_.reset(new AccessApiHandler{&device_, &access_manager_});
  }

  const base::DictionaryValue& AddCommand(const std::string& command) {
    std::string id;
    auto command_instance = component_manager_.ParseCommandInstance(
        *test::CreateDictionaryValue(command.c_str()), Command::Origin::kLocal,
        UserRole::kOwner, &id, nullptr);
    EXPECT_NE(nullptr, command_instance.get());
    component_manager_.AddCommand(std::move(command_instance));
    EXPECT_EQ(Command::State::kDone,
              component_manager_.FindCommand(id)->GetState());
    return component_manager_.FindCommand(id)->GetResults();
  }

  std::unique_ptr<base::DictionaryValue> GetState() {
    std::string path =
        component_manager_.FindComponentWithTrait("_accessControlBlackList");
    EXPECT_FALSE(path.empty());
    const auto* component = component_manager_.FindComponent(path, nullptr);
    EXPECT_TRUE(component);
    const base::DictionaryValue* state = nullptr;
    EXPECT_TRUE(
        component->GetDictionary("state._accessControlBlackList", &state));
    return std::unique_ptr<base::DictionaryValue>{state->DeepCopy()};
  }

  StrictMock<provider::test::FakeTaskRunner> task_runner_;
  ComponentManagerImpl component_manager_{&task_runner_};
  StrictMock<test::MockDevice> device_;
  StrictMock<MockAccessBlackListManager> access_manager_;
  std::unique_ptr<AccessApiHandler> handler_;
};

TEST_F(AccessApiHandlerTest, Initialization) {
  const base::DictionaryValue* trait = nullptr;
  ASSERT_TRUE(component_manager_.GetTraits().GetDictionary(
      "_accessControlBlackList", &trait));

  auto expected = R"({
    "commands": {
      "block": {
        "minimalRole": "owner",
        "parameters": {
          "userId": {
            "type": "string"
          },
          "applicationId": {
            "type": "string"
          },
          "expirationTimeoutSec": {
            "type": "integer"
          }
        }
      },
      "unblock": {
        "minimalRole": "owner",
        "parameters": {
          "userId": {
            "type": "string"
          },
          "applicationId": {
            "type": "string"
          }
        }
      },
      "list": {
        "minimalRole": "owner",
        "parameters": {},
        "results": {
          "blackList": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "userId": {
                  "type": "string"
                },
                "applicationId": {
                  "type": "string"
                }
              },
              "additionalProperties": false
            }
          }
        }
      }
    },
    "state": {
      "size": {
        "type": "integer",
        "isRequired": true
      },
      "capacity": {
        "type": "integer",
        "isRequired": true
      }
    }
  })";
  EXPECT_JSON_EQ(expected, *trait);

  expected = R"({
    "capacity": 10,
    "size": 0
  })";
  EXPECT_JSON_EQ(expected, *GetState());
}

TEST_F(AccessApiHandlerTest, Block) {
  EXPECT_CALL(access_manager_, Block(std::vector<uint8_t>{1, 2, 3},
                                     std::vector<uint8_t>{3, 4, 5}, _, _))
      .WillOnce(WithArgs<3>(
          Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
  EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(1));

  AddCommand(R"({
    'name' : '_accessControlBlackList.block',
    'component': 'accessControl',
    'parameters': {
      'userId': 'AQID',
      'applicationId': 'AwQF',
      'expirationTimeoutSec': 1234
    }
  })");

  auto expected = R"({
    "capacity": 10,
    "size": 1
  })";
  EXPECT_JSON_EQ(expected, *GetState());
}

TEST_F(AccessApiHandlerTest, Unblock) {
  EXPECT_CALL(access_manager_, Unblock(std::vector<uint8_t>{1, 2, 3},
                                       std::vector<uint8_t>{3, 4, 5}, _))
      .WillOnce(WithArgs<2>(
          Invoke([](const DoneCallback& callback) { callback.Run(nullptr); })));
  EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));

  AddCommand(R"({
    'name' : '_accessControlBlackList.unblock',
    'component': 'accessControl',
    'parameters': {
      'userId': 'AQID',
      'applicationId': 'AwQF',
      'expirationTimeoutSec': 1234
    }
  })");

  auto expected = R"({
    "capacity": 10,
    "size": 4
  })";
  EXPECT_JSON_EQ(expected, *GetState());
}

TEST_F(AccessApiHandlerTest, List) {
  std::vector<AccessBlackListManager::Entry> entries{
      {{11, 12, 13}, {21, 22, 23}, base::Time::FromTimeT(1410000000)},
      {{31, 32, 33}, {41, 42, 43}, base::Time::FromTimeT(1420000000)},
  };
  EXPECT_CALL(access_manager_, GetEntries()).WillOnce(Return(entries));
  EXPECT_CALL(access_manager_, GetSize()).WillRepeatedly(Return(4));

  auto expected = R"({
    "blackList": [ {
      "applicationId": "FRYX",
      "userId": "CwwN"
    }, {
       "applicationId": "KSor",
       "userId": "HyAh"
    } ]
  })";

  const auto& results = AddCommand(R"({
    'name' : '_accessControlBlackList.list',
    'component': 'accessControl',
    'parameters': {
    }
  })");

  EXPECT_JSON_EQ(expected, results);
}
}  // namespace weave