| // 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, BlockListIsFull) { | 
 |   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); | 
 |           }))); | 
 |   for (size_t i = manager_->GetSize(); i < manager_->GetCapacity(); ++i) { | 
 |     manager_->Block( | 
 |         {{99, static_cast<uint8_t>(i / 256), static_cast<uint8_t>(i % 256)}, | 
 |          {8, 8, 8}, | 
 |          base::Time::FromTimeT(1419970000), | 
 |          base::Time::FromTimeT(1419990000)}, | 
 |         {}); | 
 |     EXPECT_EQ(i + 1, manager_->GetSize()); | 
 |   } | 
 |   manager_->Block({{99}, | 
 |                    {8, 8, 8}, | 
 |                    base::Time::FromTimeT(1419970000), | 
 |                    base::Time::FromTimeT(1419990000)}, | 
 |                   base::Bind([](ErrorPtr error) { | 
 |                     EXPECT_TRUE(error->HasError("blacklist_is_full")); | 
 |                   })); | 
 | } | 
 |  | 
 | 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 |