17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 from __future__ import absolute_import |
18 from __future__ import absolute_import |
19 |
19 |
20 import os, os.path as osp |
20 import os, os.path as osp |
21 import errno |
21 import errno |
|
22 import shutil |
22 from tempfile import mkdtemp |
23 from tempfile import mkdtemp |
23 from subprocess import Popen, PIPE, STDOUT |
24 from subprocess import Popen, PIPE, STDOUT |
24 |
25 |
25 from six.moves.queue import Queue, Empty |
26 from six.moves.queue import Queue, Empty |
26 |
27 |
36 from cubicweb.devtools.testlib import TemporaryDirectory |
37 from cubicweb.devtools.testlib import TemporaryDirectory |
37 |
38 |
38 |
39 |
39 class FirefoxHelper(object): |
40 class FirefoxHelper(object): |
40 |
41 |
41 def __init__(self, url=None): |
42 def __init__(self, url): |
|
43 self._url = url |
42 self._process = None |
44 self._process = None |
43 self._profile_dir = mkdtemp(prefix='cwtest-ffxprof-') |
45 self._profile_dir = None |
44 self.firefox_cmd = ['firefox', '-no-remote'] |
46 self.firefox_cmd = ['firefox', '-no-remote'] |
45 if os.name == 'posix': |
47 if os.name == 'posix': |
46 self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'), |
48 self.firefox_cmd = [osp.join(osp.dirname(__file__), 'data', 'xvfb-run.sh'), |
47 '-a', '-s', '-noreset -screen 0 800x600x24'] + self.firefox_cmd |
49 '-a', '-s', '-noreset -screen 0 800x600x24'] + self.firefox_cmd |
|
50 |
|
51 def __enter__(self): |
|
52 self._profile_dir = mkdtemp(prefix='cwtest-ffxprof-') |
|
53 isavailable, reason = self.test() |
|
54 if not isavailable: |
|
55 raise RuntimeError( |
|
56 'firefox not available or not working properly (%s)' % reason) |
|
57 self.start() |
|
58 return self |
|
59 |
|
60 def __exit__(self, *exc_info): |
|
61 self.stop() |
|
62 shutil.rmtree(self._profile_dir, ignore_errors=True) |
48 |
63 |
49 def test(self): |
64 def test(self): |
50 try: |
65 try: |
51 proc = Popen(['firefox', '--help'], stdout=PIPE, stderr=STDOUT) |
66 proc = Popen(['firefox', '--help'], stdout=PIPE, stderr=STDOUT) |
52 stdout, _ = proc.communicate() |
67 stdout, _ = proc.communicate() |
55 if exc.errno == errno.ENOENT: |
70 if exc.errno == errno.ENOENT: |
56 msg = '[%s] %s' % (errno.errorcode[exc.errno], exc.strerror) |
71 msg = '[%s] %s' % (errno.errorcode[exc.errno], exc.strerror) |
57 return False, msg |
72 return False, msg |
58 raise |
73 raise |
59 |
74 |
60 def start(self, url): |
75 def start(self): |
61 self.stop() |
76 self.stop() |
62 cmd = self.firefox_cmd + ['-silent', '--profile', self._profile_dir, |
77 cmd = self.firefox_cmd + ['-silent', '--profile', self._profile_dir, |
63 '-url', url] |
78 '-url', self._url] |
64 with open(os.devnull, 'w') as fnull: |
79 with open(os.devnull, 'w') as fnull: |
65 self._process = Popen(cmd, stdout=fnull, stderr=fnull) |
80 self._process = Popen(cmd, stdout=fnull, stderr=fnull) |
66 |
81 |
67 def stop(self): |
82 def stop(self): |
68 if self._process is not None: |
83 if self._process is not None: |
120 QUnitView.depends = depends |
135 QUnitView.depends = depends |
121 |
136 |
122 while not self.test_queue.empty(): |
137 while not self.test_queue.empty(): |
123 self.test_queue.get(False) |
138 self.test_queue.get(False) |
124 |
139 |
125 browser = FirefoxHelper() |
140 with FirefoxHelper(self.config['base-url'] + '?vid=qunit') as browser: |
126 isavailable, reason = browser.test() |
141 test_count = 0 |
127 if not isavailable: |
142 error = False |
128 self.fail('firefox not available or not working properly (%s)' % reason) |
143 |
129 browser.start(self.config['base-url'] + "?vid=qunit") |
144 def runtime_error(*data): |
130 test_count = 0 |
145 raise RuntimeError(*data) |
131 error = False |
146 |
132 |
147 while not error: |
133 def runtime_error(*data): |
148 try: |
134 raise RuntimeError(*data) |
149 result, test_name, msg = self.test_queue.get(timeout=timeout) |
135 |
150 test_name = '%s (%s)' % (test_name, test_file) |
136 while not error: |
151 if result is None: |
137 try: |
152 break |
138 result, test_name, msg = self.test_queue.get(timeout=timeout) |
153 test_count += 1 |
139 test_name = '%s (%s)' % (test_name, test_file) |
154 if result: |
140 if result is None: |
155 yield test_name, lambda *args: 1, () |
141 break |
156 else: |
142 test_count += 1 |
157 yield test_name, self.fail, (msg, ) |
143 if result: |
158 except Empty: |
144 yield test_name, lambda *args: 1, () |
159 error = True |
145 else: |
160 msg = '%s inactivity timeout (%is). %i test results received' |
146 yield test_name, self.fail, (msg, ) |
161 yield test_file, runtime_error, (msg % (test_file, timeout, test_count), ) |
147 except Empty: |
162 |
148 error = True |
|
149 msg = '%s inactivity timeout (%is). %i test results received' |
|
150 yield test_file, runtime_error, (msg % (test_file, timeout, test_count), ) |
|
151 browser.stop() |
|
152 if test_count <= 0 and not error: |
163 if test_count <= 0 and not error: |
153 yield test_name, runtime_error, ('No test yielded by qunit for %s' % test_file, ) |
164 yield test_name, runtime_error, ('No test yielded by qunit for %s' % test_file, ) |
|
165 |
154 |
166 |
155 class QUnitResultController(Controller): |
167 class QUnitResultController(Controller): |
156 |
168 |
157 __regid__ = 'qunit_result' |
169 __regid__ = 'qunit_result' |
158 |
170 |