Merge lp:~javier.collado/utah/bug1040015 into lp:utah

Proposed by Javier Collado
Status: Merged
Merged at revision: 666
Proposed branch: lp:~javier.collado/utah/bug1040015
Merge into: lp:utah
Diff against target: 195 lines (+74/-30)
5 files modified
client.py (+2/-4)
utah/client/exceptions.py (+38/-16)
utah/client/runner.py (+8/-2)
utah/client/testcase.py (+10/-3)
utah/client/testsuite.py (+16/-5)
To merge this branch: bzr merge lp:~javier.collado/utah/bug1040015
Reviewer Review Type Date Requested Status
Joe Talbott (community) Approve
UTAH Dev Pending
Review via email: mp+121586@code.launchpad.net

Description of the change

Added customized error messages for each validation error. That means that when a file fails to validate, the output in the client will show the filename and the test suite/case name together with the information that is already part of the backtrace.

Some examples:
Master runlist failed to validate: '/home/javi/code/bzr/utah/bug1040015/utah/client/examples/master.run'
Detailed information: 'testsuites' is a required property

'utah_tests' test suite runlist invalid: 'utah_tests/tslist.run'
Detailed information: 'test' is a required property

'test_one' test case control file invalid: 'utah_tests/test_one/tc_control'
Detailed information: 'description' is a required property

To post a comment you must log in.
Revision history for this message
Max Brustkern (nuclearbob) wrote :

This looks reasonable to me, but I think it wouldn't hurt to have Joe take a look since he wrote the YAML stuff to begin with.

Revision history for this message
Joe Talbott (joetalbott) wrote :

Looks okay to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'client.py'
2--- client.py 2012-08-09 21:39:20 +0000
3+++ client.py 2012-08-28 11:46:19 +0000
4@@ -11,7 +11,7 @@
5 from utah.client.result import Result, ResultYAML, ResultJSON
6
7 from utah.client.common import DEFAULT_STATE_FILE
8-from utah.client import exceptions
9+from utah.client.exceptions import UTAHClientError
10
11
12 def process_cmdline_argparse():
13@@ -126,9 +126,7 @@
14
15 returncode = runner.run()
16
17- except (exceptions.BadDir,
18- exceptions.MissingFile,
19- exceptions.YAMLParsingError) as e:
20+ except UTAHClientError as e:
21 errno = getattr(e, 'errno', 1)
22 exit(errno, e)
23
24
25=== modified file 'utah/client/exceptions.py'
26--- utah/client/exceptions.py 2012-08-02 18:36:14 +0000
27+++ utah/client/exceptions.py 2012-08-28 11:46:19 +0000
28@@ -1,20 +1,42 @@
29-#!/usr/bin/python
30-
31-
32-class BadDir(Exception):
33- pass
34-
35-
36-class MissingFile(Exception):
37- pass
38-
39-
40-class BadMasterRunlist(Exception):
41- pass
42-
43-
44-class YAMLParsingError(Exception):
45+"""
46+UTAH client exceptions
47+"""
48+
49+
50+class UTAHClientError(Exception):
51+ """
52+ Base class of all exceptions in the client
53+ """
54+
55+
56+class BadDir(UTAHClientError):
57+ """
58+ Raised when some test directory isn't found
59+ or and error happens when trying to change to it
60+ """
61+
62+
63+class MissingFile(UTAHClientError):
64+ """
65+ Raised when yaml file with metadata about tests
66+ cannot be found
67+ """
68+
69+
70+class BadMasterRunlist(UTAHClientError):
71+ """
72+ Raised when master runlist isn't in the expected format
73+ """
74+
75+
76+class YAMLParsingError(UTAHClientError):
77 """
78 Used to provided the filename and the location
79 in which the parsing error happened when calling yaml.load
80 """
81+
82+
83+class ValidationError(UTAHClientError):
84+ """
85+ Used to provide additional information when schema validation fails
86+ """
87
88=== modified file 'utah/client/runner.py'
89--- utah/client/runner.py 2012-08-21 21:34:06 +0000
90+++ utah/client/runner.py 2012-08-28 11:46:19 +0000
91@@ -3,8 +3,8 @@
92 from result import Result
93 from testsuite import TestSuite
94 from state_agent import StateAgentYAML
95-
96 import exceptions
97+
98 import os
99 import shutil
100 import stat
101@@ -343,7 +343,13 @@
102 raise exceptions.MissingFile(runlist)
103
104 data = parse_yaml_file(local_filename)
105- jsonschema.validate(data, self.MASTER_RUNLIST_SCHEMA)
106+ try:
107+ jsonschema.validate(data, self.MASTER_RUNLIST_SCHEMA)
108+ except jsonschema.ValidationError as exception:
109+ raise exceptions.ValidationError(
110+ 'Master runlist failed to validate: {!r}\n'
111+ 'Detailed information: {}'
112+ .format(local_filename, exception))
113
114 if 'timeout' in data:
115 self.timeout = int(data['timeout'])
116
117=== modified file 'utah/client/testcase.py'
118--- utah/client/testcase.py 2012-08-08 13:11:52 +0000
119+++ utah/client/testcase.py 2012-08-28 11:46:19 +0000
120@@ -1,11 +1,12 @@
121 """
122 Testcase specific code.
123 """
124+import jsonschema
125
126 from common import run_cmd, parse_control_file
127 from common import do_nothing
128 from common import CMD_TC_BUILD, CMD_TC_SETUP, CMD_TC_TEST, CMD_TC_CLEANUP
129-from exceptions import MissingFile
130+from exceptions import MissingFile, ValidationError
131
132
133 class TestCase(object):
134@@ -75,8 +76,14 @@
135 import os
136 if _control_data is None:
137 if os.path.exists(self.filename):
138- control_data = parse_control_file(self.filename,
139- self.CONTROL_SCHEMA)
140+ try:
141+ control_data = parse_control_file(self.filename,
142+ self.CONTROL_SCHEMA)
143+ except jsonschema.ValidationError as exception:
144+ raise ValidationError(
145+ '{!r} test case control file invalid: {!r}\n'
146+ 'Detailed information: {}'
147+ .format(self.name, self.filename, exception))
148 else:
149 raise MissingFile(self.filename)
150 else:
151
152=== modified file 'utah/client/testsuite.py'
153--- utah/client/testsuite.py 2012-08-16 21:41:30 +0000
154+++ utah/client/testsuite.py 2012-08-28 11:46:19 +0000
155@@ -11,8 +11,7 @@
156 from .common import CMD_TS_BUILD, CMD_TS_SETUP, CMD_TS_CLEANUP
157 from .common import do_nothing
158 from .testcase import TestCase
159-from .exceptions import MissingFile
160-
161+from .exceptions import MissingFile, ValidationError
162
163
164 def parse_runlist_file(runlist_file):
165@@ -109,8 +108,14 @@
166 if _control_data is not None:
167 control_data = _control_data
168 elif self.control_file is not None:
169- control_data = parse_control_file(self.control_file,
170- self.CONTROL_SCHEMA)
171+ try:
172+ control_data = parse_control_file(self.control_file,
173+ self.CONTROL_SCHEMA)
174+ except jsonschema.ValidationError as exception:
175+ raise ValidationError(
176+ '{!r} test suite control file invalid: {!r}\n'
177+ 'Detailed information: {}'
178+ .format(self.name, self.control_file, exception))
179
180 if control_data is not None:
181 # already initialized
182@@ -122,7 +127,13 @@
183 if _runlist_data is not None:
184 runlist_data = _runlist_data
185 elif os.path.exists(self.runlist_file):
186- runlist_data = parse_runlist_file(self.runlist_file)
187+ try:
188+ runlist_data = parse_runlist_file(self.runlist_file)
189+ except jsonschema.ValidationError as exception:
190+ raise ValidationError(
191+ '{!r} test suite runlist invalid: {!r}\n'
192+ 'Detailed information: {}'
193+ .format(self.name, self.runlist_file, exception))
194 else:
195 raise MissingFile('File not found: {}'.format(self.runlist_file))
196

Subscribers

People subscribed via source and target branches