monotone

monotone Mtn Source Tree

Root/restrictions.cc

1// Copyright (C) 2005 Derek Scherger <derek@echologic.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include <map>
11#include <string>
12#include <vector>
13
14#include "restrictions.hh"
15#include "revision.hh"
16#include "safe_map.hh"
17#include "transforms.hh"
18
19using std::make_pair;
20using std::map;
21using std::set;
22using std::vector;
23
24// TODO: add check for relevant rosters to be used by log
25//
26// i.e. as log goes back through older and older rosters it may hit one
27// that pre-dates any of the nodes in the restriction. the nodes that the
28// restriction includes or excludes may not have been born in a sufficiently
29// old roster. at this point log should stop because no earlier roster will
30// include these nodes.
31
32static void
33make_path_set(vector<file_path> const & paths, path_set & split_paths)
34{
35 for (vector<file_path>::const_iterator i = paths.begin(); i != paths.end(); ++i)
36 {
37 split_path sp;
38 i->split(sp);
39 split_paths.insert(sp);
40 }
41}
42
43static void
44map_nodes(map<node_id, restricted_path::status> & node_map,
45 roster_t const & roster,
46 path_set const & paths,
47 path_set & known_paths,
48 restricted_path::status const status)
49{
50 for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
51 {
52 if (roster.has_node(*i))
53 {
54 known_paths.insert(*i);
55 node_id nid = roster.get_node(*i)->self;
56
57 map<node_id, restricted_path::status>::iterator n = node_map.find(nid);
58 if (n != node_map.end())
59 N(n->second == status,
60 F("conflicting include/exclude on path '%s'") % *i);
61 else
62 node_map.insert(make_pair(nid, status));
63 }
64 }
65}
66
67static void
68map_paths(map<split_path, restricted_path::status> & path_map,
69 path_set const & paths,
70 restricted_path::status const status)
71{
72 for (path_set::const_iterator i = paths.begin(); i != paths.end(); ++i)
73 {
74 map<split_path, restricted_path::status>::iterator p = path_map.find(*i);
75 if (p != path_map.end())
76 N(p->second == status,
77 F("conflicting include/exclude on path '%s'") % *i);
78 else
79 path_map.insert(make_pair(*i, status));
80 }
81}
82
83static void
84validate_roster_paths(path_set const & included_paths,
85 path_set const & excluded_paths,
86 path_set const & known_paths,
87 app_state & app)
88{
89 int bad = 0;
90
91 for (path_set::const_iterator i = included_paths.begin();
92 i != included_paths.end(); ++i)
93 {
94 // ignored paths are allowed into the restriction but are not
95 // considered invalid if they are found in none of the restriction's
96 // rosters
97 if (known_paths.find(*i) == known_paths.end())
98 {
99 file_path fp(*i);
100 if (!app.lua.hook_ignore_file(fp))
101 {
102 bad++;
103 W(F("restriction includes unknown path '%s'") % *i);
104 }
105 }
106 }
107
108 for (path_set::const_iterator i = excluded_paths.begin();
109 i != excluded_paths.end(); ++i)
110 {
111 if (known_paths.find(*i) == known_paths.end())
112 {
113 bad++;
114 W(F("restriction excludes unknown path '%s'") % *i);
115 }
116 }
117
118 N(bad == 0, F("%d unknown paths") % bad);
119}
120
121void
122validate_workspace_paths(path_set const & included_paths,
123 path_set const & excluded_paths,
124 app_state & app)
125{
126 int bad = 0;
127
128 for (path_set::const_iterator i = included_paths.begin();
129 i != included_paths.end(); ++i)
130 {
131 if (workspace_root(*i))
132 continue;
133
134 // ignored paths are allowed into the restriction but are not
135 // considered invalid if they are found in none of the restriction's
136 // rosters
137 file_path fp(*i);
138 if (!path_exists(fp) && !app.lua.hook_ignore_file(fp))
139 {
140 bad++;
141 W(F("restriction includes unknown path '%s'") % *i);
142 }
143 }
144
145 for (path_set::const_iterator i = excluded_paths.begin();
146 i != excluded_paths.end(); ++i)
147 {
148 if (workspace_root(*i))
149 continue;
150
151 file_path fp(*i);
152 if (!path_exists(fp))
153 {
154 bad++;
155 W(F("restriction excludes unknown path '%s'") % *i);
156 }
157 }
158
159 N(bad == 0, F("%d unknown paths") % bad);
160}
161
162restriction::restriction(std::vector<file_path> const & includes,
163 std::vector<file_path> const & excludes,
164 app_state & a) :
165 app(a)
166{
167 make_path_set(includes, included_paths);
168 make_path_set(excludes, excluded_paths);
169}
170
171node_restriction::node_restriction(std::vector<file_path> const & includes,
172 std::vector<file_path> const & excludes,
173 roster_t const & roster,
174 app_state & a) :
175 restriction(includes, excludes, a)
176{
177 map_nodes(node_map, roster, included_paths, known_paths,
178 restricted_path::included);
179 map_nodes(node_map, roster, excluded_paths, known_paths,
180 restricted_path::excluded);
181
182 validate_roster_paths(included_paths, excluded_paths, known_paths, app);
183}
184
185node_restriction::node_restriction(std::vector<file_path> const & includes,
186 std::vector<file_path> const & excludes,
187 roster_t const & roster1,
188 roster_t const & roster2,
189 app_state & a) :
190 restriction(includes, excludes, a)
191{
192 map_nodes(node_map, roster1, included_paths, known_paths,
193 restricted_path::included);
194 map_nodes(node_map, roster1, excluded_paths, known_paths,
195 restricted_path::excluded);
196
197 map_nodes(node_map, roster2, included_paths, known_paths,
198 restricted_path::included);
199 map_nodes(node_map, roster2, excluded_paths, known_paths,
200 restricted_path::excluded);
201
202 validate_roster_paths(included_paths, excluded_paths, known_paths, app);
203}
204
205path_restriction::path_restriction(std::vector<file_path> const & includes,
206 std::vector<file_path> const & excludes,
207 app_state & a) :
208 restriction(includes, excludes, a)
209{
210 map_paths(path_map, included_paths, restricted_path::included);
211 map_paths(path_map, excluded_paths, restricted_path::excluded);
212
213 validate_workspace_paths(included_paths, excluded_paths, app);
214}
215
216bool
217node_restriction::includes(roster_t const & roster, node_id nid) const
218{
219 MM(roster);
220 I(roster.has_node(nid));
221
222 split_path sp;
223 roster.get_name(nid, sp);
224
225 if (empty())
226 {
227 if (app.depth != -1)
228 {
229 int depth = sp.size() - 1; // -1 to not count root path_component
230 if (depth <= app.depth + 1)
231 {
232 L(FL("depth includes nid %d path '%s'") % nid % file_path(sp));
233 return true;
234 }
235 else
236 {
237 L(FL("depth excludes nid %d path '%s'") % nid % file_path(sp));
238 return false;
239 }
240 }
241 else
242 {
243 L(FL("empty include of nid %d path '%s'") % nid % file_path(sp));
244 return true;
245 }
246 }
247
248 node_id current = nid;
249 int depth = 0;
250
251 // FIXME: this uses app.depth+1 because the old semantics of depth=0 were
252 // something like "the current directory and its immediate children". it
253 // seems somewhat more reasonable here to use depth=0 to mean "exactly
254 // this directory" and depth=1 to mean "this directory and its immediate
255 // children"
256
257 while (!null_node(current) && (app.depth == -1 || depth <= app.depth + 1))
258 {
259 map<node_id, restricted_path::status>::const_iterator
260 r = node_map.find(current);
261
262 if (r != node_map.end())
263 {
264 switch (r->second)
265 {
266 case restricted_path::included:
267 L(FL("explicit include of nid %d path '%s'")
268 % current % file_path(sp));
269 return true;
270
271 case restricted_path::excluded:
272 L(FL("explicit exclude of nid %d path '%s'")
273 % current % file_path(sp));
274 return false;
275 }
276 }
277
278 node_t node = roster.get_node(current);
279 current = node->parent;
280 depth++;
281 }
282
283 if (included_paths.empty())
284 {
285 L(FL("default include of nid %d path '%s'")
286 % nid % file_path(sp));
287 return true;
288 }
289 else
290 {
291 L(FL("default exclude of nid %d path '%s'")
292 % nid % file_path(sp));
293 return false;
294 }
295}
296
297bool
298path_restriction::includes(split_path const & sp) const
299{
300 if (empty())
301 {
302 if (app.depth != -1)
303 {
304 int depth = sp.size() - 1; // -1 to not count root path_component
305 if (depth <= app.depth + 1)
306 {
307 L(FL("depth includes path '%s'") % file_path(sp));
308 return true;
309 }
310 else
311 {
312 L(FL("depth excludes path '%s'") % file_path(sp));
313 return false;
314 }
315 }
316 else
317 {
318 L(FL("empty include of path '%s'") % file_path(sp));
319 return true;
320 }
321 }
322
323 split_path current(sp);
324 int depth = 0;
325
326 // FIXME: this uses app.depth+1 because the old semantics of depth=0 were
327 // something like "the current directory and its immediate children". it
328 // seems somewhat more reasonable here to use depth=0 to mean "exactly
329 // this directory" and depth=1 to mean "this directory and its immediate
330 // children"
331
332 while (!current.empty() && (app.depth == -1 || depth <= app.depth + 1))
333 {
334 map<split_path, restricted_path::status>::const_iterator
335 r = path_map.find(current);
336
337 if (r != path_map.end())
338 {
339 switch (r->second)
340 {
341 case restricted_path::included:
342 L(FL("explicit include of path '%s'")
343 % file_path(sp));
344 return true;
345
346 case restricted_path::excluded:
347 L(FL("explicit exclude of path '%s'")
348 % file_path(sp));
349 return false;
350 }
351 }
352
353 current.pop_back();
354 depth++;
355 }
356
357 if (included_paths.empty())
358 {
359 L(FL("default include of path '%s'")
360 % file_path(sp));
361 return true;
362 }
363 else
364 {
365 L(FL("default exclude of path '%s'")
366 % file_path(sp));
367 return false;
368 }
369}
370
371///////////////////////////////////////////////////////////////////////
372// tests
373///////////////////////////////////////////////////////////////////////
374
375#ifdef BUILD_UNIT_TESTS
376#include "app_state.hh"
377#include "unit_tests.hh"
378#include "roster.hh"
379#include "sanity.hh"
380
381using std::string;
382
383// f's and g's are files
384// x's and y's are directories
385// and this is rather painful
386
387split_path sp_root;
388split_path sp_f;
389split_path sp_g;
390
391split_path sp_x;
392split_path sp_xf;
393split_path sp_xg;
394split_path sp_xx;
395split_path sp_xxf;
396split_path sp_xxg;
397split_path sp_xy;
398split_path sp_xyf;
399split_path sp_xyg;
400
401split_path sp_y;
402split_path sp_yf;
403split_path sp_yg;
404split_path sp_yx;
405split_path sp_yxf;
406split_path sp_yxg;
407split_path sp_yy;
408split_path sp_yyf;
409split_path sp_yyg;
410
411node_id nid_root;
412node_id nid_f;
413node_id nid_g;
414
415node_id nid_x;
416node_id nid_xf;
417node_id nid_xg;
418node_id nid_xx;
419node_id nid_xxf;
420node_id nid_xxg;
421node_id nid_xy;
422node_id nid_xyf;
423node_id nid_xyg;
424
425node_id nid_y;
426node_id nid_yf;
427node_id nid_yg;
428node_id nid_yx;
429node_id nid_yxf;
430node_id nid_yxg;
431node_id nid_yy;
432node_id nid_yyf;
433node_id nid_yyg;
434
435file_id fid_f(string("1000000000000000000000000000000000000000"));
436file_id fid_g(string("2000000000000000000000000000000000000000"));
437
438file_id fid_xf(string("3000000000000000000000000000000000000000"));
439file_id fid_xg(string("4000000000000000000000000000000000000000"));
440file_id fid_xxf(string("5000000000000000000000000000000000000000"));
441file_id fid_xxg(string("6000000000000000000000000000000000000000"));
442file_id fid_xyf(string("7000000000000000000000000000000000000000"));
443file_id fid_xyg(string("8000000000000000000000000000000000000000"));
444
445file_id fid_yf(string("9000000000000000000000000000000000000000"));
446file_id fid_yg(string("a000000000000000000000000000000000000000"));
447file_id fid_yxf(string("b000000000000000000000000000000000000000"));
448file_id fid_yxg(string("c000000000000000000000000000000000000000"));
449file_id fid_yyf(string("d000000000000000000000000000000000000000"));
450file_id fid_yyg(string("e000000000000000000000000000000000000000"));
451
452static void setup(roster_t & roster)
453{
454 temp_node_id_source nis;
455
456 file_path_internal("").split(sp_root);
457 file_path_internal("f").split(sp_f);
458 file_path_internal("g").split(sp_g);
459
460 file_path_internal("x").split(sp_x);
461 file_path_internal("x/f").split(sp_xf);
462 file_path_internal("x/g").split(sp_xg);
463 file_path_internal("x/x").split(sp_xx);
464 file_path_internal("x/x/f").split(sp_xxf);
465 file_path_internal("x/x/g").split(sp_xxg);
466 file_path_internal("x/y").split(sp_xy);
467 file_path_internal("x/y/f").split(sp_xyf);
468 file_path_internal("x/y/g").split(sp_xyg);
469
470 file_path_internal("y").split(sp_y);
471 file_path_internal("y/f").split(sp_yf);
472 file_path_internal("y/g").split(sp_yg);
473 file_path_internal("y/x").split(sp_yx);
474 file_path_internal("y/x/f").split(sp_yxf);
475 file_path_internal("y/x/g").split(sp_yxg);
476 file_path_internal("y/y").split(sp_yy);
477 file_path_internal("y/y/f").split(sp_yyf);
478 file_path_internal("y/y/g").split(sp_yyg);
479
480 // these directories must exist for the path_restrictions to be valid. it
481 // is a bit lame to be creating directories arbitrarily like this. perhaps
482 // unit_tests should run in a unit_tests.dir or something.
483
484 mkdir_p(file_path_internal("x/x"));
485 mkdir_p(file_path_internal("x/y"));
486 mkdir_p(file_path_internal("y/x"));
487 mkdir_p(file_path_internal("y/y"));
488
489 nid_root = roster.create_dir_node(nis);
490 nid_f = roster.create_file_node(fid_f, nis);
491 nid_g = roster.create_file_node(fid_g, nis);
492
493 nid_x = roster.create_dir_node(nis);
494 nid_xf = roster.create_file_node(fid_xf, nis);
495 nid_xg = roster.create_file_node(fid_xg, nis);
496 nid_xx = roster.create_dir_node(nis);
497 nid_xxf = roster.create_file_node(fid_xxf, nis);
498 nid_xxg = roster.create_file_node(fid_xxg, nis);
499 nid_xy = roster.create_dir_node(nis);
500 nid_xyf = roster.create_file_node(fid_xxf, nis);
501 nid_xyg = roster.create_file_node(fid_xxg, nis);
502
503 nid_y = roster.create_dir_node(nis);
504 nid_yf = roster.create_file_node(fid_yf, nis);
505 nid_yg = roster.create_file_node(fid_yg, nis);
506 nid_yx = roster.create_dir_node(nis);
507 nid_yxf = roster.create_file_node(fid_yxf, nis);
508 nid_yxg = roster.create_file_node(fid_yxg, nis);
509 nid_yy = roster.create_dir_node(nis);
510 nid_yyf = roster.create_file_node(fid_yxf, nis);
511 nid_yyg = roster.create_file_node(fid_yxg, nis);
512
513 roster.attach_node(nid_root, sp_root);
514 roster.attach_node(nid_f, sp_f);
515 roster.attach_node(nid_g, sp_g);
516
517 roster.attach_node(nid_x, sp_x);
518 roster.attach_node(nid_xf, sp_xf);
519 roster.attach_node(nid_xg, sp_xg);
520 roster.attach_node(nid_xx, sp_xx);
521 roster.attach_node(nid_xxf, sp_xxf);
522 roster.attach_node(nid_xxg, sp_xxg);
523 roster.attach_node(nid_xy, sp_xy);
524 roster.attach_node(nid_xyf, sp_xyf);
525 roster.attach_node(nid_xyg, sp_xyg);
526
527 roster.attach_node(nid_y, sp_y);
528 roster.attach_node(nid_yf, sp_yf);
529 roster.attach_node(nid_yg, sp_yg);
530 roster.attach_node(nid_yx, sp_yx);
531 roster.attach_node(nid_yxf, sp_yxf);
532 roster.attach_node(nid_yxg, sp_yxg);
533 roster.attach_node(nid_yy, sp_yy);
534 roster.attach_node(nid_yyf, sp_yyf);
535 roster.attach_node(nid_yyg, sp_yyg);
536
537}
538
539static void
540test_empty_restriction()
541{
542 roster_t roster;
543 setup(roster);
544
545 app_state app;
546
547 // check restricted nodes
548
549 node_restriction nmask(app);
550
551 BOOST_CHECK(nmask.empty());
552
553 BOOST_CHECK(nmask.includes(roster, nid_root));
554 BOOST_CHECK(nmask.includes(roster, nid_f));
555 BOOST_CHECK(nmask.includes(roster, nid_g));
556
557 BOOST_CHECK(nmask.includes(roster, nid_x));
558 BOOST_CHECK(nmask.includes(roster, nid_xf));
559 BOOST_CHECK(nmask.includes(roster, nid_xg));
560 BOOST_CHECK(nmask.includes(roster, nid_xx));
561 BOOST_CHECK(nmask.includes(roster, nid_xxf));
562 BOOST_CHECK(nmask.includes(roster, nid_xxg));
563 BOOST_CHECK(nmask.includes(roster, nid_xy));
564 BOOST_CHECK(nmask.includes(roster, nid_xyf));
565 BOOST_CHECK(nmask.includes(roster, nid_xyg));
566
567 BOOST_CHECK(nmask.includes(roster, nid_y));
568 BOOST_CHECK(nmask.includes(roster, nid_yf));
569 BOOST_CHECK(nmask.includes(roster, nid_yg));
570 BOOST_CHECK(nmask.includes(roster, nid_yx));
571 BOOST_CHECK(nmask.includes(roster, nid_yxf));
572 BOOST_CHECK(nmask.includes(roster, nid_yxg));
573 BOOST_CHECK(nmask.includes(roster, nid_yy));
574 BOOST_CHECK(nmask.includes(roster, nid_yyf));
575 BOOST_CHECK(nmask.includes(roster, nid_yyg));
576
577 // check restricted paths
578
579 path_restriction pmask(app);
580
581 BOOST_CHECK(pmask.empty());
582
583 BOOST_CHECK(pmask.includes(sp_root));
584 BOOST_CHECK(pmask.includes(sp_f));
585 BOOST_CHECK(pmask.includes(sp_g));
586
587 BOOST_CHECK(pmask.includes(sp_x));
588 BOOST_CHECK(pmask.includes(sp_xf));
589 BOOST_CHECK(pmask.includes(sp_xg));
590 BOOST_CHECK(pmask.includes(sp_xx));
591 BOOST_CHECK(pmask.includes(sp_xxf));
592 BOOST_CHECK(pmask.includes(sp_xxg));
593 BOOST_CHECK(pmask.includes(sp_xy));
594 BOOST_CHECK(pmask.includes(sp_xyf));
595 BOOST_CHECK(pmask.includes(sp_xyg));
596
597 BOOST_CHECK(pmask.includes(sp_y));
598 BOOST_CHECK(pmask.includes(sp_yf));
599 BOOST_CHECK(pmask.includes(sp_yg));
600 BOOST_CHECK(pmask.includes(sp_yx));
601 BOOST_CHECK(pmask.includes(sp_yxf));
602 BOOST_CHECK(pmask.includes(sp_yxg));
603 BOOST_CHECK(pmask.includes(sp_yy));
604 BOOST_CHECK(pmask.includes(sp_yyf));
605 BOOST_CHECK(pmask.includes(sp_yyg));
606}
607
608static void
609test_simple_include()
610{
611 roster_t roster;
612 setup(roster);
613
614 vector<file_path> includes, excludes;
615 includes.push_back(file_path_internal("x/x"));
616 includes.push_back(file_path_internal("y/y"));
617
618 app_state app;
619
620 // check restricted nodes
621
622 node_restriction nmask(includes, excludes, roster, app);
623
624 BOOST_CHECK(!nmask.empty());
625
626 BOOST_CHECK(!nmask.includes(roster, nid_root));
627 BOOST_CHECK(!nmask.includes(roster, nid_f));
628 BOOST_CHECK(!nmask.includes(roster, nid_g));
629
630 BOOST_CHECK(!nmask.includes(roster, nid_x));
631 BOOST_CHECK(!nmask.includes(roster, nid_xf));
632 BOOST_CHECK(!nmask.includes(roster, nid_xg));
633 BOOST_CHECK( nmask.includes(roster, nid_xx));
634 BOOST_CHECK( nmask.includes(roster, nid_xxf));
635 BOOST_CHECK( nmask.includes(roster, nid_xxg));
636 BOOST_CHECK(!nmask.includes(roster, nid_xy));
637 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
638 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
639
640 BOOST_CHECK(!nmask.includes(roster, nid_y));
641 BOOST_CHECK(!nmask.includes(roster, nid_yf));
642 BOOST_CHECK(!nmask.includes(roster, nid_yg));
643 BOOST_CHECK(!nmask.includes(roster, nid_yx));
644 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
645 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
646 BOOST_CHECK( nmask.includes(roster, nid_yy));
647 BOOST_CHECK( nmask.includes(roster, nid_yyf));
648 BOOST_CHECK( nmask.includes(roster, nid_yyg));
649
650 // check restricted paths
651
652 path_restriction pmask(includes, excludes, app);
653
654 BOOST_CHECK(!pmask.empty());
655
656 BOOST_CHECK(!pmask.includes(sp_root));
657 BOOST_CHECK(!pmask.includes(sp_f));
658 BOOST_CHECK(!pmask.includes(sp_g));
659
660 BOOST_CHECK(!pmask.includes(sp_x));
661 BOOST_CHECK(!pmask.includes(sp_xf));
662 BOOST_CHECK(!pmask.includes(sp_xg));
663 BOOST_CHECK( pmask.includes(sp_xx));
664 BOOST_CHECK( pmask.includes(sp_xxf));
665 BOOST_CHECK( pmask.includes(sp_xxg));
666 BOOST_CHECK(!pmask.includes(sp_xy));
667 BOOST_CHECK(!pmask.includes(sp_xyf));
668 BOOST_CHECK(!pmask.includes(sp_xyg));
669
670 BOOST_CHECK(!pmask.includes(sp_y));
671 BOOST_CHECK(!pmask.includes(sp_yf));
672 BOOST_CHECK(!pmask.includes(sp_yg));
673 BOOST_CHECK(!pmask.includes(sp_yx));
674 BOOST_CHECK(!pmask.includes(sp_yxf));
675 BOOST_CHECK(!pmask.includes(sp_yxg));
676 BOOST_CHECK( pmask.includes(sp_yy));
677 BOOST_CHECK( pmask.includes(sp_yyf));
678 BOOST_CHECK( pmask.includes(sp_yyg));
679}
680
681static void
682test_simple_exclude()
683{
684 roster_t roster;
685 setup(roster);
686
687 vector<file_path> includes, excludes;
688 excludes.push_back(file_path_internal("x/x"));
689 excludes.push_back(file_path_internal("y/y"));
690
691 app_state app;
692
693 // check restricted nodes
694
695 node_restriction nmask(includes, excludes, roster, app);
696
697 BOOST_CHECK(!nmask.empty());
698
699 BOOST_CHECK( nmask.includes(roster, nid_root));
700 BOOST_CHECK( nmask.includes(roster, nid_f));
701 BOOST_CHECK( nmask.includes(roster, nid_g));
702
703 BOOST_CHECK( nmask.includes(roster, nid_x));
704 BOOST_CHECK( nmask.includes(roster, nid_xf));
705 BOOST_CHECK( nmask.includes(roster, nid_xg));
706 BOOST_CHECK(!nmask.includes(roster, nid_xx));
707 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
708 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
709 BOOST_CHECK( nmask.includes(roster, nid_xy));
710 BOOST_CHECK( nmask.includes(roster, nid_xyf));
711 BOOST_CHECK( nmask.includes(roster, nid_xyg));
712
713 BOOST_CHECK( nmask.includes(roster, nid_y));
714 BOOST_CHECK( nmask.includes(roster, nid_yf));
715 BOOST_CHECK( nmask.includes(roster, nid_yg));
716 BOOST_CHECK( nmask.includes(roster, nid_yx));
717 BOOST_CHECK( nmask.includes(roster, nid_yxf));
718 BOOST_CHECK( nmask.includes(roster, nid_yxg));
719 BOOST_CHECK(!nmask.includes(roster, nid_yy));
720 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
721 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
722
723 // check restricted paths
724
725 path_restriction pmask(includes, excludes, app);
726
727 BOOST_CHECK(!pmask.empty());
728
729 BOOST_CHECK( pmask.includes(sp_root));
730 BOOST_CHECK( pmask.includes(sp_f));
731 BOOST_CHECK( pmask.includes(sp_g));
732
733 BOOST_CHECK( pmask.includes(sp_x));
734 BOOST_CHECK( pmask.includes(sp_xf));
735 BOOST_CHECK( pmask.includes(sp_xg));
736 BOOST_CHECK(!pmask.includes(sp_xx));
737 BOOST_CHECK(!pmask.includes(sp_xxf));
738 BOOST_CHECK(!pmask.includes(sp_xxg));
739 BOOST_CHECK( pmask.includes(sp_xy));
740 BOOST_CHECK( pmask.includes(sp_xyf));
741 BOOST_CHECK( pmask.includes(sp_xyg));
742
743 BOOST_CHECK( pmask.includes(sp_y));
744 BOOST_CHECK( pmask.includes(sp_yf));
745 BOOST_CHECK( pmask.includes(sp_yg));
746 BOOST_CHECK( pmask.includes(sp_yx));
747 BOOST_CHECK( pmask.includes(sp_yxf));
748 BOOST_CHECK( pmask.includes(sp_yxg));
749 BOOST_CHECK(!pmask.includes(sp_yy));
750 BOOST_CHECK(!pmask.includes(sp_yyf));
751 BOOST_CHECK(!pmask.includes(sp_yyg));
752}
753
754static void
755test_include_exclude()
756{
757 roster_t roster;
758 setup(roster);
759
760 vector<file_path> includes, excludes;
761 includes.push_back(file_path_internal("x"));
762 includes.push_back(file_path_internal("y"));
763 excludes.push_back(file_path_internal("x/x"));
764 excludes.push_back(file_path_internal("y/y"));
765
766 app_state app;
767
768 // check restricted nodes
769
770 node_restriction nmask(includes, excludes, roster, app);
771
772 BOOST_CHECK(!nmask.empty());
773
774 BOOST_CHECK(!nmask.includes(roster, nid_root));
775 BOOST_CHECK(!nmask.includes(roster, nid_f));
776 BOOST_CHECK(!nmask.includes(roster, nid_g));
777
778 BOOST_CHECK( nmask.includes(roster, nid_x));
779 BOOST_CHECK( nmask.includes(roster, nid_xf));
780 BOOST_CHECK( nmask.includes(roster, nid_xg));
781 BOOST_CHECK(!nmask.includes(roster, nid_xx));
782 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
783 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
784 BOOST_CHECK( nmask.includes(roster, nid_xy));
785 BOOST_CHECK( nmask.includes(roster, nid_xyf));
786 BOOST_CHECK( nmask.includes(roster, nid_xyg));
787
788 BOOST_CHECK( nmask.includes(roster, nid_y));
789 BOOST_CHECK( nmask.includes(roster, nid_yf));
790 BOOST_CHECK( nmask.includes(roster, nid_yg));
791 BOOST_CHECK( nmask.includes(roster, nid_yx));
792 BOOST_CHECK( nmask.includes(roster, nid_yxf));
793 BOOST_CHECK( nmask.includes(roster, nid_yxg));
794 BOOST_CHECK(!nmask.includes(roster, nid_yy));
795 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
796 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
797
798 // check restricted paths
799
800 path_restriction pmask(includes, excludes, app);
801
802 BOOST_CHECK(!pmask.empty());
803
804 BOOST_CHECK(!pmask.includes(sp_root));
805 BOOST_CHECK(!pmask.includes(sp_f));
806 BOOST_CHECK(!pmask.includes(sp_g));
807
808 BOOST_CHECK( pmask.includes(sp_x));
809 BOOST_CHECK( pmask.includes(sp_xf));
810 BOOST_CHECK( pmask.includes(sp_xg));
811 BOOST_CHECK(!pmask.includes(sp_xx));
812 BOOST_CHECK(!pmask.includes(sp_xxf));
813 BOOST_CHECK(!pmask.includes(sp_xxg));
814 BOOST_CHECK( pmask.includes(sp_xy));
815 BOOST_CHECK( pmask.includes(sp_xyf));
816 BOOST_CHECK( pmask.includes(sp_xyg));
817
818 BOOST_CHECK( pmask.includes(sp_y));
819 BOOST_CHECK( pmask.includes(sp_yf));
820 BOOST_CHECK( pmask.includes(sp_yg));
821 BOOST_CHECK( pmask.includes(sp_yx));
822 BOOST_CHECK( pmask.includes(sp_yxf));
823 BOOST_CHECK( pmask.includes(sp_yxg));
824 BOOST_CHECK(!pmask.includes(sp_yy));
825 BOOST_CHECK(!pmask.includes(sp_yyf));
826 BOOST_CHECK(!pmask.includes(sp_yyg));
827}
828
829static void
830test_exclude_include()
831{
832 roster_t roster;
833 setup(roster);
834
835 vector<file_path> includes, excludes;
836 // note that excludes higher up the tree than the top
837 // include are rather pointless -- nothing above the
838 // top include is included anyway
839 excludes.push_back(file_path_internal("x"));
840 excludes.push_back(file_path_internal("y"));
841 includes.push_back(file_path_internal("x/x"));
842 includes.push_back(file_path_internal("y/y"));
843
844 app_state app;
845
846 // check restricted nodes
847
848 node_restriction nmask(includes, excludes, roster, app);
849
850 BOOST_CHECK(!nmask.empty());
851
852 BOOST_CHECK(!nmask.includes(roster, nid_root));
853 BOOST_CHECK(!nmask.includes(roster, nid_f));
854 BOOST_CHECK(!nmask.includes(roster, nid_g));
855
856 BOOST_CHECK(!nmask.includes(roster, nid_x));
857 BOOST_CHECK(!nmask.includes(roster, nid_xf));
858 BOOST_CHECK(!nmask.includes(roster, nid_xg));
859 BOOST_CHECK( nmask.includes(roster, nid_xx));
860 BOOST_CHECK( nmask.includes(roster, nid_xxf));
861 BOOST_CHECK( nmask.includes(roster, nid_xxg));
862 BOOST_CHECK(!nmask.includes(roster, nid_xy));
863 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
864 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
865
866 BOOST_CHECK(!nmask.includes(roster, nid_y));
867 BOOST_CHECK(!nmask.includes(roster, nid_yf));
868 BOOST_CHECK(!nmask.includes(roster, nid_yg));
869 BOOST_CHECK(!nmask.includes(roster, nid_yx));
870 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
871 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
872 BOOST_CHECK( nmask.includes(roster, nid_yy));
873 BOOST_CHECK( nmask.includes(roster, nid_yyf));
874 BOOST_CHECK( nmask.includes(roster, nid_yyg));
875
876 // check restricted paths
877
878 path_restriction pmask(includes, excludes, app);
879
880 BOOST_CHECK(!pmask.empty());
881
882 BOOST_CHECK(!pmask.includes(sp_root));
883 BOOST_CHECK(!pmask.includes(sp_f));
884 BOOST_CHECK(!pmask.includes(sp_g));
885
886 BOOST_CHECK(!pmask.includes(sp_x));
887 BOOST_CHECK(!pmask.includes(sp_xf));
888 BOOST_CHECK(!pmask.includes(sp_xg));
889 BOOST_CHECK( pmask.includes(sp_xx));
890 BOOST_CHECK( pmask.includes(sp_xxf));
891 BOOST_CHECK( pmask.includes(sp_xxg));
892 BOOST_CHECK(!pmask.includes(sp_xy));
893 BOOST_CHECK(!pmask.includes(sp_xyf));
894 BOOST_CHECK(!pmask.includes(sp_xyg));
895
896 BOOST_CHECK(!pmask.includes(sp_y));
897 BOOST_CHECK(!pmask.includes(sp_yf));
898 BOOST_CHECK(!pmask.includes(sp_yg));
899 BOOST_CHECK(!pmask.includes(sp_yx));
900 BOOST_CHECK(!pmask.includes(sp_yxf));
901 BOOST_CHECK(!pmask.includes(sp_yxg));
902 BOOST_CHECK( pmask.includes(sp_yy));
903 BOOST_CHECK( pmask.includes(sp_yyf));
904 BOOST_CHECK( pmask.includes(sp_yyg));
905}
906
907static void
908test_invalid_roster_paths()
909{
910 roster_t roster;
911 setup(roster);
912
913 vector<file_path> includes, excludes;
914 includes.push_back(file_path_internal("foo"));
915 excludes.push_back(file_path_internal("bar"));
916
917 app_state app;
918 BOOST_CHECK_THROW(node_restriction(includes, excludes, roster, app),
919 informative_failure);
920}
921
922static void
923test_invalid_workspace_paths()
924{
925 roster_t roster;
926 setup(roster);
927
928 vector<file_path> includes, excludes;
929 includes.push_back(file_path_internal("foo"));
930 excludes.push_back(file_path_internal("bar"));
931
932 app_state app;
933 BOOST_CHECK_THROW(path_restriction(includes, excludes, app),
934 informative_failure);
935}
936
937static void
938test_include_depth_0()
939{
940 roster_t roster;
941 setup(roster);
942
943 vector<file_path> includes, excludes;
944 includes.push_back(file_path_internal("x"));
945 includes.push_back(file_path_internal("y"));
946
947 app_state app;
948 // FIXME: depth == 0 currently means directory + immediate children
949 // this should be changed to mean just the named directory but for
950 // compatibility with old restrictions this behaviour has been preserved
951 app.set_depth(0);
952
953 // check restricted nodes
954
955 node_restriction nmask(includes, excludes, roster, app);
956
957 BOOST_CHECK(!nmask.empty());
958
959 BOOST_CHECK(!nmask.includes(roster, nid_root));
960 BOOST_CHECK(!nmask.includes(roster, nid_f));
961 BOOST_CHECK(!nmask.includes(roster, nid_g));
962
963 BOOST_CHECK( nmask.includes(roster, nid_x));
964 BOOST_CHECK( nmask.includes(roster, nid_xf));
965 BOOST_CHECK( nmask.includes(roster, nid_xg));
966 BOOST_CHECK( nmask.includes(roster, nid_xx));
967 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
968 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
969 BOOST_CHECK( nmask.includes(roster, nid_xy));
970 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
971 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
972
973 BOOST_CHECK( nmask.includes(roster, nid_y));
974 BOOST_CHECK( nmask.includes(roster, nid_yf));
975 BOOST_CHECK( nmask.includes(roster, nid_yg));
976 BOOST_CHECK( nmask.includes(roster, nid_yx));
977 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
978 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
979 BOOST_CHECK( nmask.includes(roster, nid_yy));
980 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
981 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
982
983 // check restricted paths
984
985 path_restriction pmask(includes, excludes, app);
986
987 BOOST_CHECK(!pmask.empty());
988
989 BOOST_CHECK(!pmask.includes(sp_root));
990 BOOST_CHECK(!pmask.includes(sp_f));
991 BOOST_CHECK(!pmask.includes(sp_g));
992
993 BOOST_CHECK( pmask.includes(sp_x));
994 BOOST_CHECK( pmask.includes(sp_xf));
995 BOOST_CHECK( pmask.includes(sp_xg));
996 BOOST_CHECK( pmask.includes(sp_xx));
997 BOOST_CHECK(!pmask.includes(sp_xxf));
998 BOOST_CHECK(!pmask.includes(sp_xxg));
999 BOOST_CHECK( pmask.includes(sp_xy));
1000 BOOST_CHECK(!pmask.includes(sp_xyf));
1001 BOOST_CHECK(!pmask.includes(sp_xyg));
1002
1003 BOOST_CHECK( pmask.includes(sp_y));
1004 BOOST_CHECK( pmask.includes(sp_yf));
1005 BOOST_CHECK( pmask.includes(sp_yg));
1006 BOOST_CHECK( pmask.includes(sp_yx));
1007 BOOST_CHECK(!pmask.includes(sp_yxf));
1008 BOOST_CHECK(!pmask.includes(sp_yxg));
1009 BOOST_CHECK( pmask.includes(sp_yy));
1010 BOOST_CHECK(!pmask.includes(sp_yyf));
1011 BOOST_CHECK(!pmask.includes(sp_yyg));
1012}
1013
1014static void
1015test_include_depth_0_empty_restriction()
1016{
1017 roster_t roster;
1018 setup(roster);
1019
1020 vector<file_path> includes, excludes;
1021
1022 app_state app;
1023 // FIXME: depth == 0 currently means directory + immediate children
1024 // this should be changed to mean just the named directory but for
1025 // compatibility with old restrictions this behaviour has been preserved
1026 app.set_depth(0);
1027
1028 // check restricted nodes
1029
1030 node_restriction nmask(includes, excludes, roster, app);
1031
1032 BOOST_CHECK( nmask.empty());
1033
1034 BOOST_CHECK( nmask.includes(roster, nid_root));
1035 BOOST_CHECK( nmask.includes(roster, nid_f));
1036 BOOST_CHECK( nmask.includes(roster, nid_g));
1037
1038 BOOST_CHECK( nmask.includes(roster, nid_x));
1039 BOOST_CHECK(!nmask.includes(roster, nid_xf));
1040 BOOST_CHECK(!nmask.includes(roster, nid_xg));
1041 BOOST_CHECK(!nmask.includes(roster, nid_xx));
1042 BOOST_CHECK(!nmask.includes(roster, nid_xxf));
1043 BOOST_CHECK(!nmask.includes(roster, nid_xxg));
1044 BOOST_CHECK(!nmask.includes(roster, nid_xy));
1045 BOOST_CHECK(!nmask.includes(roster, nid_xyf));
1046 BOOST_CHECK(!nmask.includes(roster, nid_xyg));
1047
1048 BOOST_CHECK( nmask.includes(roster, nid_y));
1049 BOOST_CHECK(!nmask.includes(roster, nid_yf));
1050 BOOST_CHECK(!nmask.includes(roster, nid_yg));
1051 BOOST_CHECK(!nmask.includes(roster, nid_yx));
1052 BOOST_CHECK(!nmask.includes(roster, nid_yxf));
1053 BOOST_CHECK(!nmask.includes(roster, nid_yxg));
1054 BOOST_CHECK(!nmask.includes(roster, nid_yy));
1055 BOOST_CHECK(!nmask.includes(roster, nid_yyf));
1056 BOOST_CHECK(!nmask.includes(roster, nid_yyg));
1057
1058 // check restricted paths
1059
1060 path_restriction pmask(includes, excludes, app);
1061
1062 BOOST_CHECK( pmask.empty());
1063
1064 BOOST_CHECK( pmask.includes(sp_root));
1065 BOOST_CHECK( pmask.includes(sp_f));
1066 BOOST_CHECK( pmask.includes(sp_g));
1067
1068 BOOST_CHECK( pmask.includes(sp_x));
1069 BOOST_CHECK(!pmask.includes(sp_xf));
1070 BOOST_CHECK(!pmask.includes(sp_xg));
1071 BOOST_CHECK(!pmask.includes(sp_xx));
1072 BOOST_CHECK(!pmask.includes(sp_xxf));
1073 BOOST_CHECK(!pmask.includes(sp_xxg));
1074 BOOST_CHECK(!pmask.includes(sp_xy));
1075 BOOST_CHECK(!pmask.includes(sp_xyf));
1076 BOOST_CHECK(!pmask.includes(sp_xyg));
1077
1078 BOOST_CHECK( pmask.includes(sp_y));
1079 BOOST_CHECK(!pmask.includes(sp_yf));
1080 BOOST_CHECK(!pmask.includes(sp_yg));
1081 BOOST_CHECK(!pmask.includes(sp_yx));
1082 BOOST_CHECK(!pmask.includes(sp_yxf));
1083 BOOST_CHECK(!pmask.includes(sp_yxg));
1084 BOOST_CHECK(!pmask.includes(sp_yy));
1085 BOOST_CHECK(!pmask.includes(sp_yyf));
1086 BOOST_CHECK(!pmask.includes(sp_yyg));
1087}
1088
1089static void
1090test_include_depth_1()
1091{
1092 roster_t roster;
1093 setup(roster);
1094
1095 vector<file_path> includes, excludes;
1096 includes.push_back(file_path_internal("x"));
1097 includes.push_back(file_path_internal("y"));
1098
1099 app_state app;
1100 // FIXME: depth == 1 currently means directory + children + grand children
1101 // this should be changed to mean directory + immediate children but for
1102 // compatibility with old restrictions this behaviour has been preserved
1103 app.set_depth(1);
1104
1105 // check restricted nodes
1106
1107 node_restriction nmask(includes, excludes, roster, app);
1108
1109 BOOST_CHECK(!nmask.empty());
1110
1111 BOOST_CHECK(!nmask.includes(roster, nid_root));
1112 BOOST_CHECK(!nmask.includes(roster, nid_f));
1113 BOOST_CHECK(!nmask.includes(roster, nid_g));
1114
1115 BOOST_CHECK( nmask.includes(roster, nid_x));
1116 BOOST_CHECK( nmask.includes(roster, nid_xf));
1117 BOOST_CHECK( nmask.includes(roster, nid_xg));
1118 BOOST_CHECK( nmask.includes(roster, nid_xx));
1119 BOOST_CHECK( nmask.includes(roster, nid_xxf));
1120 BOOST_CHECK( nmask.includes(roster, nid_xxg));
1121 BOOST_CHECK( nmask.includes(roster, nid_xy));
1122 BOOST_CHECK( nmask.includes(roster, nid_xyf));
1123 BOOST_CHECK( nmask.includes(roster, nid_xyg));
1124
1125 BOOST_CHECK( nmask.includes(roster, nid_y));
1126 BOOST_CHECK( nmask.includes(roster, nid_yf));
1127 BOOST_CHECK( nmask.includes(roster, nid_yg));
1128 BOOST_CHECK( nmask.includes(roster, nid_yx));
1129 BOOST_CHECK( nmask.includes(roster, nid_yxf));
1130 BOOST_CHECK( nmask.includes(roster, nid_yxg));
1131 BOOST_CHECK( nmask.includes(roster, nid_yy));
1132 BOOST_CHECK( nmask.includes(roster, nid_yyf));
1133 BOOST_CHECK( nmask.includes(roster, nid_yyg));
1134
1135 // check restricted paths
1136
1137 path_restriction pmask(includes, excludes, app);
1138
1139 BOOST_CHECK(!pmask.empty());
1140
1141 BOOST_CHECK(!pmask.includes(sp_root));
1142 BOOST_CHECK(!pmask.includes(sp_f));
1143 BOOST_CHECK(!pmask.includes(sp_g));
1144
1145 BOOST_CHECK( pmask.includes(sp_x));
1146 BOOST_CHECK( pmask.includes(sp_xf));
1147 BOOST_CHECK( pmask.includes(sp_xg));
1148 BOOST_CHECK( pmask.includes(sp_xx));
1149 BOOST_CHECK( pmask.includes(sp_xxf));
1150 BOOST_CHECK( pmask.includes(sp_xxg));
1151 BOOST_CHECK( pmask.includes(sp_xy));
1152 BOOST_CHECK( pmask.includes(sp_xyf));
1153 BOOST_CHECK( pmask.includes(sp_xyg));
1154
1155 BOOST_CHECK( pmask.includes(sp_y));
1156 BOOST_CHECK( pmask.includes(sp_yf));
1157 BOOST_CHECK( pmask.includes(sp_yg));
1158 BOOST_CHECK( pmask.includes(sp_yx));
1159 BOOST_CHECK( pmask.includes(sp_yxf));
1160 BOOST_CHECK( pmask.includes(sp_yxg));
1161 BOOST_CHECK( pmask.includes(sp_yy));
1162 BOOST_CHECK( pmask.includes(sp_yyf));
1163 BOOST_CHECK( pmask.includes(sp_yyg));
1164}
1165
1166void
1167add_restrictions_tests(test_suite * suite)
1168{
1169 I(suite);
1170 suite->add(BOOST_TEST_CASE(&test_empty_restriction));
1171 suite->add(BOOST_TEST_CASE(&test_simple_include));
1172 suite->add(BOOST_TEST_CASE(&test_simple_exclude));
1173 suite->add(BOOST_TEST_CASE(&test_include_exclude));
1174 suite->add(BOOST_TEST_CASE(&test_exclude_include));
1175 suite->add(BOOST_TEST_CASE(&test_invalid_roster_paths));
1176 suite->add(BOOST_TEST_CASE(&test_invalid_workspace_paths));
1177 suite->add(BOOST_TEST_CASE(&test_include_depth_0));
1178 suite->add(BOOST_TEST_CASE(&test_include_depth_0_empty_restriction));
1179 suite->add(BOOST_TEST_CASE(&test_include_depth_1));
1180
1181}
1182#endif // BUILD_UNIT_TESTS
1183
1184// Local Variables:
1185// mode: C++
1186// fill-column: 76
1187// c-file-style: "gnu"
1188// indent-tabs-mode: nil
1189// End:
1190// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status