@@ -32,6 +32,8 @@ namespace operations_research::sat {
3232
3333namespace {
3434
35+ static constexpr int kMaxNumVars = 200 ;
36+
3537std::string GetTestDataDir () {
3638 return file::JoinPathRespectAbsolute (::testing::SrcDir (),
3739 " _main/ortools/sat/fuzz_testdata" );
@@ -83,15 +85,12 @@ void Solve(const CpModelProto& proto) {
8385 << " Presolve should not change feasibility" ;
8486}
8587
86- fuzztest::Domain<IntegerVariableProto> CpVariableDomain () {
87- fuzztest::Domain<int64_t > bound_domain =
88- fuzztest::InRange<int64_t >(-std::numeric_limits<int64_t >::max () / 2 ,
89- std::numeric_limits<int64_t >::max () / 2 );
88+ fuzztest::Domain<IntegerVariableProto> CpVariableDomain (int64_t min,
89+ int64_t max) {
90+ fuzztest::Domain<int64_t > bound_domain = fuzztest::InRange<int64_t >(min, max);
9091 fuzztest::Domain<std::pair<int64_t , int64_t >> complex_domain_gap_and_size =
91- fuzztest::PairOf (fuzztest::InRange<int64_t >(
92- 1 , std::numeric_limits<int64_t >::max () / 2 ),
93- fuzztest::InRange<int64_t >(
94- 0 , std::numeric_limits<int64_t >::max () / 2 ));
92+ fuzztest::PairOf (fuzztest::InRange<int64_t >(1 , max),
93+ fuzztest::InRange<int64_t >(0 , max));
9594 fuzztest::Domain<IntegerVariableProto> var_domain = fuzztest::ReversibleMap (
9695 [](int64_t bound1, int64_t bound2,
9796 std::vector<std::pair<int64_t , int64_t >> complex_domain_segments) {
@@ -129,9 +128,8 @@ fuzztest::Domain<IntegerVariableProto> CpVariableDomain() {
129128 fuzztest::VectorOf (complex_domain_gap_and_size));
130129
131130 return fuzztest::Filter (
132- [](IntegerVariableProto var) {
133- return var.domain (var.domain ().size () - 1 ) <=
134- std::numeric_limits<int64_t >::max () / 2 ;
131+ [max](IntegerVariableProto var) {
132+ return var.domain (var.domain ().size () - 1 ) <= max;
135133 },
136134 var_domain);
137135}
@@ -147,7 +145,107 @@ ModelProtoVariablesDomain() {
147145 }
148146 return ValidateCpModel (model).empty ();
149147 },
150- fuzztest::VectorOf (CpVariableDomain ()));
148+ fuzztest::VectorOf (
149+ CpVariableDomain (-std::numeric_limits<int64_t >::max () / 2 ,
150+ std::numeric_limits<int64_t >::max () / 2 ))
151+ .WithMaxSize (kMaxNumVars ));
152+ }
153+
154+ fuzztest::Domain<LinearExpressionProto> LinearExprDomain () {
155+ fuzztest::Domain<int64_t > offset_domain =
156+ fuzztest::InRange<int64_t >(-std::numeric_limits<int64_t >::max () / 2 ,
157+ std::numeric_limits<int64_t >::max () / 2 );
158+ fuzztest::Domain<std::pair<int64_t , int64_t >> variable_and_coefficient =
159+ fuzztest::PairOf (
160+ fuzztest::InRange<int64_t >(0 , kMaxNumVars - 1 ),
161+ fuzztest::InRange<int64_t >(-std::numeric_limits<int64_t >::max () / 2 ,
162+ std::numeric_limits<int64_t >::max () / 2 ));
163+ return fuzztest::ReversibleMap (
164+ [](int64_t offset,
165+ std::vector<std::pair<int64_t , int64_t >> variable_and_coefficient) {
166+ LinearExpressionProto expr;
167+ for (const auto & [var, coeff] : variable_and_coefficient) {
168+ expr.add_vars (var);
169+ expr.add_coeffs (coeff);
170+ }
171+ expr.set_offset (offset);
172+ return expr;
173+ },
174+ [](LinearExpressionProto expr) {
175+ using Type =
176+ std::tuple<int64_t , std::vector<std::pair<int64_t , int64_t >>>;
177+ Type expr_inputs;
178+ expr_inputs = {expr.offset (), {}};
179+ std::vector<std::pair<int64_t , int64_t >>& variable_and_coefficient =
180+ std::get<1 >(expr_inputs);
181+ if (expr.vars_size () != expr.coeffs_size ()) {
182+ return std::optional<Type>();
183+ }
184+ for (int i = 0 ; i < expr.vars_size (); ++i) {
185+ variable_and_coefficient.push_back ({expr.vars (i), expr.coeffs (i)});
186+ }
187+ return std::optional<Type>(expr_inputs);
188+ },
189+ offset_domain, fuzztest::VectorOf (variable_and_coefficient));
190+ }
191+
192+ fuzztest::Domain<LinearConstraintProto> LinearConstraintDomain () {
193+ fuzztest::Domain<std::pair<int64_t , int64_t >> variable_and_coefficient =
194+ fuzztest::PairOf (
195+ fuzztest::InRange<int64_t >(0 , kMaxNumVars - 1 ),
196+ fuzztest::InRange<int64_t >(-std::numeric_limits<int64_t >::max () / 2 ,
197+ std::numeric_limits<int64_t >::max () / 2 ));
198+ return fuzztest::ReversibleMap (
199+ [](IntegerVariableProto domain,
200+ std::vector<std::pair<int64_t , int64_t >> variable_and_coefficient) {
201+ LinearConstraintProto constraint;
202+ for (const auto & [var, coeff] : variable_and_coefficient) {
203+ constraint.add_vars (var);
204+ constraint.add_coeffs (coeff);
205+ }
206+ *constraint.mutable_domain () = domain.domain ();
207+ return constraint;
208+ },
209+ [](LinearConstraintProto constraint) {
210+ using Type = std::tuple<IntegerVariableProto,
211+ std::vector<std::pair<int64_t , int64_t >>>;
212+ Type constraint_inputs = {IntegerVariableProto (), {}};
213+ *std::get<0 >(constraint_inputs).mutable_domain () = constraint.domain ();
214+ std::vector<std::pair<int64_t , int64_t >>& variable_and_coefficient =
215+ std::get<1 >(constraint_inputs);
216+ if (constraint.vars_size () != constraint.coeffs_size () ||
217+ constraint.vars ().empty ()) {
218+ return std::optional<Type>();
219+ }
220+ for (int i = 0 ; i < constraint.vars_size (); ++i) {
221+ variable_and_coefficient.push_back (
222+ {constraint.vars (i), constraint.coeffs (i)});
223+ }
224+ return std::optional<Type>(constraint_inputs);
225+ },
226+ CpVariableDomain (std::numeric_limits<int64_t >::min (),
227+ std::numeric_limits<int64_t >::max ()),
228+ fuzztest::VectorOf (variable_and_coefficient));
229+ }
230+
231+ fuzztest::Domain<IntervalConstraintProto> IntervalConstraintDomain () {
232+ return fuzztest::Arbitrary<IntervalConstraintProto>()
233+ .WithProtobufField (" start" , LinearExprDomain ())
234+ .WithProtobufField (" end" , LinearExprDomain ())
235+ .WithProtobufField (" size" , LinearExprDomain ());
236+ }
237+
238+ fuzztest::Domain<LinearArgumentProto> LinearArgumentDomain () {
239+ return fuzztest::Arbitrary<LinearArgumentProto>()
240+ .WithProtobufField (" target" , LinearExprDomain ())
241+ .WithRepeatedProtobufField (" exprs" ,
242+ fuzztest::VectorOf (LinearExprDomain ()));
243+ }
244+
245+ fuzztest::Domain<BoolArgumentProto> BoolArgumentDomain () {
246+ return fuzztest::Arbitrary<BoolArgumentProto>().WithRepeatedInt32Field (
247+ " literals" , fuzztest::VectorOf (fuzztest::InRange<int32_t >(
248+ -kMaxNumVars , kMaxNumVars - 1 )));
151249}
152250
153251// Fuzzing repeats solve() 100 times, and timeout after 600s.
@@ -158,10 +256,23 @@ FUZZ_TEST(CpModelProtoFuzzer, Solve)
158256 .WithRepeatedProtobufField(" variables" , ModelProtoVariablesDomain())
159257 .WithRepeatedProtobufField(
160258 " constraints" ,
161- fuzztest::VectorOf (fuzztest::Arbitrary<ConstraintProto>()
162- .WithOneofAlwaysSet(" constraint" )
163- .WithFieldUnset(" name" )
164- .WithFieldUnset(" dummy_constraint" )))
259+ fuzztest::VectorOf (
260+ fuzztest::Arbitrary<ConstraintProto>()
261+ .WithOneofAlwaysSet(" constraint" )
262+ .WithFieldUnset(" name" )
263+ .WithFieldUnset(" dummy_constraint" )
264+ .WithProtobufField(" bool_or" , BoolArgumentDomain())
265+ .WithProtobufField(" bool_and" , BoolArgumentDomain())
266+ .WithProtobufField(" at_most_one" , BoolArgumentDomain())
267+ .WithProtobufField(" exactly_one" , BoolArgumentDomain())
268+ .WithProtobufField(" bool_xor" , BoolArgumentDomain())
269+ .WithProtobufField(" int_div" , LinearArgumentDomain())
270+ .WithProtobufField(" int_mod" , LinearArgumentDomain())
271+ .WithProtobufField(" int_prod" , LinearArgumentDomain())
272+ .WithProtobufField(" lin_max" , LinearArgumentDomain())
273+ .WithProtobufField(" linear" , LinearConstraintDomain())
274+ .WithProtobufField(" interval" ,
275+ IntervalConstraintDomain ())))
165276 .WithFieldUnset(" name" )
166277 .WithFieldUnset(" symmetry" )
167278 .WithProtobufField(" objective" ,
0 commit comments