result_aggregator_unittest.cc revision fa3043cd7dfabf084ee2daa177d197cf67fd3cd6
1// Copyright (c) 2013 The Chromium OS 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 "shill/result_aggregator.h" 6 7#include <base/bind.h> 8#include <base/memory/ref_counted.h> 9#include <gmock/gmock.h> 10#include <gtest/gtest.h> 11 12#include "shill/mock_event_dispatcher.h" 13#include "shill/testing.h" 14 15namespace shill { 16 17using testing::StrictMock; 18using testing::_; 19using base::Bind; 20using base::Unretained; 21 22namespace { 23 24const int kTimeoutMilliseconds = 0; 25 26} // namespace 27 28class ResultAggregatorTest : public ::testing::Test { 29 public: 30 ResultAggregatorTest() 31 : aggregator_(new ResultAggregator( 32 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)))) {} 33 virtual ~ResultAggregatorTest() {} 34 35 virtual void TearDown() { 36 aggregator_ = nullptr; // Ensure ReportResult is invoked before our dtor. 37 } 38 39 MOCK_METHOD1(ReportResult, void(const Error&)); 40 41 protected: 42 scoped_refptr<ResultAggregator> aggregator_; 43}; 44 45class ResultAggregatorTestWithDispatcher : public ResultAggregatorTest { 46 public: 47 ResultAggregatorTestWithDispatcher() : ResultAggregatorTest() {} 48 virtual ~ResultAggregatorTestWithDispatcher() {} 49 50 void InitializeResultAggregatorWithTimeout() { 51 aggregator_ = new ResultAggregator( 52 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), 53 &dispatcher_, kTimeoutMilliseconds); 54 } 55 56 protected: 57 EventDispatcher dispatcher_; 58}; 59 60class ResultAggregatorTestWithMockDispatcher : public ResultAggregatorTest { 61 public: 62 ResultAggregatorTestWithMockDispatcher() : ResultAggregatorTest() {} 63 virtual ~ResultAggregatorTestWithMockDispatcher() {} 64 65 protected: 66 StrictMock<MockEventDispatcher> dispatcher_; 67}; 68 69class ResultGenerator { 70 public: 71 explicit ResultGenerator(const scoped_refptr<ResultAggregator>& aggregator) 72 : aggregator_(aggregator) {} 73 ~ResultGenerator() {} 74 75 void GenerateResult(const Error::Type error_type) { 76 aggregator_->ReportResult(Error(error_type)); 77 } 78 79 private: 80 scoped_refptr<ResultAggregator> aggregator_; 81 DISALLOW_COPY_AND_ASSIGN(ResultGenerator); 82}; 83 84TEST_F(ResultAggregatorTestWithMockDispatcher, Unused) { 85 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess))).Times(0); 86} 87 88TEST_F(ResultAggregatorTestWithMockDispatcher, BothSucceed) { 89 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess))); 90 ResultGenerator first_generator(aggregator_); 91 ResultGenerator second_generator(aggregator_); 92 first_generator.GenerateResult(Error::kSuccess); 93 second_generator.GenerateResult(Error::kSuccess); 94} 95 96TEST_F(ResultAggregatorTestWithMockDispatcher, FirstFails) { 97 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))); 98 ResultGenerator first_generator(aggregator_); 99 ResultGenerator second_generator(aggregator_); 100 first_generator.GenerateResult(Error::kOperationTimeout); 101 second_generator.GenerateResult(Error::kSuccess); 102} 103 104TEST_F(ResultAggregatorTestWithMockDispatcher, SecondFails) { 105 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))); 106 ResultGenerator first_generator(aggregator_); 107 ResultGenerator second_generator(aggregator_); 108 first_generator.GenerateResult(Error::kSuccess); 109 second_generator.GenerateResult(Error::kOperationTimeout); 110} 111 112TEST_F(ResultAggregatorTestWithMockDispatcher, BothFail) { 113 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))); 114 ResultGenerator first_generator(aggregator_); 115 ResultGenerator second_generator(aggregator_); 116 first_generator.GenerateResult(Error::kOperationTimeout); 117 second_generator.GenerateResult(Error::kPermissionDenied); 118} 119 120TEST_F(ResultAggregatorTestWithMockDispatcher, 121 TimeoutCallbackPostedOnConstruction) { 122 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kTimeoutMilliseconds)); 123 auto result_aggregator = make_scoped_refptr(new ResultAggregator( 124 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), &dispatcher_, 125 kTimeoutMilliseconds)); 126} 127 128TEST_F(ResultAggregatorTestWithDispatcher, 129 TimeoutReceivedWithoutAnyResultsReceived) { 130 InitializeResultAggregatorWithTimeout(); 131 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))); 132 ResultGenerator generator(aggregator_); 133 dispatcher_.DispatchPendingEvents(); // Invoke timeout callback. 134} 135 136TEST_F(ResultAggregatorTestWithDispatcher, TimeoutAndOtherResultReceived) { 137 // Timeout should override any other error results. 138 InitializeResultAggregatorWithTimeout(); 139 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))); 140 ResultGenerator first_generator(aggregator_); 141 ResultGenerator second_generator(aggregator_); 142 first_generator.GenerateResult(Error::kSuccess); 143 dispatcher_.DispatchPendingEvents(); // Invoke timeout callback. 144 second_generator.GenerateResult(Error::kPermissionDenied); 145} 146 147TEST_F(ResultAggregatorTestWithDispatcher, 148 TimeoutCallbackNotInvokedIfAllActionsComplete) { 149 { 150 auto result_aggregator = make_scoped_refptr(new ResultAggregator( 151 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), 152 &dispatcher_, kTimeoutMilliseconds)); 153 // The result aggregator receives the one callback it expects, and goes 154 // out of scope. At this point, it should invoke the ReportResult callback 155 // with the error type kPermissionDenied that it copied. 156 ResultGenerator generator(result_aggregator); 157 generator.GenerateResult(Error::kPermissionDenied); 158 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kPermissionDenied))); 159 } 160 // The timeout callback should be canceled after the ResultAggregator went 161 // out of scope and was destructed. 162 EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout))) 163 .Times(0); 164 dispatcher_.DispatchPendingEvents(); 165} 166 167} // namespace shill 168