9
9
reason = "only dependencies for benchmarking are used in this file"
10
10
) ]
11
11
12
- use std:: {
13
- io:: Write ,
14
- path:: { Path , PathBuf } ,
15
- time:: Duration ,
16
- } ;
12
+ #[ path = "../tests/helpers/mod.rs" ]
13
+ mod helpers;
14
+
15
+ use std:: { path:: PathBuf , time:: Duration } ;
17
16
18
17
use codspeed_criterion_compat:: {
19
18
criterion_main, measurement:: Measurement , BenchmarkGroup , BenchmarkId , Criterion , SamplingMode ,
20
19
} ;
21
20
use expect_test:: expect_file;
22
- use fzn_huub :: Cli ;
23
- use pico_args :: Arguments ;
21
+
22
+ use crate :: helpers :: check_final ;
24
23
25
24
/// A configuration for instances that run for a few seconds.
26
25
const FEW_SECONDS_CONFIG : CriterionConfig = CriterionConfig {
@@ -29,17 +28,6 @@ const FEW_SECONDS_CONFIG: CriterionConfig = CriterionConfig {
29
28
measurement_time : Some ( Duration :: from_secs ( 60 ) ) ,
30
29
} ;
31
30
32
- /// The string that is printed when the solver has proven that no more/better
33
- /// solutions exist.
34
- const FZN_COMPLETE : & str = "==========\n " ;
35
-
36
- /// The string that is printed after every solution.
37
- const FZN_SEPERATOR : & str = "----------\n " ;
38
-
39
- // /// The string that is printed when the solver has proven that the instance is
40
- // /// unsatisfiable.
41
- // const FZN_UNSATISFIABLE: &str = "=====UNSATISFIABLE=====\n";
42
-
43
31
/// A configuration for instances that run in a few milliseconds.
44
32
const INSTANT_CONFIG : CriterionConfig = CriterionConfig {
45
33
sampling_mode : None ,
@@ -65,43 +53,6 @@ struct CriterionConfig {
65
53
measurement_time : Option < Duration > ,
66
54
}
67
55
68
- #[ derive( Debug , Clone , Copy ) ]
69
- /// Output stream that immediately discards all data.
70
- struct DummyOutput ;
71
-
72
- #[ derive( Debug , Clone , Copy ) ]
73
- /// What the goal is when running the solver on an instance.
74
- enum InstanceType {
75
- /// An optimal solution should be found.
76
- Optimization ,
77
- /// A correct solution should be found.
78
- Satisfaction ,
79
- }
80
-
81
- /// Run the solver on the given instance and check the output.
82
- fn check_final ( name : & str , instance_type : InstanceType ) {
83
- let base = PathBuf :: from ( "./corpus/" ) . join ( name) ;
84
- let fzn = base. with_extension ( "fzn.json" ) ;
85
- let out = run_solver ( & fzn) ;
86
- let mut slice: & str = std:: str:: from_utf8 ( & out) . expect ( "invalid utf-8" ) ;
87
- if let InstanceType :: Optimization = instance_type {
88
- assert ! (
89
- slice. ends_with( FZN_COMPLETE ) ,
90
- "Solver did not finish with complete marker: ```\n {}\n '''" ,
91
- slice
92
- ) ;
93
- slice = & slice[ ..slice. len ( ) - FZN_COMPLETE . len ( ) ] ;
94
- }
95
- assert ! (
96
- slice. ends_with( FZN_SEPERATOR ) ,
97
- "Solution did not end with a seperator: ```\n {}\n '''" ,
98
- slice
99
- ) ;
100
- slice = & slice[ ..slice. len ( ) - FZN_SEPERATOR . len ( ) ] ;
101
- let sol = base. with_extension ( "sol" ) . canonicalize ( ) . unwrap ( ) ;
102
- expect_file ! [ sol] . assert_eq ( slice) ;
103
- }
104
-
105
56
/// Benchmarks of optimization problems (finding the optimal solution).
106
57
///
107
58
/// Note that it is assumed that the solver will always find the same optimal
@@ -124,23 +75,15 @@ fn optimization(c: &mut Criterion) {
124
75
for ( instance, config) in instances {
125
76
config. apply ( & mut group) ;
126
77
let _ = group. bench_with_input ( BenchmarkId :: from_parameter ( instance) , & instance, |b, s| {
127
- b. iter ( || check_final ( s, InstanceType :: Optimization ) ) ;
78
+ let base = PathBuf :: from ( "./corpus/" ) . join ( s) ;
79
+ let fzn = base. with_extension ( "fzn.json" ) ;
80
+ let sol = base. with_extension ( "sol" ) . canonicalize ( ) . unwrap ( ) ;
81
+ b. iter ( || check_final ( & fzn, true , expect_file ! [ & sol] ) ) ;
128
82
} ) ;
129
83
}
130
84
group. finish ( ) ;
131
85
}
132
86
133
- /// Run the solver on the given instance and return the output as raw bytes.
134
- fn run_solver ( fzn : & Path ) -> Vec < u8 > {
135
- let args = Arguments :: from_vec ( vec ! [ fzn. into( ) ] ) ;
136
- let cli: Cli < _ , _ > = args. try_into ( ) . unwrap ( ) ;
137
- let mut out = Vec :: new ( ) ;
138
- let mut cli = cli. with_stdout ( & mut out) . with_stderr ( || DummyOutput , false ) ;
139
- cli. run ( )
140
- . expect ( "unexpected error while running the solver" ) ;
141
- out
142
- }
143
-
144
87
/// Benchmarks of satisfaction problems (finding any correct solution).
145
88
///
146
89
/// Note that it is assumed that the solver will always find the same solution,
@@ -157,7 +100,10 @@ fn satisfaction(c: &mut Criterion) {
157
100
for ( instance, config) in instances {
158
101
config. apply ( & mut group) ;
159
102
let _ = group. bench_with_input ( BenchmarkId :: from_parameter ( instance) , & instance, |b, s| {
160
- b. iter ( || check_final ( s, InstanceType :: Satisfaction ) ) ;
103
+ let base = PathBuf :: from ( "./corpus/" ) . join ( s) ;
104
+ let fzn = base. with_extension ( "fzn.json" ) ;
105
+ let sol = base. with_extension ( "sol" ) . canonicalize ( ) . unwrap ( ) ;
106
+ b. iter ( || check_final ( & fzn, false , expect_file ! [ & sol] ) ) ;
161
107
} ) ;
162
108
}
163
109
group. finish ( ) ;
@@ -178,15 +124,6 @@ impl CriterionConfig {
178
124
}
179
125
}
180
126
181
- impl Write for DummyOutput {
182
- fn flush ( & mut self ) -> std:: io:: Result < ( ) > {
183
- Ok ( ( ) )
184
- }
185
- fn write ( & mut self , buf : & [ u8 ] ) -> std:: io:: Result < usize > {
186
- Ok ( buf. len ( ) )
187
- }
188
- }
189
-
190
127
/// Module to capture the generated criterion code (which cannot be documented).
191
128
mod criterion_gen {
192
129
use codspeed_criterion_compat:: criterion_group;
0 commit comments