Merge lp:~openerp-dev/openobject-server/trunk-test-al into lp:openobject-server
- trunk-test-al
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~openerp-dev/openobject-server/trunk-test-al |
Merge into: | lp:openobject-server |
Diff against target: |
1685 lines (+478/-589) 34 files modified
openerp/addons/__init__.py (+0/-3) openerp/addons/base/__openerp__.py (+0/-2) openerp/addons/base/test/bug_lp541545.xml (+0/-14) openerp/addons/base/test/test_context.xml (+0/-20) openerp/addons/base/tests/__init__.py (+16/-12) openerp/addons/base/tests/test_acl.py (+1/-2) openerp/addons/base/tests/test_basecase.py (+1/-1) openerp/addons/base/tests/test_db_cursor.py (+1/-1) openerp/addons/base/tests/test_expression.py (+10/-1) openerp/addons/base/tests/test_fields.py (+1/-2) openerp/addons/base/tests/test_ir_filters.py (+1/-1) openerp/addons/base/tests/test_ir_sequence.py (+1/-1) openerp/addons/base/tests/test_mail.py (+2/-1) openerp/addons/base/tests/test_misc.py (+37/-0) openerp/addons/base/tests/test_orm.py (+1/-1) openerp/addons/base/tests/test_phantom.py (+11/-0) openerp/addons/base/tests/test_phantom_dummy.js (+4/-0) openerp/addons/base/tests/test_uninstall.py (+89/-0) openerp/addons/base/tests/test_xmlrpc.py (+12/-54) openerp/cli/server.py (+10/-26) openerp/http.py (+5/-2) openerp/modules/__init__.py (+3/-9) openerp/modules/loading.py (+4/-11) openerp/modules/module.py (+65/-216) openerp/modules/registry.py (+48/-57) openerp/service/model.py (+0/-2) openerp/service/server.py (+36/-7) openerp/sql_db.py (+3/-0) openerp/tests/__init__.py (+5/-39) openerp/tests/common.py (+108/-45) openerp/tests/test_expression.py (+0/-13) openerp/tests/test_misc.py (+0/-44) openerp/tools/yaml_import.py (+1/-2) openerpcommand/run_tests.py (+2/-0) |
To merge this branch: | bzr merge lp:~openerp-dev/openobject-server/trunk-test-al |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christophe Simonis (OpenERP) | Needs Fixing | ||
Raphael Collet (OpenERP) (community) | Needs Information | ||
Review via email: mp+202225@code.launchpad.net |
Commit message
Description of the change
- 5018. By Antony Lesuisse (OpenERP)
-
replace RpcTestCase by HttpTestCase
- postponed when the server is listening
- magic session_id for cross requests rollback - 5019. By Antony Lesuisse (OpenERP)
-
[MERGE] trunk
- 5020. By Antony Lesuisse (OpenERP)
-
add phantomjs helper for HttpCase (refactored from ddm website test)
- 5021. By Antony Lesuisse (OpenERP)
-
[MERGE] trunk
- 5022. By Antony Lesuisse (OpenERP)
-
[FIX] merge conflicts woes
- 5023. By Antony Lesuisse (OpenERP)
-
[IMP] start http before preloading regsitries
- 5024. By Antony Lesuisse (OpenERP)
-
[IMP] run http test, dont lock the registry manager
- 5025. By Antony Lesuisse (OpenERP)
-
[IMP] allow request registries under construction
- 5026. By Antony Lesuisse (OpenERP)
-
[FIX] oe run_test return code 0
- 5027. By Antony Lesuisse (OpenERP)
-
[ADD] phantomjs example test
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
Please redo the move openerp/
You've screwed up the file history.
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
Why have you removed the lock from the registry?
Couldn't this cause an issue when the server runs multi-threaded?
Raphael Collet (OpenERP) (rco-openerp) wrote : | # |
Please remove commented code (diff 1332-1335).
Christophe Simonis (OpenERP) (kangol) wrote : | # |
> Please redo the move openerp/
> openerp/
> You've screwed up the file history.
same for openerp/
Christophe Simonis (OpenERP) (kangol) wrote : | # |
Why removing the RLock on registry access?
The check on _init (openerp/
Accessing the database during loading may lead to strange things for the end-user. I know it's needed to http test but only deactivate this behaviour if the server is running with --test-enable flag.
Unmerged revisions
- 5027. By Antony Lesuisse (OpenERP)
-
[ADD] phantomjs example test
- 5026. By Antony Lesuisse (OpenERP)
-
[FIX] oe run_test return code 0
- 5025. By Antony Lesuisse (OpenERP)
-
[IMP] allow request registries under construction
- 5024. By Antony Lesuisse (OpenERP)
-
[IMP] run http test, dont lock the registry manager
- 5023. By Antony Lesuisse (OpenERP)
-
[IMP] start http before preloading regsitries
- 5022. By Antony Lesuisse (OpenERP)
-
[FIX] merge conflicts woes
- 5021. By Antony Lesuisse (OpenERP)
-
[MERGE] trunk
- 5020. By Antony Lesuisse (OpenERP)
-
add phantomjs helper for HttpCase (refactored from ddm website test)
- 5019. By Antony Lesuisse (OpenERP)
-
[MERGE] trunk
- 5018. By Antony Lesuisse (OpenERP)
-
replace RpcTestCase by HttpTestCase
- postponed when the server is listening
- magic session_id for cross requests rollback
Preview Diff
1 | === modified file 'openerp/addons/__init__.py' |
2 | --- openerp/addons/__init__.py 2012-01-09 12:41:20 +0000 |
3 | +++ openerp/addons/__init__.py 2014-02-03 01:51:54 +0000 |
4 | @@ -34,7 +34,4 @@ |
5 | |
6 | """ |
7 | |
8 | -# get_module_path is used only by base_module_quality |
9 | -from openerp.modules import get_module_resource, get_module_path |
10 | - |
11 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
12 | |
13 | === modified file 'openerp/addons/base/__openerp__.py' |
14 | --- openerp/addons/base/__openerp__.py 2013-10-06 15:18:27 +0000 |
15 | +++ openerp/addons/base/__openerp__.py 2014-02-03 01:51:54 +0000 |
16 | @@ -92,8 +92,6 @@ |
17 | ], |
18 | 'test': [ |
19 | 'test/base_test.yml', |
20 | - 'test/test_context.xml', |
21 | - 'test/bug_lp541545.xml', |
22 | 'test/test_osv_expression.yml', |
23 | 'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules. |
24 | ], |
25 | |
26 | === removed file 'openerp/addons/base/test/bug_lp541545.xml' |
27 | --- openerp/addons/base/test/bug_lp541545.xml 2010-09-24 11:34:52 +0000 |
28 | +++ openerp/addons/base/test/bug_lp541545.xml 1970-01-01 00:00:00 +0000 |
29 | @@ -1,14 +0,0 @@ |
30 | -<?xml version="1.0" encoding="utf-8"?> |
31 | -<openerp> |
32 | - <!-- Test count attribute for assertions --> |
33 | - <data> |
34 | - <assert |
35 | - model="res.currency.rate" |
36 | - search="[('currency_id', '=', ref('INR'))]" |
37 | - count="1" |
38 | - string="Rate entries for Indian rupee"> |
39 | - <test expr="True"/> |
40 | - </assert> |
41 | - </data> |
42 | - |
43 | -</openerp> |
44 | |
45 | === removed file 'openerp/addons/base/test/test_context.xml' |
46 | --- openerp/addons/base/test/test_context.xml 2011-12-29 12:34:13 +0000 |
47 | +++ openerp/addons/base/test/test_context.xml 1970-01-01 00:00:00 +0000 |
48 | @@ -1,20 +0,0 @@ |
49 | -<?xml version="1.0" encoding="utf-8"?> |
50 | -<openerp> |
51 | - <!-- Test context attribute for unit tests --> |
52 | - <data context="{'date': '2009-06-01'}"> |
53 | -<!-- <assert --> |
54 | -<!-- model="res.currency"--> |
55 | -<!-- id="INR"--> |
56 | -<!-- string="Indian rupee rate in 2009">--> |
57 | - <!-- date specified in data element's context --> |
58 | -<!-- <test expr="str(rate)">65.8287</test>--> |
59 | -<!-- </assert> --> |
60 | - <assert |
61 | - model="res.currency" |
62 | - id="INR" |
63 | - string="Indian rupee rate in 2002" |
64 | - context="{'date': '2010-06-01'}"> |
65 | - <test expr="rate_ids and str(rate_ids[0].rate)">59.9739</test> |
66 | - </assert> |
67 | - </data> |
68 | -</openerp> |
69 | |
70 | === modified file 'openerp/addons/base/tests/__init__.py' |
71 | --- openerp/addons/base/tests/__init__.py 2013-10-02 13:38:20 +0000 |
72 | +++ openerp/addons/base/tests/__init__.py 2014-02-03 01:51:54 +0000 |
73 | @@ -1,3 +1,18 @@ |
74 | +import test_acl |
75 | +import test_basecase |
76 | +import test_db_cursor |
77 | +import test_expression |
78 | +import test_fields |
79 | +import test_ir_filters |
80 | +import test_ir_sequence |
81 | +import test_mail |
82 | +import test_orm |
83 | +import test_osv |
84 | +import test_translate |
85 | +#import test_uninstall |
86 | +import test_view_validation |
87 | +import test_xmlrpc |
88 | + |
89 | import test_base |
90 | import test_expression |
91 | import test_ir_actions |
92 | @@ -9,15 +24,4 @@ |
93 | import test_search |
94 | import test_views |
95 | |
96 | -checks = [ |
97 | - test_base, |
98 | - test_expression, |
99 | - test_ir_actions, |
100 | - test_ir_attachment, |
101 | - test_ir_values, |
102 | - test_menu, |
103 | - test_res_config, |
104 | - test_res_lang, |
105 | - test_search, |
106 | - test_views, |
107 | -] |
108 | +import test_phantom |
109 | |
110 | === renamed file 'openerp/tests/test_acl.py' => 'openerp/addons/base/tests/test_acl.py' |
111 | --- openerp/tests/test_acl.py 2014-01-28 18:09:10 +0000 |
112 | +++ openerp/addons/base/tests/test_acl.py 2014-02-03 01:51:54 +0000 |
113 | @@ -3,8 +3,7 @@ |
114 | |
115 | import openerp |
116 | from openerp.tools.misc import mute_logger |
117 | - |
118 | -import common |
119 | +from openerp.tests import common |
120 | |
121 | # test group that demo user should not have |
122 | GROUP_TECHNICAL_FEATURES = 'base.group_no_one' |
123 | |
124 | === renamed file 'openerp/tests/test_basecase.py' => 'openerp/addons/base/tests/test_basecase.py' |
125 | --- openerp/tests/test_basecase.py 2012-11-09 17:08:26 +0000 |
126 | +++ openerp/addons/base/tests/test_basecase.py 2014-02-03 01:51:54 +0000 |
127 | @@ -1,7 +1,7 @@ |
128 | # -*- coding: utf-8 -*- |
129 | import unittest2 |
130 | |
131 | -import common |
132 | +from openerp.tests import common |
133 | |
134 | class test_single_transaction_case(common.SingleTransactionCase): |
135 | """ |
136 | |
137 | === renamed file 'openerp/tests/test_db_cursor.py' => 'openerp/addons/base/tests/test_db_cursor.py' |
138 | --- openerp/tests/test_db_cursor.py 2012-11-15 12:39:37 +0000 |
139 | +++ openerp/addons/base/tests/test_db_cursor.py 2014-02-03 01:51:54 +0000 |
140 | @@ -4,7 +4,7 @@ |
141 | |
142 | import openerp |
143 | from openerp.tools.misc import mute_logger |
144 | -import common |
145 | +from openerp.tests import common |
146 | |
147 | DB = common.DB |
148 | ADMIN_USER_ID = common.ADMIN_USER_ID |
149 | |
150 | === modified file 'openerp/addons/base/tests/test_expression.py' |
151 | --- openerp/addons/base/tests/test_expression.py 2013-04-19 17:31:59 +0000 |
152 | +++ openerp/addons/base/tests/test_expression.py 2014-02-03 01:51:54 +0000 |
153 | @@ -1,8 +1,9 @@ |
154 | import unittest2 |
155 | + |
156 | +import openerp |
157 | from openerp.osv.orm import BaseModel |
158 | import openerp.tests.common as common |
159 | |
160 | - |
161 | class test_expression(common.TransactionCase): |
162 | |
163 | def _reinit_mock(self): |
164 | @@ -439,5 +440,13 @@ |
165 | partner_parent_id_col._auto_join = False |
166 | state_country_id_col._auto_join = False |
167 | |
168 | + def test_30_normalize_domain(self): |
169 | + expression = openerp.osv.expression |
170 | + norm_domain = domain = ['&', (1, '=', 1), ('a', '=', 'b')] |
171 | + assert norm_domain == expression.normalize_domain(domain), "Normalized domains should be left untouched" |
172 | + domain = [('x', 'in', ['y', 'z']), ('a.v', '=', 'e'), '|', '|', ('a', '=', 'b'), '!', ('c', '>', 'd'), ('e', '!=', 'f'), ('g', '=', 'h')] |
173 | + norm_domain = ['&', '&', '&'] + domain |
174 | + assert norm_domain == expression.normalize_domain(domain), "Non-normalized domains should be properly normalized" |
175 | + |
176 | if __name__ == '__main__': |
177 | unittest2.main() |
178 | |
179 | === renamed file 'openerp/tests/test_fields.py' => 'openerp/addons/base/tests/test_fields.py' |
180 | --- openerp/tests/test_fields.py 2012-12-17 14:30:29 +0000 |
181 | +++ openerp/addons/base/tests/test_fields.py 2014-02-03 01:51:54 +0000 |
182 | @@ -1,9 +1,8 @@ |
183 | # |
184 | # test cases for fields access, etc. |
185 | # |
186 | -import common |
187 | - |
188 | from openerp.osv import fields |
189 | +from openerp.tests import common |
190 | |
191 | class TestRelatedField(common.TransactionCase): |
192 | |
193 | |
194 | === renamed file 'openerp/tests/test_func.py' => 'openerp/addons/base/tests/test_func.py' |
195 | === renamed file 'openerp/tests/test_ir_filters.py' => 'openerp/addons/base/tests/test_ir_filters.py' |
196 | --- openerp/tests/test_ir_filters.py 2014-01-28 16:48:49 +0000 |
197 | +++ openerp/addons/base/tests/test_ir_filters.py 2014-02-03 01:51:54 +0000 |
198 | @@ -2,7 +2,7 @@ |
199 | import functools |
200 | |
201 | from openerp import exceptions |
202 | -from . import common |
203 | +from openerp.tests import common |
204 | |
205 | def noid(d): |
206 | """ Removes `id` key from a dict so we don't have to keep these things |
207 | |
208 | === renamed file 'openerp/tests/test_ir_sequence.py' => 'openerp/addons/base/tests/test_ir_sequence.py' |
209 | --- openerp/tests/test_ir_sequence.py 2012-11-28 13:51:01 +0000 |
210 | +++ openerp/addons/base/tests/test_ir_sequence.py 2014-02-03 01:51:54 +0000 |
211 | @@ -11,7 +11,7 @@ |
212 | import unittest2 |
213 | |
214 | import openerp |
215 | -import common |
216 | +from openerp.tests import common |
217 | |
218 | DB = common.DB |
219 | ADMIN_USER_ID = common.ADMIN_USER_ID |
220 | |
221 | === renamed file 'openerp/tests/test_mail.py' => 'openerp/addons/base/tests/test_mail.py' (properties changed: +x to -x) |
222 | --- openerp/tests/test_mail.py 2014-01-16 09:17:16 +0000 |
223 | +++ openerp/addons/base/tests/test_mail.py 2014-02-03 01:51:54 +0000 |
224 | @@ -26,9 +26,10 @@ |
225 | |
226 | from lxml import etree |
227 | |
228 | -from openerp.tests import test_mail_examples |
229 | from openerp.tools import html_sanitize, html_email_clean, append_content_to_html, plaintext2html, email_split |
230 | |
231 | +import test_mail_examples |
232 | + |
233 | |
234 | class TestSanitizer(unittest2.TestCase): |
235 | """ Test the html sanitizer that filters html to remove unwanted attributes """ |
236 | |
237 | === renamed file 'openerp/tests/test_mail_examples.py' => 'openerp/addons/base/tests/test_mail_examples.py' |
238 | === added file 'openerp/addons/base/tests/test_misc.py' |
239 | --- openerp/addons/base/tests/test_misc.py 1970-01-01 00:00:00 +0000 |
240 | +++ openerp/addons/base/tests/test_misc.py 2014-02-03 01:51:54 +0000 |
241 | @@ -0,0 +1,37 @@ |
242 | +import unittest2 |
243 | + |
244 | +from openerp.tools import misc |
245 | + |
246 | + |
247 | +class test_countingstream(unittest2.TestCase): |
248 | + def test_empty_stream(self): |
249 | + s = misc.CountingStream(iter([])) |
250 | + self.assertEqual(s.index, -1) |
251 | + self.assertIsNone(next(s, None)) |
252 | + self.assertEqual(s.index, 0) |
253 | + |
254 | + def test_single(self): |
255 | + s = misc.CountingStream(xrange(1)) |
256 | + self.assertEqual(s.index, -1) |
257 | + self.assertEqual(next(s, None), 0) |
258 | + self.assertIsNone(next(s, None)) |
259 | + self.assertEqual(s.index, 1) |
260 | + |
261 | + def test_full(self): |
262 | + s = misc.CountingStream(xrange(42)) |
263 | + for _ in s: |
264 | + pass |
265 | + self.assertEqual(s.index, 42) |
266 | + |
267 | + def test_repeated(self): |
268 | + """ Once the CountingStream has stopped iterating, the index should not |
269 | + increase anymore (the internal state should not be allowed to change) |
270 | + """ |
271 | + s = misc.CountingStream(iter([])) |
272 | + self.assertIsNone(next(s, None)) |
273 | + self.assertEqual(s.index, 0) |
274 | + self.assertIsNone(next(s, None)) |
275 | + self.assertEqual(s.index, 0) |
276 | + |
277 | +if __name__ == '__main__': |
278 | + unittest2.main() |
279 | |
280 | === renamed file 'openerp/tests/test_orm.py' => 'openerp/addons/base/tests/test_orm.py' |
281 | --- openerp/tests/test_orm.py 2014-01-23 13:06:03 +0000 |
282 | +++ openerp/addons/base/tests/test_orm.py 2014-02-03 01:51:54 +0000 |
283 | @@ -1,6 +1,6 @@ |
284 | from collections import defaultdict |
285 | from openerp.tools import mute_logger |
286 | -import common |
287 | +from openerp.tests import common |
288 | |
289 | UID = common.ADMIN_USER_ID |
290 | DB = common.DB |
291 | |
292 | === renamed file 'openerp/tests/test_osv.py' => 'openerp/addons/base/tests/test_osv.py' |
293 | === added file 'openerp/addons/base/tests/test_phantom.py' |
294 | --- openerp/addons/base/tests/test_phantom.py 1970-01-01 00:00:00 +0000 |
295 | +++ openerp/addons/base/tests/test_phantom.py 2014-02-03 01:51:54 +0000 |
296 | @@ -0,0 +1,11 @@ |
297 | +# -*- coding: utf-8 -*- |
298 | + |
299 | +import openerp |
300 | +from openerp.tests import common |
301 | + |
302 | +class test_phantom(common.HttpCase): |
303 | + |
304 | + def test_01_dummy(self): |
305 | + self.phantomjs(openerp.modules.module.get_module_resource('base','tests','test_phantom_dummy.js')) |
306 | + |
307 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
308 | |
309 | === added file 'openerp/addons/base/tests/test_phantom_dummy.js' |
310 | --- openerp/addons/base/tests/test_phantom_dummy.js 1970-01-01 00:00:00 +0000 |
311 | +++ openerp/addons/base/tests/test_phantom_dummy.js 2014-02-03 01:51:54 +0000 |
312 | @@ -0,0 +1,4 @@ |
313 | +console.log('{ "event": "success", "message": "Phantomjs success"}'); |
314 | +// For a failure: |
315 | +// console.log('{ "event": "failure", "message": "The test failed" }'); |
316 | +phantom.exit(); |
317 | |
318 | === renamed file 'openerp/tests/test_qweb.py' => 'openerp/addons/base/tests/test_qweb.py' |
319 | === renamed file 'openerp/tests/test_translate.py' => 'openerp/addons/base/tests/test_translate.py' |
320 | === added file 'openerp/addons/base/tests/test_uninstall.py' |
321 | --- openerp/addons/base/tests/test_uninstall.py 1970-01-01 00:00:00 +0000 |
322 | +++ openerp/addons/base/tests/test_uninstall.py 2014-02-03 01:51:54 +0000 |
323 | @@ -0,0 +1,89 @@ |
324 | +# -*- coding: utf-8 -*- |
325 | +# This assumes an existing but uninitialized database. |
326 | +import unittest2 |
327 | + |
328 | +import openerp |
329 | +from openerp import SUPERUSER_ID |
330 | +from openerp.tests import common |
331 | + |
332 | +DB = common.DB |
333 | +ADMIN_USER_ID = common.ADMIN_USER_ID |
334 | + |
335 | +def registry(model): |
336 | + return openerp.modules.registry.RegistryManager.get(DB)[model] |
337 | + |
338 | +def cursor(): |
339 | + return openerp.modules.registry.RegistryManager.get(DB).db.cursor() |
340 | + |
341 | +def model_exists(model_name): |
342 | + registry = openerp.modules.registry.RegistryManager.get(DB) |
343 | + return model_name in registry |
344 | + |
345 | +def reload_registry(): |
346 | + openerp.modules.registry.RegistryManager.new( |
347 | + DB, update_module=True) |
348 | + |
349 | +def search_registry(model_name, domain): |
350 | + cr = cursor() |
351 | + model = registry(model_name) |
352 | + record_ids = model.search(cr, SUPERUSER_ID, domain, {}) |
353 | + cr.close() |
354 | + return record_ids |
355 | + |
356 | +def install_module(module_name): |
357 | + ir_module_module = registry('ir.module.module') |
358 | + cr = cursor() |
359 | + module_ids = ir_module_module.search(cr, SUPERUSER_ID, |
360 | + [('name', '=', module_name)], {}) |
361 | + assert len(module_ids) == 1 |
362 | + ir_module_module.button_install(cr, SUPERUSER_ID, module_ids, {}) |
363 | + cr.commit() |
364 | + cr.close() |
365 | + reload_registry() |
366 | + |
367 | +def uninstall_module(module_name): |
368 | + ir_module_module = registry('ir.module.module') |
369 | + cr = cursor() |
370 | + module_ids = ir_module_module.search(cr, SUPERUSER_ID, |
371 | + [('name', '=', module_name)], {}) |
372 | + assert len(module_ids) == 1 |
373 | + ir_module_module.button_uninstall(cr, SUPERUSER_ID, module_ids, {}) |
374 | + cr.commit() |
375 | + cr.close() |
376 | + reload_registry() |
377 | + |
378 | +class test_uninstall(unittest2.TestCase): |
379 | + """ |
380 | + Test the install/uninstall of a test module. The module is available in |
381 | + `openerp.tests` which should be present in the addons-path. |
382 | + """ |
383 | + |
384 | + def test_01_install(self): |
385 | + """ Check a few things showing the module is installed. """ |
386 | + install_module('test_uninstall') |
387 | + assert model_exists('test_uninstall.model') |
388 | + |
389 | + assert search_registry('ir.model.data', |
390 | + [('module', '=', 'test_uninstall')]) |
391 | + |
392 | + assert search_registry('ir.model.fields', |
393 | + [('model', '=', 'test_uninstall.model')]) |
394 | + |
395 | + def test_02_uninstall(self): |
396 | + """ Check a few things showing the module is uninstalled. """ |
397 | + uninstall_module('test_uninstall') |
398 | + assert not model_exists('test_uninstall.model') |
399 | + |
400 | + assert not search_registry('ir.model.data', |
401 | + [('module', '=', 'test_uninstall')]) |
402 | + |
403 | + assert not search_registry('ir.model.fields', |
404 | + [('model', '=', 'test_uninstall.model')]) |
405 | + |
406 | + |
407 | + |
408 | +if __name__ == '__main__': |
409 | + unittest2.main() |
410 | + |
411 | + |
412 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
413 | |
414 | === renamed file 'openerp/tests/test_view_validation.py' => 'openerp/addons/base/tests/test_view_validation.py' |
415 | === renamed file 'openerp/tests/test_xmlrpc.py' => 'openerp/addons/base/tests/test_xmlrpc.py' |
416 | --- openerp/tests/test_xmlrpc.py 2013-10-06 10:21:31 +0000 |
417 | +++ openerp/addons/base/tests/test_xmlrpc.py 2014-02-03 01:51:54 +0000 |
418 | @@ -1,65 +1,29 @@ |
419 | # -*- coding: utf-8 -*- |
420 | -# Run with one of these commands: |
421 | -# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ |
422 | -# OPENERP_DATABASE=yy PYTHONPATH=. python tests/test_xmlrpc.py |
423 | -# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ |
424 | -# OPENERP_DATABASE=yy nosetests tests/test_xmlrpc.py |
425 | -# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \ |
426 | -# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_xmlrpc |
427 | import time |
428 | import unittest2 |
429 | import xmlrpclib |
430 | |
431 | -import common |
432 | +from openerp.tests import common |
433 | |
434 | -DB = None |
435 | +DB = common.DB |
436 | ADMIN_USER = common.ADMIN_USER |
437 | ADMIN_USER_ID = common.ADMIN_USER_ID |
438 | ADMIN_PASSWORD = common.ADMIN_PASSWORD |
439 | |
440 | -def setUpModule(): |
441 | - common.start_openerp() |
442 | - global DB |
443 | - DB = common.RpcCase.generate_database_name() |
444 | - |
445 | -tearDownModule = common.stop_openerp |
446 | - |
447 | -class test_xmlrpc(common.RpcCase): |
448 | - |
449 | - def test_00_xmlrpc_create_database_polling(self): |
450 | - """ |
451 | - Simulate a OpenERP client requesting the creation of a database and |
452 | - polling the server until the creation is complete. |
453 | - """ |
454 | - progress_id = self.proxy.db_60.create(ADMIN_PASSWORD,DB, True, False, |
455 | - ADMIN_PASSWORD) |
456 | - while True: |
457 | - time.sleep(1) |
458 | - progress, users = self.proxy.db_60.get_progress(ADMIN_PASSWORD, |
459 | - progress_id) |
460 | - if progress == 1.0: |
461 | - break |
462 | - |
463 | - def test_xmlrpc_login(self): |
464 | +class test_xmlrpc(common.HttpCase): |
465 | + |
466 | + def test_01_xmlrpc_login(self): |
467 | """ Try to login on the common service. """ |
468 | - uid = self.proxy.common_60.login(DB, ADMIN_USER, ADMIN_PASSWORD) |
469 | - assert uid == ADMIN_USER_ID |
470 | + uid = self.xmlrpc_common.login(DB, ADMIN_USER, ADMIN_PASSWORD) |
471 | + self.assertTrue(uid == ADMIN_USER_ID) |
472 | |
473 | def test_xmlrpc_ir_model_search(self): |
474 | """ Try a search on the object service. """ |
475 | - o = self.proxy.object_60 |
476 | - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) |
477 | - assert ids |
478 | - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) |
479 | - assert ids |
480 | - |
481 | - def test_xmlrpc_8_ir_model_search(self): |
482 | - """ Try a search on the object service. """ |
483 | - o = self.proxy.object_8 |
484 | - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) |
485 | - assert ids |
486 | - ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) |
487 | - assert ids |
488 | + o = self.xmlrpc_object |
489 | + ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) |
490 | + self.assertIsInstance(ids, list) |
491 | + ids = o.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) |
492 | + self.assertIsInstance(ids, list) |
493 | |
494 | # This test was written to test the creation of a new RPC endpoint, not |
495 | # really for the EDI itself. |
496 | @@ -69,12 +33,6 @@ |
497 | # with self.assertRaisesRegexp(Exception, msg_re): |
498 | # self.proxy.edi_60.import_edi_document(DB, ADMIN_USER_ID, ADMIN_PASSWORD, {}) |
499 | |
500 | - def test_zz_xmlrpc_drop_database(self): |
501 | - """ |
502 | - Simulate a OpenERP client requesting the deletion of a database. |
503 | - """ |
504 | - assert self.proxy.db_60.drop(ADMIN_PASSWORD, DB) is True |
505 | - |
506 | if __name__ == '__main__': |
507 | unittest2.main() |
508 | |
509 | |
510 | === renamed directory 'openerp/tests/addons/test_convert' => 'openerp/addons/test_convert' |
511 | === renamed directory 'openerp/tests/addons/test_converter' => 'openerp/addons/test_converter' |
512 | === renamed directory 'openerp/tests/addons/test_exceptions' => 'openerp/addons/test_exceptions' |
513 | === renamed directory 'openerp/tests/addons/test_impex' => 'openerp/addons/test_impex' |
514 | === renamed directory 'openerp/tests/addons/test_limits' => 'openerp/addons/test_limits' |
515 | === renamed directory 'openerp/tests/addons/test_uninstall' => 'openerp/addons/test_uninstall' |
516 | === renamed directory 'openerp/tests/addons/test_workflow' => 'openerp/addons/test_workflow' |
517 | === modified file 'openerp/cli/server.py' |
518 | --- openerp/cli/server.py 2014-01-09 09:32:58 +0000 |
519 | +++ openerp/cli/server.py 2014-02-03 01:51:54 +0000 |
520 | @@ -89,16 +89,6 @@ |
521 | pidtext = "%d" % (os.getpid()) |
522 | fd.write(pidtext) |
523 | |
524 | -def preload_registry(dbname): |
525 | - """ Preload a registry, and start the cron.""" |
526 | - try: |
527 | - update_module = True if openerp.tools.config['init'] or openerp.tools.config['update'] else False |
528 | - registry = openerp.modules.registry.RegistryManager.new(dbname, update_module=update_module) |
529 | - except Exception: |
530 | - _logger.exception('Failed to initialize database `%s`.', dbname) |
531 | - return False |
532 | - return registry._assertion_report.failures == 0 |
533 | - |
534 | def run_test_file(dbname, test_file): |
535 | """ Preload a registry, possibly run a test file, and start the cron.""" |
536 | try: |
537 | @@ -172,23 +162,17 @@ |
538 | if config['workers']: |
539 | openerp.multi_process = True |
540 | |
541 | - # preload registries, needed for -u --stop_after_init |
542 | - rc = 0 |
543 | + preload = [] |
544 | if config['db_name']: |
545 | - for dbname in config['db_name'].split(','): |
546 | - if not preload_registry(dbname): |
547 | - rc += 1 |
548 | - |
549 | - if not config["stop_after_init"]: |
550 | - setup_pid_file() |
551 | - openerp.service.server.start() |
552 | - if config['pidfile']: |
553 | - os.unlink(config['pidfile']) |
554 | - else: |
555 | - sys.exit(rc) |
556 | - |
557 | - _logger.info('OpenERP server is running, waiting for connections...') |
558 | - quit_on_signals() |
559 | + preload = config['db_name'].split(',') |
560 | + |
561 | + stop = config["stop_after_init"] |
562 | + |
563 | + setup_pid_file() |
564 | + rc = openerp.service.server.start(preload=preload, stop=stop) |
565 | + if config['pidfile']: |
566 | + os.unlink(config['pidfile']) |
567 | + sys.exit(rc) |
568 | |
569 | class Server(Command): |
570 | def run(self, args): |
571 | |
572 | === modified file 'openerp/http.py' |
573 | --- openerp/http.py 2014-01-31 10:48:40 +0000 |
574 | +++ openerp/http.py 2014-02-03 01:51:54 +0000 |
575 | @@ -168,7 +168,10 @@ |
576 | """ |
577 | # some magic to lazy create the cr |
578 | if not self._cr: |
579 | - self._cr = self.registry.db.cursor() |
580 | + if openerp.tools.config['test_enable'] and self.session_id in openerp.tests.common.HTTP_SESSION: |
581 | + self._cr = openerp.tests.common.HTTP_SESSION[self.session_id] |
582 | + else: |
583 | + self._cr = self.registry.db.cursor() |
584 | return self._cr |
585 | |
586 | def __enter__(self): |
587 | @@ -177,7 +180,7 @@ |
588 | |
589 | def __exit__(self, exc_type, exc_value, traceback): |
590 | _request_stack.pop() |
591 | - if self._cr: |
592 | + if self._cr and not (openerp.tools.config['test_enable'] and self.session_id in openerp.tests.common.HTTP_SESSION): |
593 | if exc_type is None: |
594 | self._cr.commit() |
595 | self._cr.close() |
596 | |
597 | === modified file 'openerp/modules/__init__.py' |
598 | --- openerp/modules/__init__.py 2012-08-24 14:23:23 +0000 |
599 | +++ openerp/modules/__init__.py 2014-02-03 01:51:54 +0000 |
600 | @@ -26,16 +26,10 @@ |
601 | |
602 | from . import db, graph, loading, migration, module, registry |
603 | |
604 | -# TODO temporarily expose those things |
605 | -from openerp.modules.module import \ |
606 | - get_modules, get_modules_with_version, \ |
607 | - load_information_from_description_file, \ |
608 | - get_module_resource, zip_directory, \ |
609 | - get_module_path, initialize_sys_path, \ |
610 | - load_openerp_module, init_module_models, \ |
611 | - adapt_version |
612 | - |
613 | from openerp.modules.loading import load_modules |
614 | |
615 | +from openerp.modules.module import get_modules, get_modules_with_version, \ |
616 | + load_information_from_description_file, get_module_resource, get_module_path, \ |
617 | + initialize_sys_path, load_openerp_module, init_module_models, adapt_version |
618 | |
619 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
620 | |
621 | === modified file 'openerp/modules/loading.py' |
622 | --- openerp/modules/loading.py 2014-01-30 15:38:35 +0000 |
623 | +++ openerp/modules/loading.py 2014-02-03 01:51:54 +0000 |
624 | @@ -182,18 +182,12 @@ |
625 | migrations.migrate_module(package, 'post') |
626 | |
627 | if has_demo: |
628 | - # launch tests only in demo mode, as most tests will depend |
629 | - # on demo data. Other tests can be added into the regular |
630 | - # 'data' section, but should probably not alter the data, |
631 | - # as there is no rollback. |
632 | + # launch tests only in demo mode, allowing tests to use demo data. |
633 | if tools.config.options['test_enable']: |
634 | + # Yamel test |
635 | report.record_result(load_test(module_name, idref, mode)) |
636 | - |
637 | - # Run the `fast_suite` and `checks` tests given by the module. |
638 | - if module_name == 'base': |
639 | - # Also run the core tests after the database is created. |
640 | - report.record_result(openerp.modules.module.run_unit_tests('openerp')) |
641 | - report.record_result(openerp.modules.module.run_unit_tests(module_name)) |
642 | + # Python tests |
643 | + report.record_result(openerp.modules.module.run_unit_tests(module_name, cr.dbname)) |
644 | |
645 | processed_modules.append(package.name) |
646 | |
647 | @@ -247,7 +241,6 @@ |
648 | if not processed: break |
649 | return processed_modules |
650 | |
651 | - |
652 | def load_modules(db, force_demo=False, status=None, update_module=False): |
653 | # TODO status['progress'] reporting is broken: used twice (and reset each |
654 | # time to zero) in load_module_graph, not fine-grained enough. |
655 | |
656 | === modified file 'openerp/modules/module.py' |
657 | --- openerp/modules/module.py 2013-06-28 15:07:55 +0000 |
658 | +++ openerp/modules/module.py 2014-02-03 01:51:54 +0000 |
659 | @@ -20,32 +20,31 @@ |
660 | # |
661 | ############################################################################## |
662 | |
663 | +import base64 |
664 | import imp |
665 | import itertools |
666 | +import logging |
667 | import os |
668 | -from os.path import join as opj |
669 | +import re |
670 | import sys |
671 | import types |
672 | -import zipimport |
673 | - |
674 | +from cStringIO import StringIO |
675 | +from os.path import join as opj |
676 | + |
677 | +import unittest2 |
678 | + |
679 | +import openerp |
680 | import openerp.tools as tools |
681 | -import openerp.tools.osutil as osutil |
682 | +import openerp.release as release |
683 | from openerp.tools.safe_eval import safe_eval as eval |
684 | |
685 | -import zipfile |
686 | -import openerp.release as release |
687 | - |
688 | -import re |
689 | -import base64 |
690 | -from zipfile import PyZipFile, ZIP_DEFLATED |
691 | -from cStringIO import StringIO |
692 | - |
693 | -import logging |
694 | - |
695 | _logger = logging.getLogger(__name__) |
696 | _test_logger = logging.getLogger('openerp.tests') |
697 | |
698 | +# addons path ','.joined |
699 | _ad = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons') # default addons path (base) |
700 | + |
701 | +# addons path as a list |
702 | ad_paths = [] |
703 | |
704 | # Modules already loaded |
705 | @@ -120,7 +119,6 @@ |
706 | _logger.warning('module %s: module not found', module) |
707 | return False |
708 | |
709 | - |
710 | def get_module_filetree(module, dir='.'): |
711 | path = get_module_path(module) |
712 | if not path: |
713 | @@ -132,12 +130,7 @@ |
714 | if dir.startswith('..') or (dir and dir[0] == '/'): |
715 | raise Exception('Cannot access file outside the module') |
716 | |
717 | - if not os.path.isdir(path): |
718 | - # zipmodule |
719 | - zip = zipfile.ZipFile(path + ".zip") |
720 | - files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()] |
721 | - else: |
722 | - files = osutil.listdir(path, True) |
723 | + files = openerp.tools.osutil.listdir(path, True) |
724 | |
725 | tree = {} |
726 | for f in files: |
727 | @@ -154,68 +147,6 @@ |
728 | |
729 | return tree |
730 | |
731 | -def zip_directory(directory, b64enc=True, src=True): |
732 | - """Compress a directory |
733 | - |
734 | - @param directory: The directory to compress |
735 | - @param base64enc: if True the function will encode the zip file with base64 |
736 | - @param src: Integrate the source files |
737 | - |
738 | - @return: a string containing the zip file |
739 | - """ |
740 | - |
741 | - RE_exclude = re.compile('(?:^\..+\.swp$)|(?:\.py[oc]$)|(?:\.bak$)|(?:\.~.~$)', re.I) |
742 | - |
743 | - def _zippy(archive, path, src=True): |
744 | - path = os.path.abspath(path) |
745 | - base = os.path.basename(path) |
746 | - for f in osutil.listdir(path, True): |
747 | - bf = os.path.basename(f) |
748 | - if not RE_exclude.search(bf) and (src or bf == '__openerp__.py' or not bf.endswith('.py')): |
749 | - archive.write(os.path.join(path, f), os.path.join(base, f)) |
750 | - |
751 | - archname = StringIO() |
752 | - archive = PyZipFile(archname, "w", ZIP_DEFLATED) |
753 | - |
754 | - # for Python 2.5, ZipFile.write() still expects 8-bit strings (2.6 converts to utf-8) |
755 | - directory = tools.ustr(directory).encode('utf-8') |
756 | - |
757 | - archive.writepy(directory) |
758 | - _zippy(archive, directory, src=src) |
759 | - archive.close() |
760 | - archive_data = archname.getvalue() |
761 | - archname.close() |
762 | - |
763 | - if b64enc: |
764 | - return base64.encodestring(archive_data) |
765 | - |
766 | - return archive_data |
767 | - |
768 | -def get_module_as_zip(modulename, b64enc=True, src=True): |
769 | - """Generate a module as zip file with the source or not and can do a base64 encoding |
770 | - |
771 | - @param modulename: The module name |
772 | - @param b64enc: if True the function will encode the zip file with base64 |
773 | - @param src: Integrate the source files |
774 | - |
775 | - @return: a stream to store in a file-like object |
776 | - """ |
777 | - |
778 | - ap = get_module_path(str(modulename)) |
779 | - if not ap: |
780 | - raise Exception('Unable to find path for module %s' % modulename) |
781 | - |
782 | - ap = ap.encode('utf8') |
783 | - if os.path.isfile(ap + '.zip'): |
784 | - val = file(ap + '.zip', 'rb').read() |
785 | - if b64enc: |
786 | - val = base64.encodestring(val) |
787 | - else: |
788 | - val = zip_directory(ap, b64enc, src) |
789 | - |
790 | - return val |
791 | - |
792 | - |
793 | def get_module_resource(module, *args): |
794 | """Return the full path of a resource of the given module. |
795 | |
796 | @@ -235,12 +166,6 @@ |
797 | # the module is a directory - ignore zip behavior |
798 | if os.path.exists(resource_path): |
799 | return resource_path |
800 | - elif zipfile.is_zipfile(mod_path + '.zip'): |
801 | - zip = zipfile.ZipFile( mod_path + ".zip") |
802 | - files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()] |
803 | - resource_path = '/'.join(args) |
804 | - if resource_path in files: |
805 | - return opj(mod_path, resource_path) |
806 | return False |
807 | |
808 | def get_module_icon(module): |
809 | @@ -258,7 +183,7 @@ |
810 | mod_path = get_module_path(module) |
811 | if terp_file: |
812 | info = {} |
813 | - if os.path.isfile(terp_file) or zipfile.is_zipfile(mod_path+'.zip'): |
814 | + if os.path.isfile(terp_file): |
815 | # default values for descriptor |
816 | info = { |
817 | 'application': False, |
818 | @@ -300,7 +225,6 @@ |
819 | _logger.debug('module %s: no __openerp__.py file found.', module) |
820 | return {} |
821 | |
822 | - |
823 | def init_module_models(cr, module_name, obj_list): |
824 | """ Initialize a list of models. |
825 | |
826 | @@ -342,12 +266,7 @@ |
827 | initialize_sys_path() |
828 | try: |
829 | mod_path = get_module_path(module_name) |
830 | - zip_mod_path = '' if not mod_path else mod_path + '.zip' |
831 | - if not os.path.isfile(zip_mod_path): |
832 | - __import__('openerp.addons.' + module_name) |
833 | - else: |
834 | - zimp = zipimport.zipimporter(zip_mod_path) |
835 | - zimp.load_module(module_name) |
836 | + __import__('openerp.addons.' + module_name) |
837 | |
838 | # Call the module's post-load hook. This can done before any model or |
839 | # data has been initialized. This is ok as the post-load hook is for |
840 | @@ -357,8 +276,7 @@ |
841 | getattr(sys.modules['openerp.addons.' + module_name], info['post_load'])() |
842 | |
843 | except Exception, e: |
844 | - mt = isinstance(e, zipimport.ZipImportError) and 'zip ' or '' |
845 | - msg = "Couldn't load %smodule %s" % (mt, module_name) |
846 | + msg = "Couldn't load module %s" % (module_name) |
847 | _logger.critical(msg) |
848 | _logger.critical(e) |
849 | raise |
850 | @@ -378,7 +296,7 @@ |
851 | def is_really_module(name): |
852 | manifest_name = opj(dir, name, '__openerp__.py') |
853 | zipfile_name = opj(dir, name) |
854 | - return os.path.isfile(manifest_name) or zipfile.is_zipfile(zipfile_name) |
855 | + return os.path.isfile(manifest_name) |
856 | return map(clean, filter(is_really_module, os.listdir(dir))) |
857 | |
858 | plist = [] |
859 | @@ -387,7 +305,6 @@ |
860 | plist.extend(listdir(ad)) |
861 | return list(set(plist)) |
862 | |
863 | - |
864 | def get_modules_with_version(): |
865 | modules = get_modules() |
866 | res = dict.fromkeys(modules, adapt_version('1.0')) |
867 | @@ -405,126 +322,58 @@ |
868 | version = '%s.%s' % (serie, version) |
869 | return version |
870 | |
871 | - |
872 | -def get_test_modules(module, submodule, explode): |
873 | - """ |
874 | - Return a list of submodules containing tests. |
875 | - `submodule` can be: |
876 | - - None |
877 | - - the name of a submodule |
878 | - - '__fast_suite__' |
879 | - - '__sanity_checks__' |
880 | - """ |
881 | - # Turn command-line module, submodule into importable names. |
882 | - if module is None: |
883 | +def get_test_modules(module): |
884 | + """ Return a list of module for the addons potentialy containing tests to |
885 | + feed unittest2.TestLoader.loadTestsFromModule() """ |
886 | + # Try to import the module |
887 | + module = 'openerp.addons.' + module + '.tests' |
888 | + try: |
889 | + m = __import__(module) |
890 | + except Exception, e: |
891 | + # If module has no `tests` sub-module, no problem. |
892 | + if str(e) != 'No module named tests': |
893 | + _logger.exception('Can not `import %s`.', module) |
894 | + return [] |
895 | + |
896 | + # include submodules too |
897 | + result = [] |
898 | + for name in sys.modules: |
899 | + if name.startswith(module) and sys.modules[name]: |
900 | + result.append(sys.modules[name]) |
901 | + return result |
902 | + |
903 | +# Use a custom stream object to log the test executions. |
904 | +class TestStream(object): |
905 | + def __init__(self): |
906 | + self.r = re.compile(r'^-*$|^ *... *$|^ok$') |
907 | + def flush(self): |
908 | pass |
909 | - elif module == 'openerp': |
910 | - module = 'openerp.tests' |
911 | - else: |
912 | - module = 'openerp.addons.' + module + '.tests' |
913 | - |
914 | - # Try to import the module |
915 | - try: |
916 | - __import__(module) |
917 | - except Exception, e: |
918 | - if explode: |
919 | - print 'Can not `import %s`.' % module |
920 | - import logging |
921 | - logging.exception('') |
922 | - sys.exit(1) |
923 | - else: |
924 | - if str(e) == 'No module named tests': |
925 | - # It seems the module has no `tests` sub-module, no problem. |
926 | - pass |
927 | - else: |
928 | - _logger.exception('Can not `import %s`.', module) |
929 | - return [] |
930 | - |
931 | - # Discover available test sub-modules. |
932 | - m = sys.modules[module] |
933 | - submodule_names = sorted([x for x in dir(m) \ |
934 | - if x.startswith('test_') and \ |
935 | - isinstance(getattr(m, x), types.ModuleType)]) |
936 | - submodules = [getattr(m, x) for x in submodule_names] |
937 | - |
938 | - def show_submodules_and_exit(): |
939 | - if submodule_names: |
940 | - print 'Available submodules are:' |
941 | - for x in submodule_names: |
942 | - print ' ', x |
943 | - sys.exit(1) |
944 | - |
945 | - if submodule is None: |
946 | - # Use auto-discovered sub-modules. |
947 | - ms = submodules |
948 | - elif submodule == '__fast_suite__': |
949 | - # Obtain the explicit test sub-modules list. |
950 | - ms = getattr(sys.modules[module], 'fast_suite', None) |
951 | - # `suite` was used before the 6.1 release instead of `fast_suite`. |
952 | - ms = ms if ms else getattr(sys.modules[module], 'suite', None) |
953 | - if ms is None: |
954 | - if explode: |
955 | - print 'The module `%s` has no defined test suite.' % (module,) |
956 | - show_submodules_and_exit() |
957 | - else: |
958 | - ms = [] |
959 | - elif submodule == '__sanity_checks__': |
960 | - ms = getattr(sys.modules[module], 'checks', None) |
961 | - if ms is None: |
962 | - if explode: |
963 | - print 'The module `%s` has no defined sanity checks.' % (module,) |
964 | - show_submodules_and_exit() |
965 | - else: |
966 | - ms = [] |
967 | - else: |
968 | - # Pick the command-line-specified test sub-module. |
969 | - m = getattr(sys.modules[module], submodule, None) |
970 | - ms = [m] |
971 | - |
972 | - if m is None: |
973 | - if explode: |
974 | - print 'The module `%s` has no submodule named `%s`.' % \ |
975 | - (module, submodule) |
976 | - show_submodules_and_exit() |
977 | - else: |
978 | - ms = [] |
979 | - |
980 | - return ms |
981 | - |
982 | -def run_unit_tests(module_name): |
983 | + def write(self, s): |
984 | + if self.r.match(s): |
985 | + return |
986 | + first = True |
987 | + for c in s.split('\n'): |
988 | + if not first: |
989 | + c = '` ' + c |
990 | + first = False |
991 | + _test_logger.info(c) |
992 | + |
993 | +def run_unit_tests(module_name, dbname): |
994 | """ |
995 | Return True or False if some tests were found and succeeded or failed. |
996 | Return None if no test was found. |
997 | """ |
998 | - import unittest2 |
999 | - ms = get_test_modules(module_name, '__fast_suite__', explode=False) |
1000 | - # TODO: No need to try again if the above call failed because of e.g. a syntax error. |
1001 | - ms.extend(get_test_modules(module_name, '__sanity_checks__', explode=False)) |
1002 | - suite = unittest2.TestSuite() |
1003 | - for m in ms: |
1004 | - suite.addTests(unittest2.TestLoader().loadTestsFromModule(m)) |
1005 | - if ms: |
1006 | - _test_logger.info('module %s: executing %s `fast_suite` and/or `checks` sub-modules', module_name, len(ms)) |
1007 | - # Use a custom stream object to log the test executions. |
1008 | - class MyStream(object): |
1009 | - def __init__(self): |
1010 | - self.r = re.compile(r'^-*$|^ *... *$|^ok$') |
1011 | - def flush(self): |
1012 | - pass |
1013 | - def write(self, s): |
1014 | - if self.r.match(s): |
1015 | - return |
1016 | - first = True |
1017 | - for c in s.split('\n'): |
1018 | - if not first: |
1019 | - c = '` ' + c |
1020 | - first = False |
1021 | - _test_logger.info(c) |
1022 | - result = unittest2.TextTestRunner(verbosity=2, stream=MyStream()).run(suite) |
1023 | - if result.wasSuccessful(): |
1024 | - return True |
1025 | - else: |
1026 | + mods = get_test_modules(module_name) |
1027 | + r = True |
1028 | + for m in mods: |
1029 | + suite = unittest2.TestSuite() |
1030 | + for t in unittest2.TestLoader().loadTestsFromModule(m): |
1031 | + suite.addTest(t) |
1032 | + _logger.log(logging.INFO, 'module %s: running test %s.', module_name, m.__name__) |
1033 | + result = unittest2.TextTestRunner(verbosity=2, stream=TestStream()).run(suite) |
1034 | + if not result.wasSuccessful(): |
1035 | + r = False |
1036 | _logger.error('module %s: at least one error occurred in a test', module_name) |
1037 | - return False |
1038 | + return r |
1039 | |
1040 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1041 | |
1042 | === modified file 'openerp/modules/registry.py' |
1043 | --- openerp/modules/registry.py 2014-01-21 17:27:37 +0000 |
1044 | +++ openerp/modules/registry.py 2014-02-03 01:51:54 +0000 |
1045 | @@ -63,6 +63,9 @@ |
1046 | # Indicates that the registry is |
1047 | self.ready = False |
1048 | |
1049 | + # http tests to be run when server is running |
1050 | + self.test_http = [] |
1051 | + |
1052 | # Inter-process signaling (used only when openerp.multi_process is True): |
1053 | # The `base_registry_signaling` sequence indicates the whole registry |
1054 | # must be reloaded. |
1055 | @@ -82,10 +85,6 @@ |
1056 | self.has_unaccent = openerp.tools.config['unaccent'] and has_unaccent |
1057 | cr.close() |
1058 | |
1059 | - # |
1060 | - # Mapping abstract methods implementation |
1061 | - # => mixin provides methods keys, items, values, get, __eq__, and __ne__ |
1062 | - # |
1063 | def __len__(self): |
1064 | """ Return the size of the registry. """ |
1065 | return len(self.models) |
1066 | @@ -147,7 +146,6 @@ |
1067 | if ir_ui_menu: |
1068 | ir_ui_menu.clear_cache() |
1069 | |
1070 | - |
1071 | # Useful only in a multi-process context. |
1072 | def reset_any_cache_cleared(self): |
1073 | self._any_cache_cleared = False |
1074 | @@ -204,21 +202,19 @@ |
1075 | # Mapping between db name and model registry. |
1076 | # Accessed through the methods below. |
1077 | registries = {} |
1078 | - registries_lock = threading.RLock() |
1079 | |
1080 | @classmethod |
1081 | def get(cls, db_name, force_demo=False, status=None, update_module=False): |
1082 | """ Return a registry for a given database name.""" |
1083 | - with cls.registries_lock: |
1084 | - try: |
1085 | - return cls.registries[db_name] |
1086 | - except KeyError: |
1087 | - return cls.new(db_name, force_demo, status, |
1088 | - update_module) |
1089 | - finally: |
1090 | - # set db tracker - cleaned up at the WSGI |
1091 | - # dispatching phase in openerp.service.wsgi_server.application |
1092 | - threading.current_thread().dbname = db_name |
1093 | + try: |
1094 | + return cls.registries[db_name] |
1095 | + except KeyError: |
1096 | + return cls.new(db_name, force_demo, status, |
1097 | + update_module) |
1098 | + finally: |
1099 | + # set db tracker - cleaned up at the WSGI |
1100 | + # dispatching phase in openerp.service.wsgi_server.application |
1101 | + threading.current_thread().dbname = db_name |
1102 | |
1103 | @classmethod |
1104 | def new(cls, db_name, force_demo=False, status=None, |
1105 | @@ -229,37 +225,36 @@ |
1106 | |
1107 | """ |
1108 | import openerp.modules |
1109 | - with cls.registries_lock: |
1110 | - registry = Registry(db_name) |
1111 | - |
1112 | - # Initializing a registry will call general code which will in turn |
1113 | - # call registries.get (this object) to obtain the registry being |
1114 | - # initialized. Make it available in the registries dictionary then |
1115 | - # remove it if an exception is raised. |
1116 | - cls.delete(db_name) |
1117 | - cls.registries[db_name] = registry |
1118 | - try: |
1119 | - with registry.cursor() as cr: |
1120 | - seq_registry, seq_cache = Registry.setup_multi_process_signaling(cr) |
1121 | - registry.base_registry_signaling_sequence = seq_registry |
1122 | - registry.base_cache_signaling_sequence = seq_cache |
1123 | - # This should be a method on Registry |
1124 | - openerp.modules.load_modules(registry.db, force_demo, status, update_module) |
1125 | - except Exception: |
1126 | - del cls.registries[db_name] |
1127 | - raise |
1128 | - |
1129 | - # load_modules() above can replace the registry by calling |
1130 | - # indirectly new() again (when modules have to be uninstalled). |
1131 | - # Yeah, crazy. |
1132 | - registry = cls.registries[db_name] |
1133 | - |
1134 | - cr = registry.db.cursor() |
1135 | - try: |
1136 | - registry.do_parent_store(cr) |
1137 | - cr.commit() |
1138 | - finally: |
1139 | - cr.close() |
1140 | + registry = Registry(db_name) |
1141 | + |
1142 | + # Initializing a registry will call general code which will in turn |
1143 | + # call registries.get (this object) to obtain the registry being |
1144 | + # initialized. Make it available in the registries dictionary then |
1145 | + # remove it if an exception is raised. |
1146 | + cls.delete(db_name) |
1147 | + cls.registries[db_name] = registry |
1148 | + try: |
1149 | + with registry.cursor() as cr: |
1150 | + seq_registry, seq_cache = Registry.setup_multi_process_signaling(cr) |
1151 | + registry.base_registry_signaling_sequence = seq_registry |
1152 | + registry.base_cache_signaling_sequence = seq_cache |
1153 | + # This should be a method on Registry |
1154 | + openerp.modules.load_modules(registry.db, force_demo, status, update_module) |
1155 | + except Exception: |
1156 | + del cls.registries[db_name] |
1157 | + raise |
1158 | + |
1159 | + # load_modules() above can replace the registry by calling |
1160 | + # indirectly new() again (when modules have to be uninstalled). |
1161 | + # Yeah, crazy. |
1162 | + registry = cls.registries[db_name] |
1163 | + |
1164 | + cr = registry.db.cursor() |
1165 | + try: |
1166 | + registry.do_parent_store(cr) |
1167 | + cr.commit() |
1168 | + finally: |
1169 | + cr.close() |
1170 | |
1171 | registry.ready = True |
1172 | |
1173 | @@ -271,17 +266,14 @@ |
1174 | @classmethod |
1175 | def delete(cls, db_name): |
1176 | """Delete the registry linked to a given database. """ |
1177 | - with cls.registries_lock: |
1178 | - if db_name in cls.registries: |
1179 | - cls.registries[db_name].clear_caches() |
1180 | - del cls.registries[db_name] |
1181 | + if db_name in cls.registries: |
1182 | + del cls.registries[db_name] |
1183 | |
1184 | @classmethod |
1185 | def delete_all(cls): |
1186 | """Delete all the registries. """ |
1187 | - with cls.registries_lock: |
1188 | - for db_name in cls.registries.keys(): |
1189 | - cls.delete(db_name) |
1190 | + for db_name in cls.registries.keys(): |
1191 | + cls.delete(db_name) |
1192 | |
1193 | @classmethod |
1194 | def clear_caches(cls, db_name): |
1195 | @@ -294,9 +286,8 @@ |
1196 | This method is given to spare you a ``RegistryManager.get(db_name)`` |
1197 | that would loads the given database if it was not already loaded. |
1198 | """ |
1199 | - with cls.registries_lock: |
1200 | - if db_name in cls.registries: |
1201 | - cls.registries[db_name].clear_caches() |
1202 | + if db_name in cls.registries: |
1203 | + cls.registries[db_name].clear_caches() |
1204 | |
1205 | @classmethod |
1206 | def check_registry_signaling(cls, db_name): |
1207 | |
1208 | === modified file 'openerp/service/model.py' |
1209 | --- openerp/service/model.py 2014-01-09 09:32:58 +0000 |
1210 | +++ openerp/service/model.py 2014-02-03 01:51:54 +0000 |
1211 | @@ -107,8 +107,6 @@ |
1212 | tries = 0 |
1213 | while True: |
1214 | try: |
1215 | - if openerp.registry(dbname)._init: |
1216 | - raise openerp.exceptions.Warning('Currently, this database is not fully loaded and can not be used.') |
1217 | return f(dbname, *args, **kwargs) |
1218 | except OperationalError, e: |
1219 | # Automatically retry the typical transaction serialization errors |
1220 | |
1221 | === modified file 'openerp/service/server.py' |
1222 | --- openerp/service/server.py 2014-01-22 22:15:25 +0000 |
1223 | +++ openerp/service/server.py 2014-02-03 01:51:54 +0000 |
1224 | @@ -306,7 +306,7 @@ |
1225 | openerp.modules.registry.RegistryManager.delete_all() |
1226 | logging.shutdown() |
1227 | |
1228 | - def run(self): |
1229 | + def run(self, preload=None, stop=False): |
1230 | """ Start the http server and the cron thread then wait for a signal. |
1231 | |
1232 | The first SIGINT or SIGTERM signal will initiate a graceful shutdown while |
1233 | @@ -314,6 +314,13 @@ |
1234 | """ |
1235 | self.start() |
1236 | |
1237 | + preload_registries(preload) |
1238 | + |
1239 | + if stop: |
1240 | + self.stop() |
1241 | + return |
1242 | + |
1243 | + |
1244 | # Wait for a first signal to be handled. (time.sleep will be interrupted |
1245 | # by the signal handler.) The try/except is for the win32 case. |
1246 | try: |
1247 | @@ -362,7 +369,7 @@ |
1248 | self.httpd.stop() |
1249 | gevent.shutdown() |
1250 | |
1251 | - def run(self): |
1252 | + def run(self, preload, stop): |
1253 | self.start() |
1254 | self.stop() |
1255 | |
1256 | @@ -569,8 +576,15 @@ |
1257 | self.worker_kill(pid, signal.SIGTERM) |
1258 | self.socket.close() |
1259 | |
1260 | - def run(self): |
1261 | + def run(self, preload, stop): |
1262 | self.start() |
1263 | + |
1264 | + preload_registries(preload) |
1265 | + |
1266 | + if stop: |
1267 | + self.stop() |
1268 | + return |
1269 | + |
1270 | _logger.debug("Multiprocess starting") |
1271 | while 1: |
1272 | try: |
1273 | @@ -587,7 +601,7 @@ |
1274 | except Exception,e: |
1275 | _logger.exception(e) |
1276 | self.stop(False) |
1277 | - sys.exit(-1) |
1278 | + return -1 |
1279 | |
1280 | class Worker(object): |
1281 | """ Workers """ |
1282 | @@ -809,7 +823,21 @@ |
1283 | args.insert(0, exe) |
1284 | os.execv(sys.executable, args) |
1285 | |
1286 | -def start(): |
1287 | +def preload_registries(dbnames): |
1288 | + """ Preload a registries.""" |
1289 | + dbnames = dbnames or [] |
1290 | + for dbname in dbnames: |
1291 | + try: |
1292 | + update_module = openerp.tools.config['init'] or openerp.tools.config['update'] |
1293 | + registry = openerp.modules.registry.RegistryManager.new(dbname, update_module=update_module) |
1294 | + #if config['test_enable']: |
1295 | + # openerp.modules.module.run_http_test(config['db_name']) |
1296 | + #if registry._assertion_report.failures != 0: |
1297 | + except Exception: |
1298 | + _logger.exception('Failed to initialize database `%s`.', dbname) |
1299 | + return |
1300 | + |
1301 | +def start(preload=None, stop=False): |
1302 | """ Start the openerp http server and cron processor. |
1303 | """ |
1304 | global server |
1305 | @@ -825,7 +853,7 @@ |
1306 | autoreload = AutoReload(server) |
1307 | autoreload.run() |
1308 | |
1309 | - server.run() |
1310 | + rc = server.run(preload, stop) |
1311 | |
1312 | # like the legend of the phoenix, all ends with beginnings |
1313 | if getattr(openerp, 'phoenix', False): |
1314 | @@ -833,7 +861,8 @@ |
1315 | if config['auto_reload']: |
1316 | modules = autoreload.modules.keys() |
1317 | _reexec(modules) |
1318 | - sys.exit(0) |
1319 | + |
1320 | + return rc if rc else 0 |
1321 | |
1322 | def restart(): |
1323 | """ Restart the server |
1324 | |
1325 | === modified file 'openerp/sql_db.py' |
1326 | --- openerp/sql_db.py 2014-01-22 22:15:25 +0000 |
1327 | +++ openerp/sql_db.py 2014-02-03 01:51:54 +0000 |
1328 | @@ -282,6 +282,9 @@ |
1329 | return self._close(False) |
1330 | |
1331 | def _close(self, leak=False): |
1332 | + #import traceback |
1333 | + #traceback.print_stack() |
1334 | + |
1335 | if not self._obj: |
1336 | return |
1337 | |
1338 | |
1339 | === modified file 'openerp/tests/__init__.py' |
1340 | --- openerp/tests/__init__.py 2014-01-31 00:27:01 +0000 |
1341 | +++ openerp/tests/__init__.py 2014-02-03 01:51:54 +0000 |
1342 | @@ -7,43 +7,9 @@ |
1343 | Tests can be explicitely added to the `fast_suite` or `checks` lists or not. |
1344 | See the :ref:`test-framework` section in the :ref:`features` list. |
1345 | """ |
1346 | -import test_acl |
1347 | -import test_basecase |
1348 | -import test_db_cursor |
1349 | -import test_expression |
1350 | -import test_fields |
1351 | -import test_ir_filters |
1352 | -import test_ir_sequence |
1353 | -import test_mail |
1354 | -import test_misc |
1355 | -import test_orm |
1356 | -import test_osv |
1357 | -import test_translate |
1358 | -import test_view_validation |
1359 | -import test_qweb |
1360 | -import test_func |
1361 | -# This need a change in `oe run-tests` to only run fast_suite + checks by default. |
1362 | -# import test_xmlrpc |
1363 | - |
1364 | -fast_suite = [ |
1365 | - test_ir_sequence, |
1366 | - test_ir_filters |
1367 | -] |
1368 | - |
1369 | -checks = [ |
1370 | - test_acl, |
1371 | - test_expression, |
1372 | - test_mail, |
1373 | - test_db_cursor, |
1374 | - test_orm, |
1375 | - test_fields, |
1376 | - test_basecase, |
1377 | - test_view_validation, |
1378 | - test_misc, |
1379 | - test_osv, |
1380 | - test_translate, |
1381 | - test_qweb, |
1382 | - test_func, |
1383 | -] |
1384 | - |
1385 | + |
1386 | +import common |
1387 | +from common import * |
1388 | + |
1389 | + |
1390 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1391 | |
1392 | === removed directory 'openerp/tests/addons' |
1393 | === modified file 'openerp/tests/common.py' |
1394 | --- openerp/tests/common.py 2013-10-06 10:21:31 +0000 |
1395 | +++ openerp/tests/common.py 2014-02-03 01:51:54 +0000 |
1396 | @@ -3,15 +3,24 @@ |
1397 | The module :mod:`openerp.tests.common` provides a few helpers and classes to write |
1398 | tests. |
1399 | """ |
1400 | +import json |
1401 | +import os |
1402 | +import select |
1403 | +import subprocess |
1404 | import threading |
1405 | import time |
1406 | import unittest2 |
1407 | +import uuid |
1408 | import xmlrpclib |
1409 | +import logging |
1410 | |
1411 | import openerp |
1412 | |
1413 | +_logger = logging.getLogger(__name__) |
1414 | + |
1415 | # The openerp library is supposed already configured. |
1416 | ADDONS_PATH = openerp.tools.config['addons_path'] |
1417 | +HOST = '127.0.0.1' |
1418 | PORT = openerp.tools.config['xmlrpc_port'] |
1419 | DB = openerp.tools.config['db_name'] |
1420 | |
1421 | @@ -22,26 +31,11 @@ |
1422 | if not DB and hasattr(threading.current_thread(), 'dbname'): |
1423 | DB = threading.current_thread().dbname |
1424 | |
1425 | -HOST = '127.0.0.1' |
1426 | - |
1427 | ADMIN_USER = 'admin' |
1428 | ADMIN_USER_ID = openerp.SUPERUSER_ID |
1429 | ADMIN_PASSWORD = 'admin' |
1430 | |
1431 | -def start_openerp(): |
1432 | - """ |
1433 | - Start the OpenERP server similary to the openerp-server script. |
1434 | - """ |
1435 | - openerp.service.start_services() |
1436 | - |
1437 | - # Ugly way to ensure the server is listening. |
1438 | - time.sleep(2) |
1439 | - |
1440 | -def stop_openerp(): |
1441 | - """ |
1442 | - Shutdown the OpenERP server similarly to a single ctrl-c. |
1443 | - """ |
1444 | - openerp.service.stop_services() |
1445 | +HTTP_SESSION = {} |
1446 | |
1447 | class BaseCase(unittest2.TestCase): |
1448 | """ |
1449 | @@ -116,37 +110,106 @@ |
1450 | cls.cr.close() |
1451 | |
1452 | |
1453 | -class RpcCase(unittest2.TestCase): |
1454 | - """ |
1455 | - Subclass of TestCase with a few XML-RPC proxies. |
1456 | +class HttpCase(SingleTransactionCase): |
1457 | + """ Transactionnal HTTP TestCase with a phantomjs helper. |
1458 | """ |
1459 | |
1460 | def __init__(self, methodName='runTest'): |
1461 | - super(RpcCase, self).__init__(methodName) |
1462 | - |
1463 | - class A(object): |
1464 | - pass |
1465 | - self.proxy = A() |
1466 | - |
1467 | - # Use the old (pre 6.1) API. |
1468 | - self.proxy.url_60 = url_60 = 'http://%s:%d/xmlrpc/' % (HOST, PORT) |
1469 | - self.proxy.common_60 = xmlrpclib.ServerProxy(url_60 + 'common') |
1470 | - self.proxy.db_60 = xmlrpclib.ServerProxy(url_60 + 'db') |
1471 | - self.proxy.object_60 = xmlrpclib.ServerProxy(url_60 + 'object') |
1472 | - #self.proxy.edi_60 = xmlrpclib.ServerProxy(url_60 + 'edi') |
1473 | - |
1474 | - # Use the new (8) API. |
1475 | - self.proxy.url_8 = url_8 = 'http://%s:%d/xmlrpc/2/' % (HOST, PORT) |
1476 | - self.proxy.common_8 = xmlrpclib.ServerProxy(url_8 + 'common') |
1477 | - self.proxy.db_8 = xmlrpclib.ServerProxy(url_8 + 'db') |
1478 | - self.proxy.object_8 = xmlrpclib.ServerProxy(url_8 + 'object') |
1479 | - |
1480 | - @classmethod |
1481 | - def generate_database_name(cls): |
1482 | - if hasattr(cls, '_database_id'): |
1483 | - cls._database_id += 1 |
1484 | - else: |
1485 | - cls._database_id = 0 |
1486 | - return '_fresh_name_' + str(cls._database_id) + '_' |
1487 | + super(HttpCase, self).__init__(methodName) |
1488 | + # v8 api with correct xmlrpc exception handling. |
1489 | + self.xmlrpc_url = url_8 = 'http://%s:%d/xmlrpc/2/' % (HOST, PORT) |
1490 | + self.xmlrpc_common = xmlrpclib.ServerProxy(url_8 + 'common') |
1491 | + self.xmlrpc_db = xmlrpclib.ServerProxy(url_8 + 'db') |
1492 | + self.xmlrpc_object = xmlrpclib.ServerProxy(url_8 + 'object') |
1493 | + |
1494 | + @classmethod |
1495 | + def setUpClass(cls): |
1496 | + super(HttpCase, cls).setUpClass() |
1497 | + cls.session_id = uuid.uuid4().hex |
1498 | + HTTP_SESSION[cls.session_id] = cls.cr |
1499 | + |
1500 | + @classmethod |
1501 | + def tearDownClass(cls): |
1502 | + del HTTP_SESSION[cls.session_id] |
1503 | + super(HttpCase, cls).tearDownClass() |
1504 | + |
1505 | + def phantomjs(self, jsfile, timeout=30, options=None): |
1506 | + """ Phantomjs Test protocol. |
1507 | + |
1508 | + Use console.log in phantomjs to output test results evrey line must be |
1509 | + a one line JSON message using the following format: |
1510 | + |
1511 | + - for a success: { "event": "success", "message": "Log message" } |
1512 | + - for an error: { "event": "error", "message": "Short error description" } |
1513 | + |
1514 | + if a non json parsable line is received the helper will raise an |
1515 | + exception, the output buffer will be printed and phantom will be |
1516 | + killed |
1517 | + |
1518 | + """ |
1519 | + self.timeout = timeout |
1520 | + self.options = { |
1521 | + 'timeout' : timeout, |
1522 | + 'port': PORT, |
1523 | + 'db': DB, |
1524 | + 'user': ADMIN_USER, |
1525 | + 'password': ADMIN_PASSWORD, |
1526 | + 'session_id': self.session_id, |
1527 | + } |
1528 | + if options: |
1529 | + self.options.update(options) |
1530 | + |
1531 | + self.ignore_filters = [ |
1532 | + # Ignore phantomjs warnings |
1533 | + "*** WARNING:", |
1534 | + # Fixes an issue with PhantomJS 1.9.2 on OS X 10.9 (Mavericks) |
1535 | + # cf. https://github.com/ariya/phantomjs/issues/11418 |
1536 | + "CoreText performance note", |
1537 | + ] |
1538 | + |
1539 | + cmd = ['phantomjs', jsfile, json.dumps(self.options)] |
1540 | + _logger.info('executing %s', cmd) |
1541 | + try: |
1542 | + phantom = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
1543 | + except OSError: |
1544 | + _logger.info("phantomjs not found, test %s skipped", jsfile) |
1545 | + |
1546 | + try: |
1547 | + t0 = time.time() |
1548 | + buf = '' |
1549 | + while 1: |
1550 | + if time.time() > t0 + self.timeout: |
1551 | + raise Exception("Phantom js timeout (%ss)" % self.timeout) |
1552 | + |
1553 | + ready, _, _ = select.select([phantom.stdout], [], [], 0.5) |
1554 | + if ready: |
1555 | + s = phantom.stdout.read(4096) |
1556 | + if s: |
1557 | + buf += s |
1558 | + else: |
1559 | + break |
1560 | + |
1561 | + # process lines |
1562 | + if '\n' in buf: |
1563 | + line, buf = buf.split('\n', 1) |
1564 | + if line not in self.ignore_filters: |
1565 | + try: |
1566 | + line_json = json.loads(line) |
1567 | + if line_json.get('event') == 'success': |
1568 | + _logger.info(line_json.get('message','ok')) |
1569 | + continue |
1570 | + elif line_json.get('event') == 'error': |
1571 | + err = line_json.get('message','error') |
1572 | + _logger.info(err) |
1573 | + else: |
1574 | + err = line + buf |
1575 | + except ValueError: |
1576 | + err = line + buf |
1577 | + raise Exception(err) |
1578 | + finally: |
1579 | + # kill phantomjs if phantom.exit() wasn't called in the test |
1580 | + if phantom.poll() is None: |
1581 | + phantom.terminate() |
1582 | + |
1583 | |
1584 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1585 | |
1586 | === removed file 'openerp/tests/test_expression.py' |
1587 | --- openerp/tests/test_expression.py 2012-12-04 14:26:50 +0000 |
1588 | +++ openerp/tests/test_expression.py 1970-01-01 00:00:00 +0000 |
1589 | @@ -1,13 +0,0 @@ |
1590 | -import unittest2 |
1591 | - |
1592 | -import openerp |
1593 | - |
1594 | - |
1595 | -class test_domain_normalization(unittest2.TestCase): |
1596 | - def test_normalize_domain(self): |
1597 | - expression = openerp.osv.expression |
1598 | - norm_domain = domain = ['&', (1, '=', 1), ('a', '=', 'b')] |
1599 | - assert norm_domain == expression.normalize_domain(domain), "Normalized domains should be left untouched" |
1600 | - domain = [('x', 'in', ['y', 'z']), ('a.v', '=', 'e'), '|', '|', ('a', '=', 'b'), '!', ('c', '>', 'd'), ('e', '!=', 'f'), ('g', '=', 'h')] |
1601 | - norm_domain = ['&', '&', '&'] + domain |
1602 | - assert norm_domain == expression.normalize_domain(domain), "Non-normalized domains should be properly normalized" |
1603 | |
1604 | === removed file 'openerp/tests/test_misc.py' |
1605 | --- openerp/tests/test_misc.py 2014-01-09 08:17:31 +0000 |
1606 | +++ openerp/tests/test_misc.py 1970-01-01 00:00:00 +0000 |
1607 | @@ -1,44 +0,0 @@ |
1608 | -# This test can be run stand-alone with something like: |
1609 | -# > PYTHONPATH=. python2 openerp/tests/test_misc.py |
1610 | -import datetime |
1611 | -import locale |
1612 | -import unittest2 |
1613 | - |
1614 | -import babel |
1615 | -import babel.dates |
1616 | - |
1617 | -from ..tools import misc |
1618 | - |
1619 | - |
1620 | -class test_countingstream(unittest2.TestCase): |
1621 | - def test_empty_stream(self): |
1622 | - s = misc.CountingStream(iter([])) |
1623 | - self.assertEqual(s.index, -1) |
1624 | - self.assertIsNone(next(s, None)) |
1625 | - self.assertEqual(s.index, 0) |
1626 | - |
1627 | - def test_single(self): |
1628 | - s = misc.CountingStream(xrange(1)) |
1629 | - self.assertEqual(s.index, -1) |
1630 | - self.assertEqual(next(s, None), 0) |
1631 | - self.assertIsNone(next(s, None)) |
1632 | - self.assertEqual(s.index, 1) |
1633 | - |
1634 | - def test_full(self): |
1635 | - s = misc.CountingStream(xrange(42)) |
1636 | - for _ in s: |
1637 | - pass |
1638 | - self.assertEqual(s.index, 42) |
1639 | - |
1640 | - def test_repeated(self): |
1641 | - """ Once the CountingStream has stopped iterating, the index should not |
1642 | - increase anymore (the internal state should not be allowed to change) |
1643 | - """ |
1644 | - s = misc.CountingStream(iter([])) |
1645 | - self.assertIsNone(next(s, None)) |
1646 | - self.assertEqual(s.index, 0) |
1647 | - self.assertIsNone(next(s, None)) |
1648 | - self.assertEqual(s.index, 0) |
1649 | - |
1650 | -if __name__ == '__main__': |
1651 | - unittest2.main() |
1652 | |
1653 | === modified file 'openerp/tools/yaml_import.py' |
1654 | --- openerp/tools/yaml_import.py 2014-01-27 18:02:30 +0000 |
1655 | +++ openerp/tools/yaml_import.py 2014-02-03 01:51:54 +0000 |
1656 | @@ -321,7 +321,6 @@ |
1657 | view_info = model.fields_view_get(self.cr, SUPERUSER_ID, varg, 'form', context) |
1658 | |
1659 | record_dict = self._create_record(model, fields, view_info, default=default) |
1660 | - _logger.debug("RECORD_DICT %s" % record_dict) |
1661 | id = self.pool['ir.model.data']._update(self.cr, SUPERUSER_ID, record.model, \ |
1662 | self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode, context=context) |
1663 | self.id_map[record.id] = int(id) |
1664 | @@ -931,7 +930,7 @@ |
1665 | def yaml_import(cr, module, yamlfile, kind, idref=None, mode='init', noupdate=False, report=None): |
1666 | if idref is None: |
1667 | idref = {} |
1668 | - loglevel = logging.INFO if kind == 'test' else logging.DEBUG |
1669 | + loglevel = logging.DEBUG |
1670 | yaml_string = yamlfile.read() |
1671 | yaml_interpreter = YamlInterpreter(cr, module, idref, mode, filename=yamlfile.name, report=report, noupdate=noupdate, loglevel=loglevel) |
1672 | yaml_interpreter.process(yaml_string) |
1673 | |
1674 | === modified file 'openerpcommand/run_tests.py' |
1675 | --- openerpcommand/run_tests.py 2013-11-06 13:40:32 +0000 |
1676 | +++ openerpcommand/run_tests.py 2014-02-03 01:51:54 +0000 |
1677 | @@ -96,6 +96,8 @@ |
1678 | return ms |
1679 | |
1680 | def run(args): |
1681 | + print "Please use openerp-server --test-enable -d <dbname> -i modulename" |
1682 | + sys.exit(0) |
1683 | import unittest2 |
1684 | |
1685 | import openerp |
Why have you removed openerp/ addons/ base/test/ bug_lp541545. xml ?
I suppose it was there for a good reason...