180 lines
6.2 KiB
C++
180 lines
6.2 KiB
C++
//
|
|
// Copyright (C) 2013 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#include "shill/result_aggregator.h"
|
|
|
|
#include <base/bind.h>
|
|
#include <base/memory/ref_counted.h>
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "shill/mock_event_dispatcher.h"
|
|
#include "shill/test_event_dispatcher.h"
|
|
#include "shill/testing.h"
|
|
|
|
namespace shill {
|
|
|
|
using testing::StrictMock;
|
|
using testing::_;
|
|
using base::Bind;
|
|
using base::Unretained;
|
|
|
|
namespace {
|
|
|
|
const int kTimeoutMilliseconds = 0;
|
|
|
|
} // namespace
|
|
|
|
class ResultAggregatorTest : public ::testing::Test {
|
|
public:
|
|
ResultAggregatorTest()
|
|
: aggregator_(new ResultAggregator(
|
|
Bind(&ResultAggregatorTest::ReportResult, Unretained(this)))) {}
|
|
virtual ~ResultAggregatorTest() {}
|
|
|
|
virtual void TearDown() {
|
|
aggregator_ = nullptr; // Ensure ReportResult is invoked before our dtor.
|
|
}
|
|
|
|
MOCK_METHOD1(ReportResult, void(const Error&));
|
|
|
|
protected:
|
|
scoped_refptr<ResultAggregator> aggregator_;
|
|
};
|
|
|
|
class ResultAggregatorTestWithDispatcher : public ResultAggregatorTest {
|
|
public:
|
|
ResultAggregatorTestWithDispatcher() : ResultAggregatorTest() {}
|
|
virtual ~ResultAggregatorTestWithDispatcher() {}
|
|
|
|
void InitializeResultAggregatorWithTimeout() {
|
|
aggregator_ = new ResultAggregator(
|
|
Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
|
|
&dispatcher_, kTimeoutMilliseconds);
|
|
}
|
|
|
|
protected:
|
|
EventDispatcherForTest dispatcher_;
|
|
};
|
|
|
|
class ResultAggregatorTestWithMockDispatcher : public ResultAggregatorTest {
|
|
public:
|
|
ResultAggregatorTestWithMockDispatcher() : ResultAggregatorTest() {}
|
|
virtual ~ResultAggregatorTestWithMockDispatcher() {}
|
|
|
|
protected:
|
|
StrictMock<MockEventDispatcher> dispatcher_;
|
|
};
|
|
|
|
class ResultGenerator {
|
|
public:
|
|
explicit ResultGenerator(const scoped_refptr<ResultAggregator>& aggregator)
|
|
: aggregator_(aggregator) {}
|
|
~ResultGenerator() {}
|
|
|
|
void GenerateResult(const Error::Type error_type) {
|
|
aggregator_->ReportResult(Error(error_type));
|
|
}
|
|
|
|
private:
|
|
scoped_refptr<ResultAggregator> aggregator_;
|
|
DISALLOW_COPY_AND_ASSIGN(ResultGenerator);
|
|
};
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher, Unused) {
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess))).Times(0);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher, BothSucceed) {
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kSuccess)));
|
|
ResultGenerator first_generator(aggregator_);
|
|
ResultGenerator second_generator(aggregator_);
|
|
first_generator.GenerateResult(Error::kSuccess);
|
|
second_generator.GenerateResult(Error::kSuccess);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher, FirstFails) {
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
|
|
ResultGenerator first_generator(aggregator_);
|
|
ResultGenerator second_generator(aggregator_);
|
|
first_generator.GenerateResult(Error::kOperationTimeout);
|
|
second_generator.GenerateResult(Error::kSuccess);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher, SecondFails) {
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
|
|
ResultGenerator first_generator(aggregator_);
|
|
ResultGenerator second_generator(aggregator_);
|
|
first_generator.GenerateResult(Error::kSuccess);
|
|
second_generator.GenerateResult(Error::kOperationTimeout);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher, BothFail) {
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
|
|
ResultGenerator first_generator(aggregator_);
|
|
ResultGenerator second_generator(aggregator_);
|
|
first_generator.GenerateResult(Error::kOperationTimeout);
|
|
second_generator.GenerateResult(Error::kPermissionDenied);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithMockDispatcher,
|
|
TimeoutCallbackPostedOnConstruction) {
|
|
EXPECT_CALL(dispatcher_, PostDelayedTask(_, kTimeoutMilliseconds));
|
|
auto result_aggregator = make_scoped_refptr(new ResultAggregator(
|
|
Bind(&ResultAggregatorTest::ReportResult, Unretained(this)), &dispatcher_,
|
|
kTimeoutMilliseconds));
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithDispatcher,
|
|
TimeoutReceivedWithoutAnyResultsReceived) {
|
|
InitializeResultAggregatorWithTimeout();
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
|
|
ResultGenerator generator(aggregator_);
|
|
dispatcher_.DispatchPendingEvents(); // Invoke timeout callback.
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithDispatcher, TimeoutAndOtherResultReceived) {
|
|
// Timeout should override any other error results.
|
|
InitializeResultAggregatorWithTimeout();
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)));
|
|
ResultGenerator first_generator(aggregator_);
|
|
ResultGenerator second_generator(aggregator_);
|
|
first_generator.GenerateResult(Error::kSuccess);
|
|
dispatcher_.DispatchPendingEvents(); // Invoke timeout callback.
|
|
second_generator.GenerateResult(Error::kPermissionDenied);
|
|
}
|
|
|
|
TEST_F(ResultAggregatorTestWithDispatcher,
|
|
TimeoutCallbackNotInvokedIfAllActionsComplete) {
|
|
{
|
|
auto result_aggregator = make_scoped_refptr(new ResultAggregator(
|
|
Bind(&ResultAggregatorTest::ReportResult, Unretained(this)),
|
|
&dispatcher_, kTimeoutMilliseconds));
|
|
// The result aggregator receives the one callback it expects, and goes
|
|
// out of scope. At this point, it should invoke the ReportResult callback
|
|
// with the error type kPermissionDenied that it copied.
|
|
ResultGenerator generator(result_aggregator);
|
|
generator.GenerateResult(Error::kPermissionDenied);
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kPermissionDenied)));
|
|
}
|
|
// The timeout callback should be canceled after the ResultAggregator went
|
|
// out of scope and was destructed.
|
|
EXPECT_CALL(*this, ReportResult(ErrorTypeIs(Error::kOperationTimeout)))
|
|
.Times(0);
|
|
dispatcher_.DispatchPendingEvents();
|
|
}
|
|
|
|
} // namespace shill
|