Merge lp:~openerp-dev/openobject-server/trunk-test-al into lp:openobject-server

Proposed by Antony Lesuisse (OpenERP)
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
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
To post a comment you must log in.
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

Revision history for this message
Raphael Collet (OpenERP) (rco-openerp) wrote :

Why have you removed openerp/addons/base/test/bug_lp541545.xml ?
I suppose it was there for a good reason...

review: Needs Information
Revision history for this message
Raphael Collet (OpenERP) (rco-openerp) wrote :

Please redo the move openerp/tests/test_misc.py -> openerp/addons/base/tests/test_misc.py with "bzr mv".
You've screwed up the file history.

review: Needs Fixing
Revision history for this message
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?

review: Needs Information
Revision history for this message
Raphael Collet (OpenERP) (rco-openerp) wrote :

Please remove commented code (diff 1332-1335).

Revision history for this message
Christophe Simonis (OpenERP) (kangol) wrote :

> Please redo the move openerp/tests/test_misc.py ->
> openerp/addons/base/tests/test_misc.py with "bzr mv".
> You've screwed up the file history.

same for openerp/addons/base/tests/test_uninstall.py and openerp/tests/test_expression.py

review: Needs Fixing
Revision history for this message
Christophe Simonis (OpenERP) (kangol) wrote :

Why removing the RLock on registry access?

The check on _init (openerp/service/model.py) was there for a good reason. do not remove it.
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.

review: Needs Fixing

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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