@@ -38,76 +38,127 @@ static const AnalyzerOptions DefaultOpts = [] {
3838
3939 // Remember to update the tests in this file when these values change.
4040 // Also update the doc comment of `interpretQueryResult`.
41- assert (Config.Z3CrosscheckRLimitThreshold == 400'000 );
42- assert (Config.Z3CrosscheckTimeoutThreshold == 300_ms );
41+ assert (Config.Z3CrosscheckRLimitThreshold == 0 );
42+ assert (Config.Z3CrosscheckTimeoutThreshold == 15 ' 000_ms );
4343 // Usually, when the timeout/rlimit threshold is reached, Z3 only slightly
4444 // overshoots until it realizes that it overshoot and needs to back off.
4545 // Consequently, the measured timeout should be fairly close to the threshold.
4646 // Same reasoning applies to the rlimit too.
4747 return Config;
4848}();
4949
50+ static const AnalyzerOptions LimitedOpts = [] {
51+ AnalyzerOptions Config = DefaultOpts;
52+ Config.Z3CrosscheckEQClassTimeoutThreshold = 700_ms;
53+ Config.Z3CrosscheckTimeoutThreshold = 300_step;
54+ Config.Z3CrosscheckRLimitThreshold = 400' 000_step;
55+ return Config;
56+ }();
57+
5058namespace {
5159
60+ template <const AnalyzerOptions &Opts>
5261class Z3CrosscheckOracleTest : public testing ::Test {
5362public:
5463 Z3Decision interpretQueryResult (const Z3Result &Result) {
5564 return Oracle.interpretQueryResult (Result);
5665 }
5766
5867private:
59- Z3CrosscheckOracle Oracle = Z3CrosscheckOracle(DefaultOpts );
68+ Z3CrosscheckOracle Oracle = Z3CrosscheckOracle(Opts );
6069};
6170
62- TEST_F (Z3CrosscheckOracleTest, AcceptsFirstSAT) {
71+ using DefaultZ3CrosscheckOracleTest = Z3CrosscheckOracleTest<DefaultOpts>;
72+ using LimitedZ3CrosscheckOracleTest = Z3CrosscheckOracleTest<LimitedOpts>;
73+
74+ TEST_F (DefaultZ3CrosscheckOracleTest, AcceptsFirstSAT) {
75+ ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 25_ms, 1000_step}));
76+ }
77+ TEST_F (LimitedZ3CrosscheckOracleTest, AcceptsFirstSAT) {
6378 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 25_ms, 1000_step}));
6479}
6580
66- TEST_F (Z3CrosscheckOracleTest, AcceptsSAT) {
81+ TEST_F (DefaultZ3CrosscheckOracleTest, AcceptsSAT) {
82+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
83+ ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 25_ms, 1000_step}));
84+ }
85+ TEST_F (LimitedZ3CrosscheckOracleTest, AcceptsSAT) {
6786 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
6887 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 25_ms, 1000_step}));
6988}
7089
71- TEST_F (Z3CrosscheckOracleTest, SATWhenItGoesOverTime) {
90+ TEST_F (DefaultZ3CrosscheckOracleTest, SATWhenItGoesOverTime) {
91+ // Even if it times out, if it is SAT, we should accept it.
92+ ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 15' 010_ms, 1000_step}));
93+ }
94+ TEST_F (LimitedZ3CrosscheckOracleTest, SATWhenItGoesOverTime) {
7295 // Even if it times out, if it is SAT, we should accept it.
7396 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 310_ms, 1000_step}));
7497}
7598
76- TEST_F (Z3CrosscheckOracleTest, UNSATWhenItGoesOverTime) {
99+ TEST_F (DefaultZ3CrosscheckOracleTest, UNSATWhenItGoesOverTime) {
100+ ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNSAT, 15' 010_ms, 1000_step}));
101+ }
102+ TEST_F (LimitedZ3CrosscheckOracleTest, UNSATWhenItGoesOverTime) {
77103 ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNSAT, 310_ms, 1000_step}));
78104}
79105
80- TEST_F (Z3CrosscheckOracleTest, RejectsTimeout) {
106+ TEST_F (DefaultZ3CrosscheckOracleTest, RejectsTimeout) {
107+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
108+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
109+ ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNDEF, 15' 010_ms, 1000_step}));
110+ }
111+ TEST_F (LimitedZ3CrosscheckOracleTest, RejectsTimeout) {
81112 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
82113 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
83114 ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNDEF, 310_ms, 1000_step}));
84115}
85116
86- TEST_F (Z3CrosscheckOracleTest, RejectsUNSATs) {
117+ TEST_F (DefaultZ3CrosscheckOracleTest, RejectsUNSATs) {
118+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
119+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
120+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
121+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
122+ }
123+ TEST_F (LimitedZ3CrosscheckOracleTest, RejectsUNSATs) {
87124 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
88125 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
89126 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
90127 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
91128}
92129
93- // Testing cut heuristics:
94- // =======================
130+ // Testing cut heuristics of the two configurations :
131+ // =================================================
95132
96- TEST_F (Z3CrosscheckOracleTest, RejectEQClassIfSpendsTooMuchTotalTime) {
133+ TEST_F (DefaultZ3CrosscheckOracleTest, RejectEQClassIfSpendsTooMuchTotalTime) {
134+ // Simulate long queries, that barely doesn't trigger the timeout.
135+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 14' 990_ms, 1000_step}));
136+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 14' 990_ms, 1000_step}));
137+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 14' 990_ms, 1000_step}));
138+ }
139+ TEST_F (LimitedZ3CrosscheckOracleTest, RejectEQClassIfSpendsTooMuchTotalTime) {
97140 // Simulate long queries, that barely doesn't trigger the timeout.
98141 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 290_ms, 1000_step}));
99142 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 290_ms, 1000_step}));
100143 ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNSAT, 290_ms, 1000_step}));
101144}
102145
103- TEST_F (Z3CrosscheckOracleTest, SATWhenItSpendsTooMuchTotalTime) {
146+ TEST_F (DefaultZ3CrosscheckOracleTest, SATWhenItSpendsTooMuchTotalTime) {
147+ // Simulate long queries, that barely doesn't trigger the timeout.
148+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 14' 990_ms, 1000_step}));
149+ ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 14' 990_ms, 1000_step}));
150+ ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 14' 990_ms, 1000_step}));
151+ }
152+ TEST_F (LimitedZ3CrosscheckOracleTest, SATWhenItSpendsTooMuchTotalTime) {
104153 // Simulate long queries, that barely doesn't trigger the timeout.
105154 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 290_ms, 1000_step}));
106155 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 290_ms, 1000_step}));
107156 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 290_ms, 1000_step}));
108157}
109158
110- TEST_F (Z3CrosscheckOracleTest, RejectEQClassIfAttemptsManySmallQueries) {
159+ // Z3CrosscheckEQClassTimeoutThreshold is disabled in default configuration, so
160+ // it doesn't make sense to test that.
161+ TEST_F (LimitedZ3CrosscheckOracleTest, RejectEQClassIfAttemptsManySmallQueries) {
111162 // Simulate quick, but many queries: 35 quick UNSAT queries.
112163 // 35*20ms = 700ms, which is equal to the 700ms threshold.
113164 for (int i = 0 ; i < 35 ; ++i) {
@@ -117,7 +168,9 @@ TEST_F(Z3CrosscheckOracleTest, RejectEQClassIfAttemptsManySmallQueries) {
117168 ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNSAT, 1_ms, 1000_step}));
118169}
119170
120- TEST_F (Z3CrosscheckOracleTest, SATWhenIfAttemptsManySmallQueries) {
171+ // Z3CrosscheckEQClassTimeoutThreshold is disabled in default configuration, so
172+ // it doesn't make sense to test that.
173+ TEST_F (LimitedZ3CrosscheckOracleTest, SATWhenItAttemptsManySmallQueries) {
121174 // Simulate quick, but many queries: 35 quick UNSAT queries.
122175 // 35*20ms = 700ms, which is equal to the 700ms threshold.
123176 for (int i = 0 ; i < 35 ; ++i) {
@@ -128,16 +181,34 @@ TEST_F(Z3CrosscheckOracleTest, SATWhenIfAttemptsManySmallQueries) {
128181 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 200_ms, 1000_step}));
129182}
130183
131- TEST_F (Z3CrosscheckOracleTest, RejectEQClassIfExhaustsRLimit) {
184+ // Z3CrosscheckRLimitThreshold is disabled in default configuration, so it
185+ // doesn't make sense to test that.
186+ TEST_F (LimitedZ3CrosscheckOracleTest, RejectEQClassIfExhaustsRLimit) {
132187 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
133188 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
134189 ASSERT_EQ (RejectEQClass, interpretQueryResult ({UNDEF, 25_ms, 405' 000_step}));
135190}
136191
137- TEST_F (Z3CrosscheckOracleTest, SATWhenItExhaustsRLimit) {
192+ // Z3CrosscheckRLimitThreshold is disabled in default configuration, so it
193+ // doesn't make sense to test that.
194+ TEST_F (LimitedZ3CrosscheckOracleTest, SATWhenItExhaustsRLimit) {
138195 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
139196 ASSERT_EQ (RejectReport, interpretQueryResult ({UNSAT, 25_ms, 1000_step}));
140197 ASSERT_EQ (AcceptReport, interpretQueryResult ({SAT, 25_ms, 405' 000_step}));
141198}
142199
200+ // Demonstrate the weaknesses of the default configuration:
201+ // ========================================================
202+
203+ TEST_F (DefaultZ3CrosscheckOracleTest, ManySlowQueriesHangTheAnalyzer) {
204+ // Simulate many slow queries: 250 slow UNSAT queries.
205+ // 250*14000ms = 3500s, ~1 hour. Since we disabled the total time limitation,
206+ // this eqclass would take roughly 1 hour to process.
207+ // It doesn't matter what rlimit the queries consume.
208+ for (int i = 0 ; i < 250 ; ++i) {
209+ ASSERT_EQ (RejectReport,
210+ interpretQueryResult ({UNSAT, 14' 000_ms, 1'000' 000_step}));
211+ }
212+ }
213+
143214} // namespace
0 commit comments