Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2013 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "shill/result_aggregator.h"
     18 
     19 #include <base/bind.h>
     20 #include <base/memory/ref_counted.h>
     21 #include <gmock/gmock.h>
     22 #include <gtest/gtest.h>
     23 
     24 #include "shill/mock_event_dispatcher.h"
     25 #include "shill/test_event_dispatcher.h"
     26 #include "shill/testing.h"
     27 
     28 namespace shill {
     29 
     30 using testing::StrictMock;
     31 using testing::_;
     32 using base::Bind;
     33 using base::Unretained;
     34 
     35 namespace {
     36 
     37 const int kTimeoutMilliseconds = 0;
     38 
     39 }  // namespace
     40 
     41 class ResultAggregatorTest : public ::testing::Test {
     42  public:
     43   ResultAggregatorTest()
     44       : aggregator_(new ResultAggregator(
     45             Bind(&ResultAggregatorTest::ReportResult, Unretained(this)))) {}
     46   virtual ~ResultAggregatorTest() {}
     47 
     48   virtual void TearDown() {
     49     aggregator_ = nullptr;  // Ensure ReportResult is invoked before our dtor.
     50   }
     51 
     52   MOCK_METHOD1(ReportResult, void(const Error&));
     53 
     54  protected:
     55   scoped_refptr<ResultAggregator> aggregator_;
     56 };
     57 
     58 class ResultAggregatorTestWithDispatcher : public ResultAggregatorTest {
     59  public:
     60   ResultAggregatorTestWithDispatcher() : ResultAggregatorTest() {}
     61   virtual ~ResultAggregatorTestWithDispatcher() {}
     62 
     63   void InitializeResultAggregatorWithTimeout() {
     64     aggregator_ = new ResultAggregator(
     65         Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
     66         &dispatcher_, kTimeoutMilliseconds);
     67   }
     68 
     69  protected:
     70   EventDispatcherForTest dispatcher_;
     71 };
     72 
     73 class ResultAggregatorTestWithMockDispatcher : public ResultAggregatorTest {
     74  public:
     75   ResultAggregatorTestWithMockDispatcher() : ResultAggregatorTest() {}
     76   virtual ~ResultAggregatorTestWithMockDispatcher() {}
     77 
     78  protected:
     79   StrictMock<MockEventDispatcher> dispatcher_;
     80 };
     81 
     82 class ResultGenerator {
     83  public:
     84   explicit ResultGenerator(const scoped_refptr<ResultAggregator>& aggregator)
     85       : aggregator_(aggregator) {}
     86   ~ResultGenerator() {}
     87 
     88   void GenerateResult(const Error::Type error_type) {
     89     aggregator_->ReportResult(Error(error_type));
     90   }
     91 
     92  private:
     93   scoped_refptr<ResultAggregator> aggregator_;
     94   DISALLOW_COPY_AND_ASSIGN(ResultGenerator);
     95 };
     96 
     97 TEST_F(ResultAggregatorTestWithMockDispatcher, Unused) {
     98   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess))).Times(0);
     99 }
    100 
    101 TEST_F(ResultAggregatorTestWithMockDispatcher, BothSucceed) {
    102   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess)));
    103   ResultGenerator first_generator(aggregator_);
    104   ResultGenerator second_generator(aggregator_);
    105   first_generator.GenerateResult(Error::kSuccess);
    106   second_generator.GenerateResult(Error::kSuccess);
    107 }
    108 
    109 TEST_F(ResultAggregatorTestWithMockDispatcher, FirstFails) {
    110   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
    111   ResultGenerator first_generator(aggregator_);
    112   ResultGenerator second_generator(aggregator_);
    113   first_generator.GenerateResult(Error::kOperationTimeout);
    114   second_generator.GenerateResult(Error::kSuccess);
    115 }
    116 
    117 TEST_F(ResultAggregatorTestWithMockDispatcher, SecondFails) {
    118   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
    119   ResultGenerator first_generator(aggregator_);
    120   ResultGenerator second_generator(aggregator_);
    121   first_generator.GenerateResult(Error::kSuccess);
    122   second_generator.GenerateResult(Error::kOperationTimeout);
    123 }
    124 
    125 TEST_F(ResultAggregatorTestWithMockDispatcher, BothFail) {
    126   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
    127   ResultGenerator first_generator(aggregator_);
    128   ResultGenerator second_generator(aggregator_);
    129   first_generator.GenerateResult(Error::kOperationTimeout);
    130   second_generator.GenerateResult(Error::kPermissionDenied);
    131 }
    132 
    133 TEST_F(ResultAggregatorTestWithMockDispatcher,
    134        TimeoutCallbackPostedOnConstruction) {
    135   EXPECT_CALL(dispatcher_, PostDelayedTask(_, kTimeoutMilliseconds));
    136   auto result_aggregator = make_scoped_refptr(new ResultAggregator(
    137       Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), &dispatcher_,
    138       kTimeoutMilliseconds));
    139 }
    140 
    141 TEST_F(ResultAggregatorTestWithDispatcher,
    142        TimeoutReceivedWithoutAnyResultsReceived) {
    143   InitializeResultAggregatorWithTimeout();
    144   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
    145   ResultGenerator generator(aggregator_);
    146   dispatcher_.DispatchPendingEvents();  // Invoke timeout callback.
    147 }
    148 
    149 TEST_F(ResultAggregatorTestWithDispatcher, TimeoutAndOtherResultReceived) {
    150   // Timeout should override any other error results.
    151   InitializeResultAggregatorWithTimeout();
    152   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
    153   ResultGenerator first_generator(aggregator_);
    154   ResultGenerator second_generator(aggregator_);
    155   first_generator.GenerateResult(Error::kSuccess);
    156   dispatcher_.DispatchPendingEvents();  // Invoke timeout callback.
    157   second_generator.GenerateResult(Error::kPermissionDenied);
    158 }
    159 
    160 TEST_F(ResultAggregatorTestWithDispatcher,
    161        TimeoutCallbackNotInvokedIfAllActionsComplete) {
    162   {
    163     auto result_aggregator = make_scoped_refptr(new ResultAggregator(
    164         Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
    165         &dispatcher_, kTimeoutMilliseconds));
    166     // The result aggregator receives the one callback it expects, and goes
    167     // out of scope. At this point, it should invoke the ReportResult callback
    168     // with the error type kPermissionDenied that it copied.
    169     ResultGenerator generator(result_aggregator);
    170     generator.GenerateResult(Error::kPermissionDenied);
    171     EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kPermissionDenied)));
    172   }
    173   // The timeout callback should be canceled after the ResultAggregator went
    174   // out of scope and was destructed.
    175   EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)))
    176       .Times(0);
    177   dispatcher_.DispatchPendingEvents();
    178 }
    179 
    180 }  // namespace shill
    181