1// Copyright 2011 The Kyua Authors.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "engine/filters.hpp"
30
31#include <stdexcept>
32
33#include <atf-c++.hpp>
34
35namespace fs = utils::fs;
36
37
38namespace {
39
40
41/// Syntactic sugar to instantiate engine::test_filter objects.
42///
43/// \param test_program Test program.
44/// \param test_case Test case.
45///
46/// \return A \p test_filter object, based on \p test_program and \p test_case.
47inline engine::test_filter
48mkfilter(const char* test_program, const char* test_case)
49{
50    return engine::test_filter(fs::path(test_program), test_case);
51}
52
53
54}  // anonymous namespace
55
56
57ATF_TEST_CASE_WITHOUT_HEAD(test_filter__public_fields);
58ATF_TEST_CASE_BODY(test_filter__public_fields)
59{
60    const engine::test_filter filter(fs::path("foo/bar"), "baz");
61    ATF_REQUIRE_EQ(fs::path("foo/bar"), filter.test_program);
62    ATF_REQUIRE_EQ("baz", filter.test_case);
63}
64
65
66ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__ok);
67ATF_TEST_CASE_BODY(test_filter__parse__ok)
68{
69    const engine::test_filter filter(engine::test_filter::parse("foo"));
70    ATF_REQUIRE_EQ(fs::path("foo"), filter.test_program);
71    ATF_REQUIRE(filter.test_case.empty());
72}
73
74
75ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__empty);
76ATF_TEST_CASE_BODY(test_filter__parse__empty)
77{
78    ATF_REQUIRE_THROW_RE(std::runtime_error, "empty",
79                         engine::test_filter::parse(""));
80}
81
82
83ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__absolute);
84ATF_TEST_CASE_BODY(test_filter__parse__absolute)
85{
86    ATF_REQUIRE_THROW_RE(std::runtime_error, "'/foo/bar'.*relative",
87                         engine::test_filter::parse("/foo//bar"));
88}
89
90
91ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_program_name);
92ATF_TEST_CASE_BODY(test_filter__parse__bad_program_name)
93{
94    ATF_REQUIRE_THROW_RE(std::runtime_error, "Program name.*':foo'",
95                         engine::test_filter::parse(":foo"));
96}
97
98
99ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_test_case);
100ATF_TEST_CASE_BODY(test_filter__parse__bad_test_case)
101{
102    ATF_REQUIRE_THROW_RE(std::runtime_error, "Test case.*'bar/baz:'",
103                         engine::test_filter::parse("bar/baz:"));
104}
105
106
107ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_path);
108ATF_TEST_CASE_BODY(test_filter__parse__bad_path)
109{
110    // TODO(jmmv): Not implemented.  At the moment, the only reason for a path
111    // to be invalid is if it is empty... but we are checking this exact
112    // condition ourselves as part of the input validation.  So we can't mock in
113    // an argument with an invalid non-empty path...
114}
115
116
117ATF_TEST_CASE_WITHOUT_HEAD(test_filter__str);
118ATF_TEST_CASE_BODY(test_filter__str)
119{
120    const engine::test_filter filter(fs::path("foo/bar"), "baz");
121    ATF_REQUIRE_EQ("foo/bar:baz", filter.str());
122}
123
124
125ATF_TEST_CASE_WITHOUT_HEAD(test_filter__contains__same);
126ATF_TEST_CASE_BODY(test_filter__contains__same)
127{
128    {
129        const engine::test_filter f(fs::path("foo/bar"), "baz");
130        ATF_REQUIRE(f.contains(f));
131    }
132    {
133        const engine::test_filter f(fs::path("foo/bar"), "");
134        ATF_REQUIRE(f.contains(f));
135    }
136    {
137        const engine::test_filter f(fs::path("foo"), "");
138        ATF_REQUIRE(f.contains(f));
139    }
140}
141
142
143ATF_TEST_CASE_WITHOUT_HEAD(test_filter__contains__different);
144ATF_TEST_CASE_BODY(test_filter__contains__different)
145{
146    {
147        const engine::test_filter f1(fs::path("foo"), "");
148        const engine::test_filter f2(fs::path("foo"), "bar");
149        ATF_REQUIRE( f1.contains(f2));
150        ATF_REQUIRE(!f2.contains(f1));
151    }
152    {
153        const engine::test_filter f1(fs::path("foo/bar"), "");
154        const engine::test_filter f2(fs::path("foo/bar"), "baz");
155        ATF_REQUIRE( f1.contains(f2));
156        ATF_REQUIRE(!f2.contains(f1));
157    }
158    {
159        const engine::test_filter f1(fs::path("foo/bar"), "");
160        const engine::test_filter f2(fs::path("foo/baz"), "");
161        ATF_REQUIRE(!f1.contains(f2));
162        ATF_REQUIRE(!f2.contains(f1));
163    }
164    {
165        const engine::test_filter f1(fs::path("foo"), "");
166        const engine::test_filter f2(fs::path("foo/bar"), "");
167        ATF_REQUIRE( f1.contains(f2));
168        ATF_REQUIRE(!f2.contains(f1));
169    }
170    {
171        const engine::test_filter f1(fs::path("foo"), "bar");
172        const engine::test_filter f2(fs::path("foo/bar"), "");
173        ATF_REQUIRE(!f1.contains(f2));
174        ATF_REQUIRE(!f2.contains(f1));
175    }
176}
177
178
179ATF_TEST_CASE_WITHOUT_HEAD(test_filter__matches_test_program)
180ATF_TEST_CASE_BODY(test_filter__matches_test_program)
181{
182    {
183        const engine::test_filter f(fs::path("top"), "unused");
184        ATF_REQUIRE( f.matches_test_program(fs::path("top")));
185        ATF_REQUIRE(!f.matches_test_program(fs::path("top2")));
186    }
187
188    {
189        const engine::test_filter f(fs::path("dir1/dir2"), "");
190        ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/foo")));
191        ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar")));
192        ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar/baz")));
193        ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar/baz")));
194        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1")));
195        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/bar/baz")));
196        ATF_REQUIRE(!f.matches_test_program(fs::path("dir2/bar/baz")));
197    }
198
199    {
200        const engine::test_filter f(fs::path("dir1/dir2"), "unused");
201        ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2")));
202        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/foo")));
203        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar")));
204        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar/baz")));
205        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar/baz")));
206        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1")));
207        ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/bar/baz")));
208        ATF_REQUIRE(!f.matches_test_program(fs::path("dir2/bar/baz")));
209    }
210}
211
212
213ATF_TEST_CASE_WITHOUT_HEAD(test_filter__matches_test_case)
214ATF_TEST_CASE_BODY(test_filter__matches_test_case)
215{
216    {
217        const engine::test_filter f(fs::path("top"), "foo");
218        ATF_REQUIRE( f.matches_test_case(fs::path("top"), "foo"));
219        ATF_REQUIRE(!f.matches_test_case(fs::path("top"), "bar"));
220    }
221
222    {
223        const engine::test_filter f(fs::path("top"), "");
224        ATF_REQUIRE( f.matches_test_case(fs::path("top"), "foo"));
225        ATF_REQUIRE( f.matches_test_case(fs::path("top"), "bar"));
226        ATF_REQUIRE(!f.matches_test_case(fs::path("top2"), "foo"));
227    }
228
229    {
230        const engine::test_filter f(fs::path("d1/d2/prog"), "t1");
231        ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t1"));
232        ATF_REQUIRE(!f.matches_test_case(fs::path("d1/d2/prog"), "t2"));
233    }
234
235    {
236        const engine::test_filter f(fs::path("d1/d2"), "");
237        ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t1"));
238        ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t2"));
239        ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog2"), "t2"));
240        ATF_REQUIRE(!f.matches_test_case(fs::path("d1/d3"), "foo"));
241        ATF_REQUIRE(!f.matches_test_case(fs::path("d2"), "foo"));
242    }
243}
244
245
246ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_lt)
247ATF_TEST_CASE_BODY(test_filter__operator_lt)
248{
249    {
250        const engine::test_filter f1(fs::path("d1/d2"), "");
251        ATF_REQUIRE(!(f1 < f1));
252    }
253    {
254        const engine::test_filter f1(fs::path("d1/d2"), "");
255        const engine::test_filter f2(fs::path("d1/d3"), "");
256        ATF_REQUIRE( (f1 < f2));
257        ATF_REQUIRE(!(f2 < f1));
258    }
259    {
260        const engine::test_filter f1(fs::path("d1/d2"), "");
261        const engine::test_filter f2(fs::path("d1/d2"), "foo");
262        ATF_REQUIRE( (f1 < f2));
263        ATF_REQUIRE(!(f2 < f1));
264    }
265    {
266        const engine::test_filter f1(fs::path("d1/d2"), "bar");
267        const engine::test_filter f2(fs::path("d1/d2"), "foo");
268        ATF_REQUIRE( (f1 < f2));
269        ATF_REQUIRE(!(f2 < f1));
270    }
271    {
272        const engine::test_filter f1(fs::path("d1/d2"), "bar");
273        const engine::test_filter f2(fs::path("d1/d3"), "");
274        ATF_REQUIRE( (f1 < f2));
275        ATF_REQUIRE(!(f2 < f1));
276    }
277}
278
279
280ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_eq)
281ATF_TEST_CASE_BODY(test_filter__operator_eq)
282{
283    const engine::test_filter f1(fs::path("d1/d2"), "");
284    const engine::test_filter f2(fs::path("d1/d2"), "bar");
285    ATF_REQUIRE( (f1 == f1));
286    ATF_REQUIRE(!(f1 == f2));
287    ATF_REQUIRE(!(f2 == f1));
288    ATF_REQUIRE( (f2 == f2));
289}
290
291
292ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_ne)
293ATF_TEST_CASE_BODY(test_filter__operator_ne)
294{
295    const engine::test_filter f1(fs::path("d1/d2"), "");
296    const engine::test_filter f2(fs::path("d1/d2"), "bar");
297    ATF_REQUIRE(!(f1 != f1));
298    ATF_REQUIRE( (f1 != f2));
299    ATF_REQUIRE( (f2 != f1));
300    ATF_REQUIRE(!(f2 != f2));
301}
302
303
304ATF_TEST_CASE_WITHOUT_HEAD(test_filter__output);
305ATF_TEST_CASE_BODY(test_filter__output)
306{
307    {
308        std::ostringstream str;
309        str << engine::test_filter(fs::path("d1/d2"), "");
310        ATF_REQUIRE_EQ(
311            "test_filter{test_program=d1/d2}",
312            str.str());
313    }
314    {
315        std::ostringstream str;
316        str << engine::test_filter(fs::path("d1/d2"), "bar");
317        ATF_REQUIRE_EQ(
318            "test_filter{test_program=d1/d2, test_case=bar}",
319            str.str());
320    }
321}
322
323
324ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_case__no_filters)
325ATF_TEST_CASE_BODY(test_filters__match_test_case__no_filters)
326{
327    const std::set< engine::test_filter > raw_filters;
328
329    const engine::test_filters filters(raw_filters);
330    engine::test_filters::match match;
331
332    match = filters.match_test_case(fs::path("foo"), "baz");
333    ATF_REQUIRE(match.first);
334    ATF_REQUIRE(!match.second);
335
336    match = filters.match_test_case(fs::path("foo/bar"), "baz");
337    ATF_REQUIRE(match.first);
338    ATF_REQUIRE(!match.second);
339}
340
341
342ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_case__some_filters)
343ATF_TEST_CASE_BODY(test_filters__match_test_case__some_filters)
344{
345    std::set< engine::test_filter > raw_filters;
346    raw_filters.insert(mkfilter("top_test", ""));
347    raw_filters.insert(mkfilter("subdir_1", ""));
348    raw_filters.insert(mkfilter("subdir_2/a_test", ""));
349    raw_filters.insert(mkfilter("subdir_2/b_test", "foo"));
350
351    const engine::test_filters filters(raw_filters);
352    engine::test_filters::match match;
353
354    match = filters.match_test_case(fs::path("top_test"), "a");
355    ATF_REQUIRE(match.first);
356    ATF_REQUIRE_EQ("top_test", match.second.get().str());
357
358    match = filters.match_test_case(fs::path("subdir_1/foo"), "a");
359    ATF_REQUIRE(match.first);
360    ATF_REQUIRE_EQ("subdir_1", match.second.get().str());
361
362    match = filters.match_test_case(fs::path("subdir_1/bar"), "z");
363    ATF_REQUIRE(match.first);
364    ATF_REQUIRE_EQ("subdir_1", match.second.get().str());
365
366    match = filters.match_test_case(fs::path("subdir_2/a_test"), "bar");
367    ATF_REQUIRE(match.first);
368    ATF_REQUIRE_EQ("subdir_2/a_test", match.second.get().str());
369
370    match = filters.match_test_case(fs::path("subdir_2/b_test"), "foo");
371    ATF_REQUIRE(match.first);
372    ATF_REQUIRE_EQ("subdir_2/b_test:foo", match.second.get().str());
373
374    match = filters.match_test_case(fs::path("subdir_2/b_test"), "bar");
375    ATF_REQUIRE(!match.first);
376
377    match = filters.match_test_case(fs::path("subdir_2/c_test"), "foo");
378    ATF_REQUIRE(!match.first);
379
380    match = filters.match_test_case(fs::path("subdir_3"), "hello");
381    ATF_REQUIRE(!match.first);
382}
383
384
385ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_program__no_filters)
386ATF_TEST_CASE_BODY(test_filters__match_test_program__no_filters)
387{
388    const std::set< engine::test_filter > raw_filters;
389
390    const engine::test_filters filters(raw_filters);
391    ATF_REQUIRE(filters.match_test_program(fs::path("foo")));
392    ATF_REQUIRE(filters.match_test_program(fs::path("foo/bar")));
393}
394
395
396ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_program__some_filters)
397ATF_TEST_CASE_BODY(test_filters__match_test_program__some_filters)
398{
399    std::set< engine::test_filter > raw_filters;
400    raw_filters.insert(mkfilter("top_test", ""));
401    raw_filters.insert(mkfilter("subdir_1", ""));
402    raw_filters.insert(mkfilter("subdir_2/a_test", ""));
403    raw_filters.insert(mkfilter("subdir_2/b_test", "foo"));
404
405    const engine::test_filters filters(raw_filters);
406    ATF_REQUIRE( filters.match_test_program(fs::path("top_test")));
407    ATF_REQUIRE( filters.match_test_program(fs::path("subdir_1/foo")));
408    ATF_REQUIRE( filters.match_test_program(fs::path("subdir_1/bar")));
409    ATF_REQUIRE( filters.match_test_program(fs::path("subdir_2/a_test")));
410    ATF_REQUIRE( filters.match_test_program(fs::path("subdir_2/b_test")));
411    ATF_REQUIRE(!filters.match_test_program(fs::path("subdir_2/c_test")));
412    ATF_REQUIRE(!filters.match_test_program(fs::path("subdir_3")));
413}
414
415
416ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__no_filters);
417ATF_TEST_CASE_BODY(test_filters__difference__no_filters)
418{
419    const std::set< engine::test_filter > in_filters;
420    const std::set< engine::test_filter > used;
421    const std::set< engine::test_filter > diff = engine::test_filters(
422        in_filters).difference(used);
423    ATF_REQUIRE(diff.empty());
424}
425
426
427ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__some_filters__all_used);
428ATF_TEST_CASE_BODY(test_filters__difference__some_filters__all_used)
429{
430    std::set< engine::test_filter > in_filters;
431    in_filters.insert(mkfilter("a", ""));
432    in_filters.insert(mkfilter("b", "c"));
433
434    const std::set< engine::test_filter > used = in_filters;
435
436    const std::set< engine::test_filter > diff = engine::test_filters(
437        in_filters).difference(used);
438    ATF_REQUIRE(diff.empty());
439}
440
441
442ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__some_filters__some_unused);
443ATF_TEST_CASE_BODY(test_filters__difference__some_filters__some_unused)
444{
445    std::set< engine::test_filter > in_filters;
446    in_filters.insert(mkfilter("a", ""));
447    in_filters.insert(mkfilter("b", "c"));
448    in_filters.insert(mkfilter("d", ""));
449    in_filters.insert(mkfilter("e", "f"));
450
451    std::set< engine::test_filter > used;
452    used.insert(mkfilter("b", "c"));
453    used.insert(mkfilter("d", ""));
454
455    const std::set< engine::test_filter > diff = engine::test_filters(
456        in_filters).difference(used);
457    ATF_REQUIRE_EQ(2, diff.size());
458    ATF_REQUIRE(diff.find(mkfilter("a", "")) != diff.end());
459    ATF_REQUIRE(diff.find(mkfilter("e", "f")) != diff.end());
460}
461
462
463ATF_TEST_CASE_WITHOUT_HEAD(check_disjoint_filters__ok);
464ATF_TEST_CASE_BODY(check_disjoint_filters__ok)
465{
466    std::set< engine::test_filter > filters;
467    filters.insert(mkfilter("a", ""));
468    filters.insert(mkfilter("b", ""));
469    filters.insert(mkfilter("c", "a"));
470    filters.insert(mkfilter("c", "b"));
471
472    engine::check_disjoint_filters(filters);
473}
474
475
476ATF_TEST_CASE_WITHOUT_HEAD(check_disjoint_filters__fail);
477ATF_TEST_CASE_BODY(check_disjoint_filters__fail)
478{
479    std::set< engine::test_filter > filters;
480    filters.insert(mkfilter("a", ""));
481    filters.insert(mkfilter("b", ""));
482    filters.insert(mkfilter("c", "a"));
483    filters.insert(mkfilter("d", "b"));
484    filters.insert(mkfilter("c", ""));
485
486    ATF_REQUIRE_THROW_RE(std::runtime_error, "'c'.*'c:a'.*not disjoint",
487                         engine::check_disjoint_filters(filters));
488}
489
490
491ATF_TEST_CASE_WITHOUT_HEAD(filters_state__match_test_program);
492ATF_TEST_CASE_BODY(filters_state__match_test_program)
493{
494    std::set< engine::test_filter > filters;
495    filters.insert(mkfilter("foo/bar", ""));
496    filters.insert(mkfilter("baz", "tc"));
497    engine::filters_state state(filters);
498
499    ATF_REQUIRE(state.match_test_program(fs::path("foo/bar/something")));
500    ATF_REQUIRE(state.match_test_program(fs::path("baz")));
501
502    ATF_REQUIRE(!state.match_test_program(fs::path("foo/baz")));
503    ATF_REQUIRE(!state.match_test_program(fs::path("hello")));
504}
505
506
507ATF_TEST_CASE_WITHOUT_HEAD(filters_state__match_test_case);
508ATF_TEST_CASE_BODY(filters_state__match_test_case)
509{
510    std::set< engine::test_filter > filters;
511    filters.insert(mkfilter("foo/bar", ""));
512    filters.insert(mkfilter("baz", "tc"));
513    engine::filters_state state(filters);
514
515    ATF_REQUIRE(state.match_test_case(fs::path("foo/bar/something"), "any"));
516    ATF_REQUIRE(state.match_test_case(fs::path("baz"), "tc"));
517
518    ATF_REQUIRE(!state.match_test_case(fs::path("foo/baz/something"), "tc"));
519    ATF_REQUIRE(!state.match_test_case(fs::path("baz"), "tc2"));
520}
521
522
523ATF_TEST_CASE_WITHOUT_HEAD(filters_state__unused__none);
524ATF_TEST_CASE_BODY(filters_state__unused__none)
525{
526    std::set< engine::test_filter > filters;
527    filters.insert(mkfilter("a/b", ""));
528    filters.insert(mkfilter("baz", "tc"));
529    filters.insert(mkfilter("hey/d", "yes"));
530    engine::filters_state state(filters);
531
532    state.match_test_case(fs::path("a/b/c"), "any");
533    state.match_test_case(fs::path("baz"), "tc");
534    state.match_test_case(fs::path("hey/d"), "yes");
535
536    ATF_REQUIRE(state.unused().empty());
537}
538
539
540ATF_TEST_CASE_WITHOUT_HEAD(filters_state__unused__some);
541ATF_TEST_CASE_BODY(filters_state__unused__some)
542{
543    std::set< engine::test_filter > filters;
544    filters.insert(mkfilter("a/b", ""));
545    filters.insert(mkfilter("baz", "tc"));
546    filters.insert(mkfilter("hey/d", "yes"));
547    engine::filters_state state(filters);
548
549    state.match_test_program(fs::path("a/b/c"));
550    state.match_test_case(fs::path("baz"), "tc");
551
552    std::set< engine::test_filter > exp_unused;
553    exp_unused.insert(mkfilter("a/b", ""));
554    exp_unused.insert(mkfilter("hey/d", "yes"));
555
556    ATF_REQUIRE(exp_unused == state.unused());
557}
558
559
560ATF_INIT_TEST_CASES(tcs)
561{
562    ATF_ADD_TEST_CASE(tcs, test_filter__public_fields);
563    ATF_ADD_TEST_CASE(tcs, test_filter__parse__ok);
564    ATF_ADD_TEST_CASE(tcs, test_filter__parse__empty);
565    ATF_ADD_TEST_CASE(tcs, test_filter__parse__absolute);
566    ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_program_name);
567    ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_test_case);
568    ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_path);
569    ATF_ADD_TEST_CASE(tcs, test_filter__str);
570    ATF_ADD_TEST_CASE(tcs, test_filter__contains__same);
571    ATF_ADD_TEST_CASE(tcs, test_filter__contains__different);
572    ATF_ADD_TEST_CASE(tcs, test_filter__matches_test_program);
573    ATF_ADD_TEST_CASE(tcs, test_filter__matches_test_case);
574    ATF_ADD_TEST_CASE(tcs, test_filter__operator_lt);
575    ATF_ADD_TEST_CASE(tcs, test_filter__operator_eq);
576    ATF_ADD_TEST_CASE(tcs, test_filter__operator_ne);
577    ATF_ADD_TEST_CASE(tcs, test_filter__output);
578
579    ATF_ADD_TEST_CASE(tcs, test_filters__match_test_case__no_filters);
580    ATF_ADD_TEST_CASE(tcs, test_filters__match_test_case__some_filters);
581    ATF_ADD_TEST_CASE(tcs, test_filters__match_test_program__no_filters);
582    ATF_ADD_TEST_CASE(tcs, test_filters__match_test_program__some_filters);
583    ATF_ADD_TEST_CASE(tcs, test_filters__difference__no_filters);
584    ATF_ADD_TEST_CASE(tcs, test_filters__difference__some_filters__all_used);
585    ATF_ADD_TEST_CASE(tcs, test_filters__difference__some_filters__some_unused);
586
587    ATF_ADD_TEST_CASE(tcs, check_disjoint_filters__ok);
588    ATF_ADD_TEST_CASE(tcs, check_disjoint_filters__fail);
589
590    ATF_ADD_TEST_CASE(tcs, filters_state__match_test_program);
591    ATF_ADD_TEST_CASE(tcs, filters_state__match_test_case);
592    ATF_ADD_TEST_CASE(tcs, filters_state__unused__none);
593    ATF_ADD_TEST_CASE(tcs, filters_state__unused__some);
594}
595