Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2016 The LUCI Authors. All rights reserved. | |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | |
| 3 # that can be found in the LICENSE file. | |
|
martiniss
2016/10/03 19:14:19
Add a file doc string and tests?
| |
| 4 | |
| 5 import re | |
| 6 | |
| 7 from collections import defaultdict, OrderedDict | |
| 8 | |
| 9 | |
| 10 class _filterObject(object): | |
| 11 def __init__(self, data, re_data): | |
| 12 self.data = data | |
| 13 self.re_data = re_data | |
| 14 | |
| 15 def __call__(self, check, step_odict): | |
| 16 includes = self.data.copy() | |
| 17 re_data = self.re_data.copy() | |
| 18 | |
| 19 re_usage_count = defaultdict(int) | |
| 20 | |
| 21 to_ret = OrderedDict() | |
| 22 for name, step in step_odict.iteritems(): | |
| 23 field_set = includes.pop(name, None) | |
| 24 if not field_set: | |
|
dnj
2016/10/04 16:42:33
Can we have an error if both specific and regex ma
dnj
2016/10/04 16:42:34
nit: You're using "is None" below, but "not" here.
iannucci
2016/10/06 20:28:08
I don't think that's an error case, I've documente
iannucci
2016/10/06 20:28:09
Done.
| |
| 25 for exp, (_, _, fset) in re_data.iteritems(): | |
| 26 if exp.match(name): | |
| 27 re_usage_count[exp] += 1 | |
| 28 field_set = fset | |
| 29 break | |
| 30 if field_set is None: | |
| 31 continue | |
| 32 if len(field_set) == 0: | |
| 33 to_ret[name] = step | |
| 34 else: | |
| 35 to_ret[name] = { | |
| 36 k: v for k, v in step.iteritems() | |
| 37 if k in field_set or k == 'name' | |
| 38 } | |
| 39 | |
| 40 check('all includes were used', len(includes) == 0) | |
| 41 | |
| 42 for regex, (at_least, at_most, _) in re_data.iteritems(): | |
| 43 check(re_usage_count[regex] >= at_least) | |
| 44 if at_most is not None: | |
| 45 check(re_usage_count[regex] < at_most) | |
|
dnj
2016/10/04 16:42:34
If I say, "at most 3", I would expect 3 to be vali
iannucci
2016/10/06 20:28:09
Done.
| |
| 46 | |
| 47 return to_ret | |
| 48 | |
| 49 def include(self, step_name, *fields): | |
| 50 new_data = self.data.copy() | |
| 51 new_data[step_name] = set(fields) | |
| 52 return _filterObject(new_data, self.re_data) | |
| 53 | |
| 54 def include_re(self, step_name_re, at_least=1, at_most=None, *fields): | |
| 55 new_re_data = self.re_data.copy() | |
| 56 new_re_data[re.compile(step_name_re)] = (at_least, at_most, set(fields)) | |
|
dnj
2016/10/04 16:42:34
Let's use a namedtuple here. Simple to create one
iannucci
2016/10/06 20:28:08
Done.
| |
| 57 return _filterObject(self.data, new_re_data) | |
| 58 | |
| 59 | |
| 60 def NewFilter(*steps): | |
|
dnj
2016/10/04 16:42:34
docstrings!
iannucci
2016/10/06 20:28:09
Done.
| |
| 61 return _filterObject({name: set() for name in steps}, {}) | |
| 62 | |
| 63 | |
| 64 def DoesntRun(check, step_odict, *steps): | |
|
dnj
2016/10/04 16:42:34
This looks awkward. How about DoesNotRun?
iannucci
2016/10/06 20:28:09
Done.
| |
| 65 banSet = set(steps) | |
| 66 for step_name in step_odict: | |
| 67 check(step_name not in banSet) | |
| 68 | |
| 69 | |
| 70 def DoesntRunRE(check, step_odict, *step_regexes): | |
|
dnj
2016/10/04 16:42:34
(same)
iannucci
2016/10/06 20:28:09
Done.
| |
| 71 step_regexes = [re.compile(r) for r in step_regexes] | |
|
dnj
2016/10/04 16:42:34
Assert that "step_odict" is an OrderedDict? Here a
iannucci
2016/10/06 20:28:09
That would be a terrible abstraction violation :D.
| |
| 72 for step_name in step_odict: | |
| 73 for r in step_regexes: | |
| 74 check(not r.match(step_name)) | |
| 75 | |
| 76 | |
| 77 def MustRun(check, step_odict, *steps): | |
| 78 step_names = step_odict.keys() | |
| 79 for step_name in steps: | |
| 80 check(step_name in step_names) | |
| 81 | |
| 82 | |
| 83 def MustRunRE(check, step_odict, step_regex, at_least=1, at_most=None): | |
|
martiniss
2016/10/03 19:14:18
Maybe have examples of these in other engine tests
iannucci
2016/10/06 20:28:09
there are docs now, I don't think an example of ev
| |
| 84 step_regex = re.compile(step_regex) | |
|
dnj
2016/10/04 16:42:34
WDYT about allowing "step_regex" to actually be a
iannucci
2016/10/06 20:28:08
It's already the case.
f = re.compile('foo')
F
| |
| 85 matches = 0 | |
| 86 for step_name in step_odict: | |
| 87 if step_regex.match(step_name): | |
| 88 matches += 1 | |
| 89 check(matches >= at_least) | |
| 90 if at_most is not None: | |
| 91 check(matches < at_most) | |
| 92 | |
| 93 | |
| 94 def DropExpectation(_check, _step_odict): | |
| 95 return [] | |
| OLD | NEW |