blob: 0718bef4de39a82dbcadebb9967d2ff1cceb1cae [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#ifndef __TESTS_ALLOCATOR_HPP__
#define __TESTS_ALLOCATOR_HPP__
#include <gmock/gmock.h>
#include <mesos/allocator/allocator.hpp>
#include <process/future.hpp>
#include <process/gmock.hpp>
#include <process/owned.hpp>
#include "master/allocator/mesos/hierarchical.hpp"
using ::testing::_;
using ::testing::An;
using ::testing::DoDefault;
using ::testing::Invoke;
using ::testing::Return;
using mesos::allocator::Options;
namespace mesos {
namespace internal {
namespace tests {
// Allocator test helpers.
Quota createQuota(const std::string& role, const std::string& resources);
WeightInfo createWeightInfo(const std::string& role, double weight);
// The following actions make up for the fact that DoDefault
// cannot be used inside a DoAll, for example:
// EXPECT_CALL(allocator, addFramework(_, _, _, _, _))
// .WillOnce(DoAll(InvokeAddFramework(&allocator),
// FutureSatisfy(&addFramework)));
ACTION_P(InvokeInitialize, allocator)
{
allocator->real->initialize(arg0, arg1, arg2);
}
ACTION_P(InvokeRecover, allocator)
{
allocator->real->recover(arg0, arg1);
}
ACTION_P(InvokeAddFramework, allocator)
{
allocator->real->addFramework(arg0, arg1, arg2, arg3, arg4);
}
ACTION_P(InvokeRemoveFramework, allocator)
{
allocator->real->removeFramework(arg0);
}
ACTION_P(InvokeActivateFramework, allocator)
{
allocator->real->activateFramework(arg0);
}
ACTION_P(InvokeDeactivateFramework, allocator)
{
allocator->real->deactivateFramework(arg0);
}
ACTION_P(InvokeUpdateFramework, allocator)
{
allocator->real->updateFramework(arg0, arg1, arg2);
}
ACTION_P(InvokeAddSlave, allocator)
{
allocator->real->addSlave(arg0, arg1, arg2, arg3, arg4, arg5);
}
ACTION_P(InvokeRemoveSlave, allocator)
{
allocator->real->removeSlave(arg0);
}
ACTION_P(InvokeUpdateSlave, allocator)
{
allocator->real->updateSlave(arg0, arg1, arg2, arg3);
}
ACTION_P(InvokeAddResourceProvider, allocator)
{
allocator->real->addResourceProvider(arg0, arg1, arg2);
}
ACTION_P(InvokeActivateSlave, allocator)
{
allocator->real->activateSlave(arg0);
}
ACTION_P(InvokeDeactivateSlave, allocator)
{
allocator->real->deactivateSlave(arg0);
}
ACTION_P(InvokeUpdateWhitelist, allocator)
{
allocator->real->updateWhitelist(arg0);
}
ACTION_P(InvokeRequestResources, allocator)
{
allocator->real->requestResources(arg0, arg1);
}
ACTION_P(InvokeUpdateAllocation, allocator)
{
allocator->real->updateAllocation(arg0, arg1, arg2, arg3);
}
ACTION_P(InvokeUpdateAvailable, allocator)
{
return allocator->real->updateAvailable(arg0, arg1);
}
ACTION_P(InvokeUpdateUnavailability, allocator)
{
return allocator->real->updateUnavailability(arg0, arg1);
}
ACTION_P(InvokeUpdateInverseOffer, allocator)
{
return allocator->real->updateInverseOffer(arg0, arg1, arg2, arg3, arg4);
}
ACTION_P(InvokeGetInverseOfferStatuses, allocator)
{
return allocator->real->getInverseOfferStatuses();
}
ACTION_P(InvokeRecoverResources, allocator)
{
allocator->real->recoverResources(arg0, arg1, arg2, arg3);
}
ACTION_P2(InvokeRecoverResourcesWithFilters, allocator, timeout)
{
Filters filters;
filters.set_refuse_seconds(timeout);
allocator->real->recoverResources(arg0, arg1, arg2, filters);
}
ACTION_P(InvokeSuppressOffers, allocator)
{
allocator->real->suppressOffers(arg0, arg1);
}
ACTION_P(InvokeReviveOffers, allocator)
{
allocator->real->reviveOffers(arg0, arg1);
}
ACTION_P(InvokeSetQuota, allocator)
{
allocator->real->setQuota(arg0, arg1);
}
ACTION_P(InvokeRemoveQuota, allocator)
{
allocator->real->removeQuota(arg0);
}
ACTION_P(InvokeUpdateWeights, allocator)
{
allocator->real->updateWeights(arg0);
}
ACTION_P(InvokePause, allocator)
{
allocator->real->pause();
}
ACTION_P(InvokeResume, allocator)
{
allocator->real->resume();
}
template <typename T = master::allocator::HierarchicalDRFAllocator>
mesos::allocator::Allocator* createAllocator()
{
// T represents the allocator type. It can be a default built-in
// allocator, or one provided by an allocator module.
Try<mesos::allocator::Allocator*> instance = T::create();
CHECK_SOME(instance);
return CHECK_NOTNULL(instance.get());
}
template <typename T = master::allocator::HierarchicalDRFAllocator>
class TestAllocator : public mesos::allocator::Allocator
{
public:
// Actual allocation is done by an instance of real allocator,
// which is specified by the template parameter.
TestAllocator() : real(createAllocator<T>())
{
// We use 'ON_CALL' and 'WillByDefault' here to specify the
// default actions (call in to the real allocator). This allows
// the tests to leverage the 'DoDefault' action.
// However, 'ON_CALL' results in a "Uninteresting mock function
// call" warning unless each test puts expectations in place.
// As a result, we also use 'EXPECT_CALL' and 'WillRepeatedly'
// to get the best of both worlds: the ability to use 'DoDefault'
// and no warnings when expectations are not explicit.
ON_CALL(*this, initialize(_, _, _))
.WillByDefault(InvokeInitialize(this));
EXPECT_CALL(*this, initialize(_, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, recover(_, _))
.WillByDefault(InvokeRecover(this));
EXPECT_CALL(*this, recover(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, addFramework(_, _, _, _, _))
.WillByDefault(InvokeAddFramework(this));
EXPECT_CALL(*this, addFramework(_, _, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, removeFramework(_))
.WillByDefault(InvokeRemoveFramework(this));
EXPECT_CALL(*this, removeFramework(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, activateFramework(_))
.WillByDefault(InvokeActivateFramework(this));
EXPECT_CALL(*this, activateFramework(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, deactivateFramework(_))
.WillByDefault(InvokeDeactivateFramework(this));
EXPECT_CALL(*this, deactivateFramework(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateFramework(_, _, _))
.WillByDefault(InvokeUpdateFramework(this));
EXPECT_CALL(*this, updateFramework(_, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, addSlave(_, _, _, _, _, _))
.WillByDefault(InvokeAddSlave(this));
EXPECT_CALL(*this, addSlave(_, _, _, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, removeSlave(_))
.WillByDefault(InvokeRemoveSlave(this));
EXPECT_CALL(*this, removeSlave(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateSlave(_, _, _, _))
.WillByDefault(InvokeUpdateSlave(this));
EXPECT_CALL(*this, updateSlave(_, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, addResourceProvider(_, _, _))
.WillByDefault(InvokeAddResourceProvider(this));
EXPECT_CALL(*this, addResourceProvider(_, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, activateSlave(_))
.WillByDefault(InvokeActivateSlave(this));
EXPECT_CALL(*this, activateSlave(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, deactivateSlave(_))
.WillByDefault(InvokeDeactivateSlave(this));
EXPECT_CALL(*this, deactivateSlave(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateWhitelist(_))
.WillByDefault(InvokeUpdateWhitelist(this));
EXPECT_CALL(*this, updateWhitelist(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, requestResources(_, _))
.WillByDefault(InvokeRequestResources(this));
EXPECT_CALL(*this, requestResources(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateAllocation(_, _, _, _))
.WillByDefault(InvokeUpdateAllocation(this));
EXPECT_CALL(*this, updateAllocation(_, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateAvailable(_, _))
.WillByDefault(InvokeUpdateAvailable(this));
EXPECT_CALL(*this, updateAvailable(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateUnavailability(_, _))
.WillByDefault(InvokeUpdateUnavailability(this));
EXPECT_CALL(*this, updateUnavailability(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateInverseOffer(_, _, _, _, _))
.WillByDefault(InvokeUpdateInverseOffer(this));
EXPECT_CALL(*this, updateInverseOffer(_, _, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, getInverseOfferStatuses())
.WillByDefault(InvokeGetInverseOfferStatuses(this));
EXPECT_CALL(*this, getInverseOfferStatuses())
.WillRepeatedly(DoDefault());
ON_CALL(*this, recoverResources(_, _, _, _))
.WillByDefault(InvokeRecoverResources(this));
EXPECT_CALL(*this, recoverResources(_, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, suppressOffers(_, _))
.WillByDefault(InvokeSuppressOffers(this));
EXPECT_CALL(*this, suppressOffers(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, reviveOffers(_, _))
.WillByDefault(InvokeReviveOffers(this));
EXPECT_CALL(*this, reviveOffers(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, setQuota(_, _))
.WillByDefault(InvokeSetQuota(this));
EXPECT_CALL(*this, setQuota(_, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, removeQuota(_))
.WillByDefault(InvokeRemoveQuota(this));
EXPECT_CALL(*this, removeQuota(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, updateWeights(_))
.WillByDefault(InvokeUpdateWeights(this));
EXPECT_CALL(*this, updateWeights(_))
.WillRepeatedly(DoDefault());
ON_CALL(*this, pause())
.WillByDefault(InvokePause(this));
EXPECT_CALL(*this, pause())
.WillRepeatedly(DoDefault());
ON_CALL(*this, resume())
.WillByDefault(InvokeResume(this));
EXPECT_CALL(*this, resume())
.WillRepeatedly(DoDefault());
}
~TestAllocator() override {}
MOCK_METHOD3(initialize, void(
const Options& options,
const lambda::function<
void(const FrameworkID&,
const hashmap<std::string, hashmap<SlaveID, Resources>>&)>&,
const lambda::function<
void(const FrameworkID&,
const hashmap<SlaveID, UnavailableResources>&)>&));
MOCK_METHOD2(recover, void(
const int expectedAgentCount,
const hashmap<std::string, Quota>&));
MOCK_METHOD5(addFramework, void(
const FrameworkID&,
const FrameworkInfo&,
const hashmap<SlaveID, Resources>&,
bool active,
const std::set<std::string>&));
MOCK_METHOD1(removeFramework, void(
const FrameworkID&));
MOCK_METHOD1(activateFramework, void(
const FrameworkID&));
MOCK_METHOD1(deactivateFramework, void(
const FrameworkID&));
MOCK_METHOD3(updateFramework, void(
const FrameworkID&,
const FrameworkInfo&,
const std::set<std::string>&));
MOCK_METHOD6(addSlave, void(
const SlaveID&,
const SlaveInfo&,
const std::vector<SlaveInfo::Capability>&,
const Option<Unavailability>&,
const Resources&,
const hashmap<FrameworkID, Resources>&));
MOCK_METHOD1(removeSlave, void(
const SlaveID&));
MOCK_METHOD4(updateSlave, void(
const SlaveID&,
const SlaveInfo&,
const Option<Resources>&,
const Option<std::vector<SlaveInfo::Capability>>&));
MOCK_METHOD3(addResourceProvider, void(
const SlaveID&,
const Resources&,
const hashmap<FrameworkID, Resources>&));
MOCK_METHOD1(activateSlave, void(
const SlaveID&));
MOCK_METHOD1(deactivateSlave, void(
const SlaveID&));
MOCK_METHOD1(updateWhitelist, void(
const Option<hashset<std::string>>&));
MOCK_METHOD2(requestResources, void(
const FrameworkID&,
const std::vector<Request>&));
MOCK_METHOD4(updateAllocation, void(
const FrameworkID&,
const SlaveID&,
const Resources&,
const std::vector<ResourceConversion>&));
MOCK_METHOD2(updateAvailable, process::Future<Nothing>(
const SlaveID&,
const std::vector<Offer::Operation>&));
MOCK_METHOD2(updateUnavailability, void(
const SlaveID&,
const Option<Unavailability>&));
MOCK_METHOD5(updateInverseOffer, void(
const SlaveID&,
const FrameworkID&,
const Option<UnavailableResources>&,
const Option<mesos::allocator::InverseOfferStatus>&,
const Option<Filters>&));
MOCK_METHOD0(getInverseOfferStatuses, process::Future<
hashmap<SlaveID, hashmap<
FrameworkID,
mesos::allocator::InverseOfferStatus>>>());
MOCK_METHOD4(recoverResources, void(
const FrameworkID&,
const SlaveID&,
const Resources&,
const Option<Filters>& filters));
MOCK_METHOD2(suppressOffers, void(
const FrameworkID&,
const std::set<std::string>&));
MOCK_METHOD2(reviveOffers, void(
const FrameworkID&,
const std::set<std::string>&));
MOCK_METHOD2(setQuota, void(
const std::string&,
const Quota&));
MOCK_METHOD1(removeQuota, void(
const std::string&));
MOCK_METHOD1(updateWeights, void(
const std::vector<WeightInfo>&));
MOCK_METHOD0(pause, void());
MOCK_METHOD0(resume, void());
process::Owned<mesos::allocator::Allocator> real;
};
} // namespace tests {
} // namespace internal {
} // namespace mesos {
#endif // __TESTS_ALLOCATOR_HPP__