Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
solver_interface_mock.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// This header defines tools for mocking a SolverInterface.
15//
16// The SolverInterfaceMock mocks the SolverInterface itself. But this is usually
17// not enough since we have one SolverInterface per ModelProto we solve (with
18// potential updates to the initial model as ModelUpdateProto).
19//
20// The SolverInterfaceFactoryMock can be used to mock a solver factory function,
21// along with DelegatingSolver to point to an existing SolverInterfaceMock.
22//
23// The SolverFactoryRegistration can be used to register the mock solver
24// factory.
25//
26// Example of testing Solve() using all the components:
27// // Create and register the mock factory.
28// SolverInterfaceFactoryMock factory_mock;
29// SolverFactoryRegistration registration(factory_mock.AsStdFunction());
30//
31// Model model;
32//
33// // The mock solver that will be returned by the mock factory.
34// SolverInterfaceMock solver;
35//
36// {
37// // We want to assert the sequence of calls between the factory and the
38// // solver.
39// InSequence s;
40//
41// // Prepare the factory call for the next Solve() and make it return the
42// // mock solver.
43// const ModelProto expected_model = ...;
44// EXPECT_CALL(factory_mock, Call(EquivToProto(expected_model), _))
45// .WillOnce(Return(ByMove(std::make_unique<DelegatingSolver>(&solver))));
46//
47// // Prepare the mock solver and its call for the next Solve().
48// const SolveResultProto result = ...;
49// EXPECT_CALL(solver, Solve(_, _, _, _, _, _))
50// .WillOnce(Return(result));
51// }
52//
53// // Make the call to Solve() that is expected to make above calls using the
54// // registered SolverTypeProto.
55// ASSERT_OK_AND_ASSIGN(const SolveResult result,
56// Solve(model, registration.solver_type(), params));
57//
58//
59// To simulate a error in the instantiation of the solver, don't forget to use
60// ByMove() (for the same reason as above, absl::StatusOr<std::unique_ptr> is
61// not copyable):
62//
63// EXPECT_CALL(factory_mock,
64// Call(EquivToProto(basic_lp.model->ExportModel()), _))
65// .WillOnce(Return(ByMove(absl::InternalError("oops"))));
66//
67#ifndef ORTOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_MOCK_H_
68#define ORTOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_MOCK_H_
69
70#include <functional>
71#include <memory>
72#include <utility>
73
74#include "absl/base/attributes.h"
75#include "absl/base/nullability.h"
76#include "absl/base/thread_annotations.h"
77#include "absl/log/die_if_null.h"
78#include "absl/status/statusor.h"
79#include "absl/synchronization/mutex.h"
80#include "ortools/base/gmock.h"
91
92namespace operations_research {
93namespace math_opt {
94
95// A mocking of SolverInterface.
97 public:
98 MOCK_METHOD(absl::StatusOr<SolveResultProto>, Solve,
99 (const SolveParametersProto& parameters,
100 const ModelSolveParametersProto& model_parameters,
101 MessageCallback message_cb,
102 const CallbackRegistrationProto& callback_registration,
103 Callback cb, const SolveInterrupter* absl_nullable interrupter),
104 (override));
105
106 MOCK_METHOD(absl::StatusOr<bool>, Update,
107 (const ModelUpdateProto& model_update), (override));
108
109 MOCK_METHOD(absl::StatusOr<ComputeInfeasibleSubsystemResultProto>,
111 (const SolveParametersProto& parameters,
112 MessageCallback message_cb,
113 const SolveInterrupter* absl_nullable interrupter),
114 (override));
115};
116
117// An implementation of SolverInterface that delegate calls to another solver
118// interface.
119//
120// Typically used with SolverInterfaceFactoryMock to return an existing
121// SolverInterfaceMock. See the comment at the top of the file for an example.
123 public:
124 // Wraps the input solver interface, delegating calls to it. The optional
125 // destructor_cb callback will be called in ~DelegatingSolver().
126 explicit DelegatingSolver(SolverInterface* const solver,
127 std::function<void()> destructor_cb = nullptr)
128 : solver_(ABSL_DIE_IF_NULL(solver)),
129 destructor_cb_(std::move(destructor_cb)) {}
130
131 ~DelegatingSolver() override {
132 if (destructor_cb_ != nullptr) {
133 destructor_cb_();
134 }
135 }
136
137 absl::StatusOr<SolveResultProto> Solve(
138 const SolveParametersProto& parameters,
139 const ModelSolveParametersProto& model_parameters,
140 MessageCallback message_cb,
141 const CallbackRegistrationProto& callback_registration, Callback cb,
142 const SolveInterrupter* absl_nullable const interrupter) override {
143 return solver_->Solve(parameters, model_parameters, std::move(message_cb),
144 callback_registration, std::move(cb), interrupter);
145 };
146
147 absl::StatusOr<bool> Update(const ModelUpdateProto& model_update) override {
148 return solver_->Update(model_update);
149 };
150
151 absl::StatusOr<ComputeInfeasibleSubsystemResultProto>
153 const SolveParametersProto& parameters, MessageCallback message_cb,
154 const SolveInterrupter* absl_nullable const interrupter) override {
155 return solver_->ComputeInfeasibleSubsystem(
156 parameters, std::move(message_cb), interrupter);
157 }
158
159 private:
160 SolverInterface* const solver_ = nullptr;
161 const std::function<void()> destructor_cb_;
162};
163
164// A mocking of a factory of solver interface.
165//
166// Typially registered with SolverFactoryRegistration. See the comment at the
167// top of the file for an example.
169 testing::MockFunction<absl::StatusOr<std::unique_ptr<SolverInterface>>(
170 const ModelProto& model, const SolverInterface::InitArgs& init_args)>;
171
172// Creates a temporary registry with the provided solver interface factory
173// registered to an arbitrary SolverTypeProto (picked at random and returned by
174// solver_type()).
175//
176// It stops calling the input factory and fail (with CHECK) when the
177// registration when destroyed.
178//
179// It uses WithAlternateAllSolversRegistry to replace the global registry with a
180// temporary one.
181//
182// This class is thread-safe.
184 public:
185 // Registers the input factory.
186 //
187 // Asserts (with CHECK) that the input factory is not nullptr.
189
190 // Stops calling the input factory and fail instead.
192
193 // Return the unique fake SolverTypeProto which has been used to register the
194 // factory.
195 SolverTypeProto solver_type() const { return solver_type_; }
196
197 private:
198 // The data shared between this class and the caller of the factory.
199 struct CallerData {
200 explicit CallerData(SolverInterface::Factory factory);
201
202 absl::Mutex mutex;
203
204 // This will be set to nullptr at the destruction of SolverFactory.
205 SolverInterface::Factory factory ABSL_GUARDED_BY(mutex);
206 };
207
208 // A shared pointer on caller data shared between this class and the
209 // lambda registered for solver_type_.
210 std::shared_ptr<CallerData> caller_data_;
211
212 const SolverTypeProto solver_type_;
213
214 // This will override AllSolversRegistry::Instance() during the lifetime of
215 // SolverFactoryRegistration; making it only contain a registration for
216 // solver_type_.
217 const WithAlternateAllSolversRegistry alternate_registry_{
218 /*configuration=*/{}};
219};
220
221} // namespace math_opt
222} // namespace operations_research
223
224#endif // ORTOOLS_MATH_OPT_CORE_SOLVER_INTERFACE_MOCK_H_
DelegatingSolver(SolverInterface *const solver, std::function< void()> destructor_cb=nullptr)
absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *absl_nullable const interrupter) override
absl::StatusOr< bool > Update(const ModelUpdateProto &model_update) override
absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *absl_nullable const interrupter) override
MOCK_METHOD(absl::StatusOr< bool >, Update,(const ModelUpdateProto &model_update),(override))
MOCK_METHOD(absl::StatusOr< SolveResultProto >, Solve,(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *absl_nullable interrupter),(override))
MOCK_METHOD(absl::StatusOr< ComputeInfeasibleSubsystemResultProto >, ComputeInfeasibleSubsystem,(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *absl_nullable interrupter),(override))
std::function< void(const std::vector< std::string > &)> MessageCallback
virtual absl::StatusOr< bool > Update(const ModelUpdateProto &model_update)=0
virtual absl::StatusOr< SolveResultProto > Solve(const SolveParametersProto &parameters, const ModelSolveParametersProto &model_parameters, MessageCallback message_cb, const CallbackRegistrationProto &callback_registration, Callback cb, const SolveInterrupter *absl_nullable interrupter)=0
virtual absl::StatusOr< ComputeInfeasibleSubsystemResultProto > ComputeInfeasibleSubsystem(const SolveParametersProto &parameters, MessageCallback message_cb, const SolveInterrupter *absl_nullable interrupter)=0
std::function< absl::StatusOr< CallbackResultProto >( const CallbackDataProto &)> Callback
std::function< absl::StatusOr< std::unique_ptr< SolverInterface > >( const ModelProto &model, const InitArgs &init_args)> Factory
testing::MockFunction< absl::StatusOr< std::unique_ptr< SolverInterface > >( const ModelProto &model, const SolverInterface::InitArgs &init_args)> SolverInterfaceFactoryMock
OR-Tools root namespace.
STL namespace.