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