2 # Copyright 2008 Google Inc. Released under the GPL v2
4 import compiler
, textwrap
, types
7 REQUIRED_VARS
= set(['author', 'doc', 'name', 'time', 'test_class',
8 'test_category', 'test_type'])
10 class ControlVariableException(Exception):
14 class ControlData(object):
15 def __init__(self
, vars, path
, raise_warnings
=False):
18 self
.dependencies
= set()
19 self
.experimental
= False
20 self
.run_verify
= True
22 self
.test_parameters
= set()
24 diff
= REQUIRED_VARS
- set(vars)
26 warning
= ("WARNING: Not all required control "
27 "variables were specified in %s. Please define "
28 "%s.") % (self
.path
, ', '.join(diff
))
30 raise ControlVariableException(warning
)
31 print textwrap
.wrap(warning
, 80)
33 for key
, val
in vars.iteritems():
35 self
.set_attr(key
, val
, raise_warnings
)
39 print "WARNING: %s; skipping" % e
42 def set_attr(self
, attr
, val
, raise_warnings
=False):
45 set_fn
= getattr(self
, 'set_%s' % attr
)
47 except AttributeError:
48 # This must not be a variable we care about
52 def _set_string(self
, attr
, val
):
54 setattr(self
, attr
, val
)
57 def _set_option(self
, attr
, val
, options
):
59 if val
.lower() not in [x
.lower() for x
in options
]:
60 raise ValueError("%s must be one of the following "
61 "options: %s" % (attr
,
63 setattr(self
, attr
, val
)
66 def _set_bool(self
, attr
, val
):
67 val
= str(val
).lower()
73 msg
= "%s must be either true or false" % attr
75 setattr(self
, attr
, val
)
78 def _set_int(self
, attr
, val
, min=None, max=None):
80 if min is not None and min > val
:
81 raise ValueError("%s is %d, which is below the "
82 "minimum of %d" % (attr
, val
, min))
83 if max is not None and max < val
:
84 raise ValueError("%s is %d, which is above the "
85 "maximum of %d" % (attr
, val
, max))
86 setattr(self
, attr
, val
)
89 def _set_set(self
, attr
, val
):
91 items
= [x
.strip() for x
in val
.split(',')]
92 setattr(self
, attr
, set(items
))
95 def set_author(self
, val
):
96 self
._set
_string
('author', val
)
99 def set_dependencies(self
, val
):
100 self
._set
_set
('dependencies', val
)
103 def set_doc(self
, val
):
104 self
._set
_string
('doc', val
)
107 def set_experimental(self
, val
):
108 self
._set
_bool
('experimental', val
)
111 def set_name(self
, val
):
112 self
._set
_string
('name', val
)
115 def set_run_verify(self
, val
):
116 self
._set
_bool
('run_verify', val
)
119 def set_sync_count(self
, val
):
120 self
._set
_int
('sync_count', val
, min=1)
123 def set_time(self
, val
):
124 self
._set
_option
('time', val
, ['short', 'medium', 'long'])
127 def set_test_class(self
, val
):
128 self
._set
_string
('test_class', val
.lower())
131 def set_test_category(self
, val
):
132 self
._set
_string
('test_category', val
.lower())
135 def set_test_type(self
, val
):
136 self
._set
_option
('test_type', val
, ['client', 'server'])
139 def set_test_parameters(self
, val
):
140 self
._set
_set
('test_parameters', val
)
143 def _extract_const(n
):
144 assert(n
.__class
__ == compiler
.ast
.Assign
)
145 assert(n
.expr
.__class
__ == compiler
.ast
.Const
)
146 assert(n
.expr
.value
.__class
__ in (str, int, float, unicode))
147 assert(n
.nodes
.__class
__ == list)
148 assert(len(n
.nodes
) == 1)
149 assert(n
.nodes
[0].__class
__ == compiler
.ast
.AssName
)
150 assert(n
.nodes
[0].flags
.__class
__ == str)
151 assert(n
.nodes
[0].name
.__class
__ == str)
153 key
= n
.nodes
[0].name
.lower()
154 val
= str(n
.expr
.value
).strip()
159 def _extract_name(n
):
160 assert(n
.__class
__ == compiler
.ast
.Assign
)
161 assert(n
.expr
.__class
__ == compiler
.ast
.Name
)
162 assert(n
.nodes
.__class
__ == list)
163 assert(len(n
.nodes
) == 1)
164 assert(n
.nodes
[0].__class
__ == compiler
.ast
.AssName
)
165 assert(n
.nodes
[0].flags
.__class
__ == str)
166 assert(n
.nodes
[0].name
.__class
__ == str)
167 assert(n
.expr
.name
in ('False', 'True', 'None'))
169 key
= n
.nodes
[0].name
.lower()
170 val
= str(n
.expr
.name
)
175 def parse_control(path
, raise_warnings
=False):
177 mod
= compiler
.parseFile(path
)
178 except SyntaxError, e
:
179 raise ControlVariableException("Error parsing %s because %s" %
182 assert(mod
.__class
__ == compiler
.ast
.Module
)
183 assert(mod
.node
.__class
__ == compiler
.ast
.Stmt
)
184 assert(mod
.node
.nodes
.__class
__ == list)
187 for n
in mod
.node
.nodes
:
188 for fn
in (_extract_const
, _extract_name
):
193 except AssertionError, e
:
196 return ControlData(vars, path
, raise_warnings
)