| // 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_revocation_manager_impl.h" |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| #include <weave/provider/test/mock_config_store.h> |
| #include <weave/test/unittest_utils.h> |
| |
| #include "src/test/mock_clock.h" |
| #include "src/bind_lambda.h" |
| |
| using testing::_; |
| using testing::Return; |
| using testing::StrictMock; |
| |
| namespace weave { |
| |
| class AccessRevocationManagerImplTest : public testing::Test { |
| protected: |
| void SetUp() { |
| std::string to_load = R"([{ |
| "user": "BQID", |
| "app": "BwQF", |
| "expiration": 463315200, |
| "revocation": 463314200 |
| }, { |
| "user": "AQID", |
| "app": "AwQF", |
| "expiration": 473315199, |
| "revocation": 473313199 |
| }])"; |
| |
| EXPECT_CALL(config_store_, LoadSettings("black_list")) |
| .WillOnce(Return(to_load)); |
| |
| EXPECT_CALL(config_store_, SaveSettings("black_list", _, _)) |
| .WillOnce(testing::WithArgs<1, 2>(testing::Invoke( |
| [](const std::string& json, const DoneCallback& callback) { |
| std::string to_save = R"([{ |
| "user": "AQID", |
| "app": "AwQF", |
| "expiration": 473315199, |
| "revocation": 473313199 |
| }])"; |
| EXPECT_JSON_EQ(to_save, *test::CreateValue(json)); |
| if (!callback.is_null()) |
| callback.Run(nullptr); |
| }))); |
| |
| EXPECT_CALL(clock_, Now()) |
| .WillRepeatedly(Return(base::Time::FromTimeT(1412121212))); |
| manager_.reset( |
| new AccessRevocationManagerImpl{&config_store_, 10, &clock_}); |
| } |
| StrictMock<test::MockClock> clock_; |
| StrictMock<provider::test::MockConfigStore> config_store_{false}; |
| std::unique_ptr<AccessRevocationManagerImpl> manager_; |
| }; |
| |
| TEST_F(AccessRevocationManagerImplTest, Init) { |
| EXPECT_EQ(1u, manager_->GetSize()); |
| EXPECT_EQ(10u, manager_->GetCapacity()); |
| EXPECT_EQ((std::vector<AccessRevocationManagerImpl::Entry>{{ |
| {1, 2, 3}, |
| {3, 4, 5}, |
| base::Time::FromTimeT(1419997999), |
| base::Time::FromTimeT(1419999999), |
| }}), |
| manager_->GetEntries()); |
| } |
| |
| TEST_F(AccessRevocationManagerImplTest, Block) { |
| bool callback_called = false; |
| manager_->AddEntryAddedCallback( |
| base::Bind([&callback_called]() { callback_called = true; })); |
| EXPECT_CALL(config_store_, SaveSettings("black_list", _, _)) |
| .WillOnce(testing::WithArgs<1, 2>(testing::Invoke( |
| [](const std::string& json, const DoneCallback& callback) { |
| std::string to_save = R"([{ |
| "user": "AQID", |
| "app": "AwQF", |
| "expiration": 473315199, |
| "revocation": 473313199 |
| }, { |
| "app": "CAgI", |
| "user": "BwcH", |
| "expiration": 473305200, |
| "revocation": 473295200 |
| }])"; |
| EXPECT_JSON_EQ(to_save, *test::CreateValue(json)); |
| if (!callback.is_null()) |
| callback.Run(nullptr); |
| }))); |
| manager_->Block({{7, 7, 7}, |
| {8, 8, 8}, |
| base::Time::FromTimeT(1419980000), |
| base::Time::FromTimeT(1419990000)}, |
| {}); |
| EXPECT_TRUE(callback_called); |
| } |
| |
| TEST_F(AccessRevocationManagerImplTest, BlockExpired) { |
| manager_->Block({{}, |
| {}, |
| base::Time::FromTimeT(1300000000), |
| base::Time::FromTimeT(1400000000)}, |
| base::Bind([](ErrorPtr error) { |
| EXPECT_TRUE(error->HasError("aleady_expired")); |
| })); |
| } |
| |
| TEST_F(AccessRevocationManagerImplTest, BlockListOverflow) { |
| EXPECT_CALL(config_store_, LoadSettings("black_list")).WillOnce(Return("")); |
| manager_.reset(new AccessRevocationManagerImpl{&config_store_, 10, &clock_}); |
| |
| EXPECT_CALL(config_store_, SaveSettings("black_list", _, _)) |
| .WillRepeatedly(testing::WithArgs<1, 2>(testing::Invoke( |
| [](const std::string& json, const DoneCallback& callback) { |
| if (!callback.is_null()) |
| callback.Run(nullptr); |
| }))); |
| |
| EXPECT_EQ(0u, manager_->GetSize()); |
| |
| // Trigger overflow several times. |
| for (size_t i = 0; i < manager_->GetCapacity() + 3; ++i) { |
| bool callback_called = false; |
| manager_->Block({{99, static_cast<uint8_t>(i), static_cast<uint8_t>(i)}, |
| {8, 8, 8}, |
| base::Time::FromTimeT(1419970000 + i), |
| base::Time::FromTimeT(1419990000)}, |
| base::Bind([&callback_called](ErrorPtr error) { |
| callback_called = true; |
| EXPECT_FALSE(error); |
| })); |
| EXPECT_TRUE(callback_called); |
| } |
| EXPECT_EQ(manager_->GetCapacity(), manager_->GetSize()); |
| |
| // We didn't block these ids, so we can use this to check if all_blocking |
| // issue is set for correct revocation time. |
| EXPECT_TRUE(manager_->IsBlocked({1}, {2}, base::Time::FromTimeT(1419970003))); |
| EXPECT_FALSE( |
| manager_->IsBlocked({1}, {2}, base::Time::FromTimeT(1419970004))); |
| |
| // Check if all blocking rules still work. |
| for (size_t i = 0; i < manager_->GetCapacity() + 3; ++i) { |
| EXPECT_TRUE(manager_->IsBlocked( |
| {99, static_cast<uint8_t>(i), static_cast<uint8_t>(i)}, {8, 8, 8}, |
| base::Time::FromTimeT(1419970000 + i))); |
| } |
| } |
| |
| TEST_F(AccessRevocationManagerImplTest, IsBlockedIdsNotMacth) { |
| EXPECT_FALSE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}, {})); |
| } |
| |
| TEST_F(AccessRevocationManagerImplTest, IsBlockedRevocationIsOld) { |
| // Ids match but delegation time is newer than revocation time. |
| EXPECT_FALSE(manager_->IsBlocked({1, 2, 3}, {3, 4, 5}, |
| base::Time::FromTimeT(1429997999))); |
| } |
| |
| class AccessRevocationManagerImplIsBlockedTest |
| : public AccessRevocationManagerImplTest, |
| public testing::WithParamInterface< |
| std::tuple<std::vector<uint8_t>, std::vector<uint8_t>>> { |
| public: |
| void SetUp() override { |
| AccessRevocationManagerImplTest::SetUp(); |
| EXPECT_CALL(config_store_, SaveSettings("black_list", _, _)) |
| .WillOnce(testing::WithArgs<2>( |
| testing::Invoke([](const DoneCallback& callback) { |
| if (!callback.is_null()) |
| callback.Run(nullptr); |
| }))); |
| manager_->Block({std::get<0>(GetParam()), |
| std::get<1>(GetParam()), |
| {}, |
| base::Time::FromTimeT(1419990000)}, |
| {}); |
| } |
| }; |
| |
| TEST_P(AccessRevocationManagerImplIsBlockedTest, IsBlocked) { |
| EXPECT_TRUE(manager_->IsBlocked({7, 7, 7}, {8, 8, 8}, {})); |
| } |
| |
| INSTANTIATE_TEST_CASE_P( |
| Filters, |
| AccessRevocationManagerImplIsBlockedTest, |
| testing::Combine(testing::Values(std::vector<uint8_t>{}, |
| std::vector<uint8_t>{7, 7, 7}), |
| testing::Values(std::vector<uint8_t>{}, |
| std::vector<uint8_t>{8, 8, 8}))); |
| |
| } // namespace weave |