1*b0d29bc4SBrooks Davis // Copyright 2014 The Kyua Authors.
2*b0d29bc4SBrooks Davis // All rights reserved.
3*b0d29bc4SBrooks Davis //
4*b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5*b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6*b0d29bc4SBrooks Davis // met:
7*b0d29bc4SBrooks Davis //
8*b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer.
10*b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11*b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the
12*b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution.
13*b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14*b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software
15*b0d29bc4SBrooks Davis // without specific prior written permission.
16*b0d29bc4SBrooks Davis //
17*b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*b0d29bc4SBrooks Davis
29*b0d29bc4SBrooks Davis #include "engine/scanner.hpp"
30*b0d29bc4SBrooks Davis
31*b0d29bc4SBrooks Davis #include <cstdarg>
32*b0d29bc4SBrooks Davis #include <cstddef>
33*b0d29bc4SBrooks Davis #include <typeinfo>
34*b0d29bc4SBrooks Davis
35*b0d29bc4SBrooks Davis #include <atf-c++.hpp>
36*b0d29bc4SBrooks Davis
37*b0d29bc4SBrooks Davis #include "engine/filters.hpp"
38*b0d29bc4SBrooks Davis #include "model/metadata.hpp"
39*b0d29bc4SBrooks Davis #include "model/test_case.hpp"
40*b0d29bc4SBrooks Davis #include "model/test_program.hpp"
41*b0d29bc4SBrooks Davis #include "utils/format/containers.ipp"
42*b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
43*b0d29bc4SBrooks Davis #include "utils/optional.ipp"
44*b0d29bc4SBrooks Davis
45*b0d29bc4SBrooks Davis namespace fs = utils::fs;
46*b0d29bc4SBrooks Davis
47*b0d29bc4SBrooks Davis using utils::optional;
48*b0d29bc4SBrooks Davis
49*b0d29bc4SBrooks Davis
50*b0d29bc4SBrooks Davis namespace {
51*b0d29bc4SBrooks Davis
52*b0d29bc4SBrooks Davis
53*b0d29bc4SBrooks Davis /// Test program that implements a mock test_cases() lazy call.
54*b0d29bc4SBrooks Davis class mock_test_program : public model::test_program {
55*b0d29bc4SBrooks Davis /// Number of times test_cases has been called.
56*b0d29bc4SBrooks Davis mutable std::size_t _num_calls;
57*b0d29bc4SBrooks Davis
58*b0d29bc4SBrooks Davis /// Collection of test cases; lazily initialized.
59*b0d29bc4SBrooks Davis mutable model::test_cases_map _test_cases;
60*b0d29bc4SBrooks Davis
61*b0d29bc4SBrooks Davis public:
62*b0d29bc4SBrooks Davis /// Constructs a new test program.
63*b0d29bc4SBrooks Davis ///
64*b0d29bc4SBrooks Davis /// \param binary_ The name of the test program binary relative to root_.
mock_test_program(const fs::path & binary_)65*b0d29bc4SBrooks Davis mock_test_program(const fs::path& binary_) :
66*b0d29bc4SBrooks Davis test_program("unused-interface", binary_, fs::path("unused-root"),
67*b0d29bc4SBrooks Davis "unused-suite", model::metadata_builder().build(),
68*b0d29bc4SBrooks Davis model::test_cases_map()),
69*b0d29bc4SBrooks Davis _num_calls(0)
70*b0d29bc4SBrooks Davis {
71*b0d29bc4SBrooks Davis }
72*b0d29bc4SBrooks Davis
73*b0d29bc4SBrooks Davis /// Gets or loads the list of test cases from the test program.
74*b0d29bc4SBrooks Davis ///
75*b0d29bc4SBrooks Davis /// \return The list of test cases provided by the test program.
76*b0d29bc4SBrooks Davis const model::test_cases_map&
test_cases(void) const77*b0d29bc4SBrooks Davis test_cases(void) const
78*b0d29bc4SBrooks Davis {
79*b0d29bc4SBrooks Davis if (_num_calls == 0) {
80*b0d29bc4SBrooks Davis const model::metadata metadata = model::metadata_builder().build();
81*b0d29bc4SBrooks Davis const model::test_case tc1("one", metadata);
82*b0d29bc4SBrooks Davis const model::test_case tc2("two", metadata);
83*b0d29bc4SBrooks Davis _test_cases.insert(model::test_cases_map::value_type("one", tc1));
84*b0d29bc4SBrooks Davis _test_cases.insert(model::test_cases_map::value_type("two", tc2));
85*b0d29bc4SBrooks Davis }
86*b0d29bc4SBrooks Davis _num_calls++;
87*b0d29bc4SBrooks Davis return _test_cases;
88*b0d29bc4SBrooks Davis }
89*b0d29bc4SBrooks Davis
90*b0d29bc4SBrooks Davis /// Returns the number of times test_cases() has been called.
91*b0d29bc4SBrooks Davis ///
92*b0d29bc4SBrooks Davis /// \return A counter.
93*b0d29bc4SBrooks Davis std::size_t
num_calls(void) const94*b0d29bc4SBrooks Davis num_calls(void) const
95*b0d29bc4SBrooks Davis {
96*b0d29bc4SBrooks Davis return _num_calls;
97*b0d29bc4SBrooks Davis }
98*b0d29bc4SBrooks Davis };
99*b0d29bc4SBrooks Davis
100*b0d29bc4SBrooks Davis
101*b0d29bc4SBrooks Davis /// Syntactic sugar to instantiate a test program with various test cases.
102*b0d29bc4SBrooks Davis ///
103*b0d29bc4SBrooks Davis /// The scanner only cares about the relative path of the test program object
104*b0d29bc4SBrooks Davis /// and the names of the test cases. This function helps in instantiating a
105*b0d29bc4SBrooks Davis /// test program that has the minimum set of details only.
106*b0d29bc4SBrooks Davis ///
107*b0d29bc4SBrooks Davis /// \param relative_path Relative path to the test program.
108*b0d29bc4SBrooks Davis /// \param ... List of test case names to add to the test program. Must be
109*b0d29bc4SBrooks Davis /// NULL-terminated.
110*b0d29bc4SBrooks Davis ///
111*b0d29bc4SBrooks Davis /// \return A constructed test program.
112*b0d29bc4SBrooks Davis static model::test_program_ptr
new_test_program(const char * relative_path,...)113*b0d29bc4SBrooks Davis new_test_program(const char* relative_path, ...)
114*b0d29bc4SBrooks Davis {
115*b0d29bc4SBrooks Davis model::test_program_builder builder(
116*b0d29bc4SBrooks Davis "unused-interface", fs::path(relative_path), fs::path("unused-root"),
117*b0d29bc4SBrooks Davis "unused-suite");
118*b0d29bc4SBrooks Davis
119*b0d29bc4SBrooks Davis va_list ap;
120*b0d29bc4SBrooks Davis va_start(ap, relative_path);
121*b0d29bc4SBrooks Davis const char* test_case_name;
122*b0d29bc4SBrooks Davis while ((test_case_name = va_arg(ap, const char*)) != NULL) {
123*b0d29bc4SBrooks Davis builder.add_test_case(test_case_name);
124*b0d29bc4SBrooks Davis }
125*b0d29bc4SBrooks Davis va_end(ap);
126*b0d29bc4SBrooks Davis
127*b0d29bc4SBrooks Davis return builder.build_ptr();
128*b0d29bc4SBrooks Davis }
129*b0d29bc4SBrooks Davis
130*b0d29bc4SBrooks Davis
131*b0d29bc4SBrooks Davis /// Yields all test cases in the scanner for simplicity of testing.
132*b0d29bc4SBrooks Davis ///
133*b0d29bc4SBrooks Davis /// In most of the tests below, we just care about the scanner returning the
134*b0d29bc4SBrooks Davis /// full set of matching test cases, not the specific behavior of every single
135*b0d29bc4SBrooks Davis /// yield() call. This function just returns the whole set, which helps in
136*b0d29bc4SBrooks Davis /// writing functional tests.
137*b0d29bc4SBrooks Davis ///
138*b0d29bc4SBrooks Davis /// \param scanner The scanner on which to iterate.
139*b0d29bc4SBrooks Davis ///
140*b0d29bc4SBrooks Davis /// \return The full collection of results yielded by the scanner.
141*b0d29bc4SBrooks Davis static std::set< engine::scan_result >
yield_all(engine::scanner & scanner)142*b0d29bc4SBrooks Davis yield_all(engine::scanner& scanner)
143*b0d29bc4SBrooks Davis {
144*b0d29bc4SBrooks Davis std::set< engine::scan_result > results;
145*b0d29bc4SBrooks Davis while (!scanner.done()) {
146*b0d29bc4SBrooks Davis const optional< engine::scan_result > result = scanner.yield();
147*b0d29bc4SBrooks Davis ATF_REQUIRE(result);
148*b0d29bc4SBrooks Davis results.insert(result.get());
149*b0d29bc4SBrooks Davis }
150*b0d29bc4SBrooks Davis ATF_REQUIRE(!scanner.yield());
151*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.done());
152*b0d29bc4SBrooks Davis return results;
153*b0d29bc4SBrooks Davis }
154*b0d29bc4SBrooks Davis
155*b0d29bc4SBrooks Davis
156*b0d29bc4SBrooks Davis } // anonymous namespace
157*b0d29bc4SBrooks Davis
158*b0d29bc4SBrooks Davis
159*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__no_tests);
ATF_TEST_CASE_BODY(scanner__no_filters__no_tests)160*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__no_tests)
161*b0d29bc4SBrooks Davis {
162*b0d29bc4SBrooks Davis const model::test_programs_vector test_programs;
163*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
164*b0d29bc4SBrooks Davis
165*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
166*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.done());
167*b0d29bc4SBrooks Davis ATF_REQUIRE(!scanner.yield());
168*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
169*b0d29bc4SBrooks Davis }
170*b0d29bc4SBrooks Davis
171*b0d29bc4SBrooks Davis
172*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__one_test_in_one_program);
ATF_TEST_CASE_BODY(scanner__no_filters__one_test_in_one_program)173*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__one_test_in_one_program)
174*b0d29bc4SBrooks Davis {
175*b0d29bc4SBrooks Davis const model::test_program_ptr test_program = new_test_program(
176*b0d29bc4SBrooks Davis "dir/program", "lone_test", NULL);
177*b0d29bc4SBrooks Davis
178*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
179*b0d29bc4SBrooks Davis test_programs.push_back(test_program);
180*b0d29bc4SBrooks Davis
181*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
182*b0d29bc4SBrooks Davis
183*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
184*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program, "lone_test"));
185*b0d29bc4SBrooks Davis
186*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
187*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
188*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
189*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
190*b0d29bc4SBrooks Davis }
191*b0d29bc4SBrooks Davis
192*b0d29bc4SBrooks Davis
193*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__one_test_per_many_programs);
ATF_TEST_CASE_BODY(scanner__no_filters__one_test_per_many_programs)194*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__one_test_per_many_programs)
195*b0d29bc4SBrooks Davis {
196*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1 = new_test_program(
197*b0d29bc4SBrooks Davis "dir/program1", "foo_test", NULL);
198*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2 = new_test_program(
199*b0d29bc4SBrooks Davis "program2", "bar_test", NULL);
200*b0d29bc4SBrooks Davis const model::test_program_ptr test_program3 = new_test_program(
201*b0d29bc4SBrooks Davis "a/b/c/d/e/program3", "baz_test", NULL);
202*b0d29bc4SBrooks Davis
203*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
204*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
205*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
206*b0d29bc4SBrooks Davis test_programs.push_back(test_program3);
207*b0d29bc4SBrooks Davis
208*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
209*b0d29bc4SBrooks Davis
210*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
211*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "foo_test"));
212*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program2, "bar_test"));
213*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program3, "baz_test"));
214*b0d29bc4SBrooks Davis
215*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
216*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
217*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
218*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
219*b0d29bc4SBrooks Davis }
220*b0d29bc4SBrooks Davis
221*b0d29bc4SBrooks Davis
222*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__many_tests_in_one_program);
ATF_TEST_CASE_BODY(scanner__no_filters__many_tests_in_one_program)223*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__many_tests_in_one_program)
224*b0d29bc4SBrooks Davis {
225*b0d29bc4SBrooks Davis const model::test_program_ptr test_program = new_test_program(
226*b0d29bc4SBrooks Davis "dir/program", "first_test", "second_test", "third_test", NULL);
227*b0d29bc4SBrooks Davis
228*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
229*b0d29bc4SBrooks Davis test_programs.push_back(test_program);
230*b0d29bc4SBrooks Davis
231*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
232*b0d29bc4SBrooks Davis
233*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
234*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program, "first_test"));
235*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program, "second_test"));
236*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program, "third_test"));
237*b0d29bc4SBrooks Davis
238*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
239*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
240*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
241*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
242*b0d29bc4SBrooks Davis }
243*b0d29bc4SBrooks Davis
244*b0d29bc4SBrooks Davis
245*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__many_tests_per_many_programs);
ATF_TEST_CASE_BODY(scanner__no_filters__many_tests_per_many_programs)246*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__many_tests_per_many_programs)
247*b0d29bc4SBrooks Davis {
248*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1 = new_test_program(
249*b0d29bc4SBrooks Davis "dir/program1", "foo_test", "bar_test", "baz_test", NULL);
250*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2 = new_test_program(
251*b0d29bc4SBrooks Davis "program2", "lone_test", NULL);
252*b0d29bc4SBrooks Davis const model::test_program_ptr test_program3 = new_test_program(
253*b0d29bc4SBrooks Davis "a/b/c/d/e/program3", "another_test", "last_test", NULL);
254*b0d29bc4SBrooks Davis
255*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
256*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
257*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
258*b0d29bc4SBrooks Davis test_programs.push_back(test_program3);
259*b0d29bc4SBrooks Davis
260*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
261*b0d29bc4SBrooks Davis
262*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
263*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "foo_test"));
264*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "bar_test"));
265*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "baz_test"));
266*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program2, "lone_test"));
267*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program3, "another_test"));
268*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program3, "last_test"));
269*b0d29bc4SBrooks Davis
270*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
271*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
272*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
273*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
274*b0d29bc4SBrooks Davis }
275*b0d29bc4SBrooks Davis
276*b0d29bc4SBrooks Davis
277*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__no_filters__verify_lazy_loads);
ATF_TEST_CASE_BODY(scanner__no_filters__verify_lazy_loads)278*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__no_filters__verify_lazy_loads)
279*b0d29bc4SBrooks Davis {
280*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1(new mock_test_program(
281*b0d29bc4SBrooks Davis fs::path("first")));
282*b0d29bc4SBrooks Davis const mock_test_program* mock_program1 =
283*b0d29bc4SBrooks Davis dynamic_cast< const mock_test_program* >(test_program1.get());
284*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2(new mock_test_program(
285*b0d29bc4SBrooks Davis fs::path("second")));
286*b0d29bc4SBrooks Davis const mock_test_program* mock_program2 =
287*b0d29bc4SBrooks Davis dynamic_cast< const mock_test_program* >(test_program2.get());
288*b0d29bc4SBrooks Davis
289*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
290*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
291*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
292*b0d29bc4SBrooks Davis
293*b0d29bc4SBrooks Davis const std::set< engine::test_filter > filters;
294*b0d29bc4SBrooks Davis
295*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
296*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "one"));
297*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "two"));
298*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program2, "one"));
299*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program2, "two"));
300*b0d29bc4SBrooks Davis
301*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
302*b0d29bc4SBrooks Davis std::set< engine::scan_result > results;
303*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program1->num_calls());
304*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
305*b0d29bc4SBrooks Davis
306*b0d29bc4SBrooks Davis // This abuses the internal implementation of the scanner by making
307*b0d29bc4SBrooks Davis // assumptions on the order of the results.
308*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
309*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
310*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
311*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
312*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
313*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
314*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
315*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
316*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program2->num_calls());
317*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
318*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
319*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program2->num_calls());
320*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.done());
321*b0d29bc4SBrooks Davis
322*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
323*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
324*b0d29bc4SBrooks Davis
325*b0d29bc4SBrooks Davis // Make sure we are still talking to the original objects.
326*b0d29bc4SBrooks Davis for (std::set< engine::scan_result >::const_iterator iter = results.begin();
327*b0d29bc4SBrooks Davis iter != results.end(); ++iter) {
328*b0d29bc4SBrooks Davis const mock_test_program* mock_program =
329*b0d29bc4SBrooks Davis dynamic_cast< const mock_test_program* >((*iter).first.get());
330*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program->num_calls());
331*b0d29bc4SBrooks Davis }
332*b0d29bc4SBrooks Davis }
333*b0d29bc4SBrooks Davis
334*b0d29bc4SBrooks Davis
335*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__with_filters__no_tests);
ATF_TEST_CASE_BODY(scanner__with_filters__no_tests)336*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__with_filters__no_tests)
337*b0d29bc4SBrooks Davis {
338*b0d29bc4SBrooks Davis const model::test_programs_vector test_programs;
339*b0d29bc4SBrooks Davis
340*b0d29bc4SBrooks Davis std::set< engine::test_filter > filters;
341*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("foo"), "bar"));
342*b0d29bc4SBrooks Davis
343*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
344*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.done());
345*b0d29bc4SBrooks Davis ATF_REQUIRE(!scanner.yield());
346*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(filters, scanner.unused_filters());
347*b0d29bc4SBrooks Davis }
348*b0d29bc4SBrooks Davis
349*b0d29bc4SBrooks Davis
350*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__with_filters__no_matches);
ATF_TEST_CASE_BODY(scanner__with_filters__no_matches)351*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__with_filters__no_matches)
352*b0d29bc4SBrooks Davis {
353*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1 = new_test_program(
354*b0d29bc4SBrooks Davis "dir/program1", "foo_test", "bar_test", "baz_test", NULL);
355*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2 = new_test_program(
356*b0d29bc4SBrooks Davis "dir/program2", "bar_test", NULL);
357*b0d29bc4SBrooks Davis const model::test_program_ptr test_program3 = new_test_program(
358*b0d29bc4SBrooks Davis "program3", "another_test", "last_test", NULL);
359*b0d29bc4SBrooks Davis
360*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
361*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
362*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
363*b0d29bc4SBrooks Davis test_programs.push_back(test_program3);
364*b0d29bc4SBrooks Davis
365*b0d29bc4SBrooks Davis std::set< engine::test_filter > filters;
366*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("dir/program2"), "baz_test"));
367*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("program4"), "another_test"));
368*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("dir/program3"), ""));
369*b0d29bc4SBrooks Davis
370*b0d29bc4SBrooks Davis const std::set< engine::scan_result > exp_results;
371*b0d29bc4SBrooks Davis
372*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
373*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
374*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
375*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(filters, scanner.unused_filters());
376*b0d29bc4SBrooks Davis }
377*b0d29bc4SBrooks Davis
378*b0d29bc4SBrooks Davis
379*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__with_filters__some_matches);
ATF_TEST_CASE_BODY(scanner__with_filters__some_matches)380*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__with_filters__some_matches)
381*b0d29bc4SBrooks Davis {
382*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1 = new_test_program(
383*b0d29bc4SBrooks Davis "dir/program1", "foo_test", "bar_test", "baz_test", NULL);
384*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2 = new_test_program(
385*b0d29bc4SBrooks Davis "dir/program2", "bar_test", NULL);
386*b0d29bc4SBrooks Davis const model::test_program_ptr test_program3 = new_test_program(
387*b0d29bc4SBrooks Davis "program3", "another_test", "last_test", NULL);
388*b0d29bc4SBrooks Davis const model::test_program_ptr test_program4 = new_test_program(
389*b0d29bc4SBrooks Davis "program4", "more_test", NULL);
390*b0d29bc4SBrooks Davis
391*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
392*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
393*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
394*b0d29bc4SBrooks Davis test_programs.push_back(test_program3);
395*b0d29bc4SBrooks Davis test_programs.push_back(test_program4);
396*b0d29bc4SBrooks Davis
397*b0d29bc4SBrooks Davis std::set< engine::test_filter > filters;
398*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("dir/program1"), "baz_test"));
399*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("dir/program2"), "foo_test"));
400*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("program3"), ""));
401*b0d29bc4SBrooks Davis
402*b0d29bc4SBrooks Davis std::set< engine::test_filter > exp_filters;
403*b0d29bc4SBrooks Davis exp_filters.insert(engine::test_filter(fs::path("dir/program2"),
404*b0d29bc4SBrooks Davis "foo_test"));
405*b0d29bc4SBrooks Davis
406*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
407*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "baz_test"));
408*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program3, "another_test"));
409*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program3, "last_test"));
410*b0d29bc4SBrooks Davis
411*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
412*b0d29bc4SBrooks Davis const std::set< engine::scan_result > results = yield_all(scanner);
413*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
414*b0d29bc4SBrooks Davis
415*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_filters, scanner.unused_filters());
416*b0d29bc4SBrooks Davis }
417*b0d29bc4SBrooks Davis
418*b0d29bc4SBrooks Davis
419*b0d29bc4SBrooks Davis ATF_TEST_CASE_WITHOUT_HEAD(scanner__with_filters__verify_lazy_loads);
ATF_TEST_CASE_BODY(scanner__with_filters__verify_lazy_loads)420*b0d29bc4SBrooks Davis ATF_TEST_CASE_BODY(scanner__with_filters__verify_lazy_loads)
421*b0d29bc4SBrooks Davis {
422*b0d29bc4SBrooks Davis const model::test_program_ptr test_program1(new mock_test_program(
423*b0d29bc4SBrooks Davis fs::path("first")));
424*b0d29bc4SBrooks Davis const mock_test_program* mock_program1 =
425*b0d29bc4SBrooks Davis dynamic_cast< const mock_test_program* >(test_program1.get());
426*b0d29bc4SBrooks Davis const model::test_program_ptr test_program2(new mock_test_program(
427*b0d29bc4SBrooks Davis fs::path("second")));
428*b0d29bc4SBrooks Davis const mock_test_program* mock_program2 =
429*b0d29bc4SBrooks Davis dynamic_cast< const mock_test_program* >(test_program2.get());
430*b0d29bc4SBrooks Davis
431*b0d29bc4SBrooks Davis model::test_programs_vector test_programs;
432*b0d29bc4SBrooks Davis test_programs.push_back(test_program1);
433*b0d29bc4SBrooks Davis test_programs.push_back(test_program2);
434*b0d29bc4SBrooks Davis
435*b0d29bc4SBrooks Davis std::set< engine::test_filter > filters;
436*b0d29bc4SBrooks Davis filters.insert(engine::test_filter(fs::path("first"), ""));
437*b0d29bc4SBrooks Davis
438*b0d29bc4SBrooks Davis std::set< engine::scan_result > exp_results;
439*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "one"));
440*b0d29bc4SBrooks Davis exp_results.insert(engine::scan_result(test_program1, "two"));
441*b0d29bc4SBrooks Davis
442*b0d29bc4SBrooks Davis engine::scanner scanner(test_programs, filters);
443*b0d29bc4SBrooks Davis std::set< engine::scan_result > results;
444*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program1->num_calls());
445*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
446*b0d29bc4SBrooks Davis
447*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
448*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
449*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
450*b0d29bc4SBrooks Davis results.insert(scanner.yield().get());
451*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
452*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
453*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.done());
454*b0d29bc4SBrooks Davis
455*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(exp_results, results);
456*b0d29bc4SBrooks Davis ATF_REQUIRE(scanner.unused_filters().empty());
457*b0d29bc4SBrooks Davis
458*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(1, mock_program1->num_calls());
459*b0d29bc4SBrooks Davis ATF_REQUIRE_EQ(0, mock_program2->num_calls());
460*b0d29bc4SBrooks Davis }
461*b0d29bc4SBrooks Davis
462*b0d29bc4SBrooks Davis
ATF_INIT_TEST_CASES(tcs)463*b0d29bc4SBrooks Davis ATF_INIT_TEST_CASES(tcs)
464*b0d29bc4SBrooks Davis {
465*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__no_tests);
466*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__one_test_in_one_program);
467*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__one_test_per_many_programs);
468*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__many_tests_in_one_program);
469*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__many_tests_per_many_programs);
470*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__no_filters__verify_lazy_loads);
471*b0d29bc4SBrooks Davis
472*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__with_filters__no_tests);
473*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__with_filters__no_matches);
474*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__with_filters__some_matches);
475*b0d29bc4SBrooks Davis ATF_ADD_TEST_CASE(tcs, scanner__with_filters__verify_lazy_loads);
476*b0d29bc4SBrooks Davis }
477