blob: fd9ce40ae104ffe8b341c3df6a471a507dc1271e [file] [log] [blame]
mukesh agrawal46c27cc2013-07-10 16:39:10 -07001// 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
Samuel Tan7c1aacb2014-09-15 17:13:40 -070012#include "shill/mock_event_dispatcher.h"
13
mukesh agrawal46c27cc2013-07-10 16:39:10 -070014namespace shill {
15
Samuel Tan7c1aacb2014-09-15 17:13:40 -070016using testing::StrictMock;
17using testing::_;
mukesh agrawal46c27cc2013-07-10 16:39:10 -070018using base::Bind;
19using base::Unretained;
20
Samuel Tan7c1aacb2014-09-15 17:13:40 -070021namespace {
22
23const int kTimeoutMilliseconds = 0;
24
25} // namespace
26
mukesh agrawal46c27cc2013-07-10 16:39:10 -070027class ResultAggregatorTest : public ::testing::Test {
28 public:
29 ResultAggregatorTest()
30 : aggregator_(new ResultAggregator(
31 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)))) {}
32 virtual ~ResultAggregatorTest() {}
33
34 virtual void TearDown() {
Ben Chancc225ef2014-09-30 13:26:51 -070035 aggregator_ = nullptr; // Ensure ReportResult is invoked before our dtor.
mukesh agrawal46c27cc2013-07-10 16:39:10 -070036 }
37
Paul Stewart3b30ca52015-06-16 13:13:10 -070038 MOCK_METHOD1(ReportResult, void(const Error&));
Samuel Tan7c1aacb2014-09-15 17:13:40 -070039
40 protected:
mukesh agrawal46c27cc2013-07-10 16:39:10 -070041 scoped_refptr<ResultAggregator> aggregator_;
42};
43
Samuel Tan7c1aacb2014-09-15 17:13:40 -070044class ResultAggregatorTestWithDispatcher : public ResultAggregatorTest {
45 public:
46 ResultAggregatorTestWithDispatcher() : ResultAggregatorTest() {}
47 virtual ~ResultAggregatorTestWithDispatcher() {}
48
49 void InitializeResultAggregatorWithTimeout() {
50 aggregator_ = new ResultAggregator(
51 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
52 &dispatcher_, kTimeoutMilliseconds);
53 }
54
55 protected:
56 EventDispatcher dispatcher_;
57};
58
59class ResultAggregatorTestWithMockDispatcher : public ResultAggregatorTest {
60 public:
61 ResultAggregatorTestWithMockDispatcher() : ResultAggregatorTest() {}
62 virtual ~ResultAggregatorTestWithMockDispatcher() {}
63
64 protected:
65 StrictMock<MockEventDispatcher> dispatcher_;
66};
67
mukesh agrawal46c27cc2013-07-10 16:39:10 -070068class ResultGenerator {
69 public:
Paul Stewart3b30ca52015-06-16 13:13:10 -070070 explicit ResultGenerator(const scoped_refptr<ResultAggregator>& aggregator)
mukesh agrawal46c27cc2013-07-10 16:39:10 -070071 : aggregator_(aggregator) {}
72 ~ResultGenerator() {}
73
74 void GenerateResult(const Error::Type error_type) {
75 aggregator_->ReportResult(Error(error_type));
76 }
77
78 private:
79 scoped_refptr<ResultAggregator> aggregator_;
80 DISALLOW_COPY_AND_ASSIGN(ResultGenerator);
81};
82
Samuel Tan7c1aacb2014-09-15 17:13:40 -070083MATCHER_P(ErrorType, type, "") { return arg.type() == type; }
mukesh agrawal46c27cc2013-07-10 16:39:10 -070084
Samuel Tan7c1aacb2014-09-15 17:13:40 -070085TEST_F(ResultAggregatorTestWithMockDispatcher, Unused) {
mukesh agrawal46c27cc2013-07-10 16:39:10 -070086 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kSuccess))).Times(0);
87}
88
Samuel Tan7c1aacb2014-09-15 17:13:40 -070089TEST_F(ResultAggregatorTestWithMockDispatcher, BothSucceed) {
mukesh agrawal46c27cc2013-07-10 16:39:10 -070090 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kSuccess)));
91 ResultGenerator first_generator(aggregator_);
92 ResultGenerator second_generator(aggregator_);
93 first_generator.GenerateResult(Error::kSuccess);
94 second_generator.GenerateResult(Error::kSuccess);
95}
96
Samuel Tan7c1aacb2014-09-15 17:13:40 -070097TEST_F(ResultAggregatorTestWithMockDispatcher, FirstFails) {
mukesh agrawal46c27cc2013-07-10 16:39:10 -070098 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)));
99 ResultGenerator first_generator(aggregator_);
100 ResultGenerator second_generator(aggregator_);
101 first_generator.GenerateResult(Error::kOperationTimeout);
102 second_generator.GenerateResult(Error::kSuccess);
103}
104
Samuel Tan7c1aacb2014-09-15 17:13:40 -0700105TEST_F(ResultAggregatorTestWithMockDispatcher, SecondFails) {
mukesh agrawal46c27cc2013-07-10 16:39:10 -0700106 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)));
107 ResultGenerator first_generator(aggregator_);
108 ResultGenerator second_generator(aggregator_);
109 first_generator.GenerateResult(Error::kSuccess);
110 second_generator.GenerateResult(Error::kOperationTimeout);
111}
112
Samuel Tan7c1aacb2014-09-15 17:13:40 -0700113TEST_F(ResultAggregatorTestWithMockDispatcher, BothFail) {
mukesh agrawal46c27cc2013-07-10 16:39:10 -0700114 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)));
115 ResultGenerator first_generator(aggregator_);
116 ResultGenerator second_generator(aggregator_);
117 first_generator.GenerateResult(Error::kOperationTimeout);
118 second_generator.GenerateResult(Error::kPermissionDenied);
119}
120
Samuel Tan7c1aacb2014-09-15 17:13:40 -0700121TEST_F(ResultAggregatorTestWithMockDispatcher,
122 TimeoutCallbackPostedOnConstruction) {
123 EXPECT_CALL(dispatcher_, PostDelayedTask(_, kTimeoutMilliseconds));
124 auto result_aggregator = make_scoped_refptr(new ResultAggregator(
125 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), &dispatcher_,
126 kTimeoutMilliseconds));
127}
128
129TEST_F(ResultAggregatorTestWithDispatcher,
130 TimeoutReceivedWithoutAnyResultsReceived) {
131 InitializeResultAggregatorWithTimeout();
132 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)));
133 ResultGenerator generator(aggregator_);
134 dispatcher_.DispatchPendingEvents(); // Invoke timeout callback.
135}
136
137TEST_F(ResultAggregatorTestWithDispatcher, TimeoutAndOtherResultReceived) {
138 // Timeout should override any other error results.
139 InitializeResultAggregatorWithTimeout();
140 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)));
141 ResultGenerator first_generator(aggregator_);
142 ResultGenerator second_generator(aggregator_);
143 first_generator.GenerateResult(Error::kSuccess);
144 dispatcher_.DispatchPendingEvents(); // Invoke timeout callback.
145 second_generator.GenerateResult(Error::kPermissionDenied);
146}
147
148TEST_F(ResultAggregatorTestWithDispatcher,
149 TimeoutCallbackNotInvokedIfAllActionsComplete) {
150 {
151 auto result_aggregator = make_scoped_refptr(new ResultAggregator(
152 Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
153 &dispatcher_, kTimeoutMilliseconds));
154 // The result aggregator receives the one callback it expects, and goes
155 // out of scope. At this point, it should invoke the ReportResult callback
156 // with the error type kPermissionDenied that it copied.
157 ResultGenerator generator(result_aggregator);
158 generator.GenerateResult(Error::kPermissionDenied);
159 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kPermissionDenied)));
160 }
161 // The timeout callback should be canceled after the ResultAggregator went
162 // out of scope and was destructed.
163 EXPECT_CALL(*this, ReportResult(ErrorType(Error::kOperationTimeout)))
164 .Times(0);
165 dispatcher_.DispatchPendingEvents();
166}
167
mukesh agrawal46c27cc2013-07-10 16:39:10 -0700168} // namespace shill