[MERGE] base: raise an exception if the format of the bank account is wrong
[odoo/odoo.git] / openerp / addons / base / test / test_osv_expression.yml
1 -
2     Testing for hierarchical search in M2M
3 -
4     !python {model: res.partner }: |
5         ids = self.search(cr, uid, [('category_id', 'child_of',ref('res_partner_category_0'))])
6         assert len(ids) >= 1, ids
7 -
8     "1.0 Setup test partner categories: parent root"
9 -
10     !record {model: res.partner.category, id: categ_root}:
11         name: Root category
12 -
13     "1.1 Setup test partner categories: parent category"
14 -
15     !record {model: res.partner.category, id: categ_0}:
16         name: Parent category
17         parent_id: categ_root
18 -
19     "1.2 Setup test partner categories: child 1"
20 -
21     !record {model: res.partner.category, id: categ_1}:
22         name: Child 1
23         parent_id: categ_0
24 -
25     Test hierarchical search in M2M with child ID (list of ids)
26 -
27     !python {model: res.partner.category }: |
28         ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_root')])])
29         assert len(ids) == 3, ids
30 -
31     Test hierarchical search in M2M with child ID (single id)
32 -
33     !python {model: res.partner.category }: |
34         ids = self.search(cr, uid, [('id', 'child_of',ref('categ_root'))])
35         assert len(ids) == 3, ids
36 -
37     Test hierarchical search in M2M with child IDs
38 -
39     !python {model: res.partner.category }: |
40         ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_1'), ref('categ_0')])])
41         assert len(ids) == 2, ids
42 -
43     Test hierarchical search in M2M with child IDs
44 -
45     !python {model: res.partner.category }: |
46         ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_0')])])
47         assert len(ids) == 2, ids
48 -
49     Test hierarchical search in M2M with child IDs
50 -
51     !python {model: res.partner.category }: |
52         ids = self.search(cr, uid, [('id', 'child_of',[ref('categ_1')])])
53         assert len(ids) == 1, ids
54 -
55     Testing that some domain expressions work
56 -
57     !python {model: res.partner }: |
58         ids = self.search(cr, uid, [('parent_id','=','Agrolait')])
59         assert len(ids) >= 1, ids
60 -
61     Trying the "in" operator, for scalar value
62 -
63     !python {model: res.partner }: |
64         ids = self.search(cr, uid, [('parent_id','in','Agrolait')])
65         assert len(ids) >= 1, ids
66 -
67     Trying the "in" operator for list value
68 -
69     !python {model: res.partner }: |
70         ids = self.search(cr, uid, [('parent_id','in',['Agrolait','ASUStek'])])
71         assert len(ids) >= 1, ids
72 -
73     Check we can use "in" operator for plain fields.
74 -
75     !python {model: ir.ui.menu }: |
76         ids = self.search(cr, uid, [('sequence','in',[1, 2, 10, 20])])
77         assert len(ids) >= 1, ids
78 -
79     Test one2many operator with empty search list
80 -
81     !assert {model: res.partner, search: "[('child_ids', 'in', [])]", count: 0, string: "Ids should be empty"}
82 -
83     Test one2many operator with False
84 -
85     !assert {model: res.partner, search: "[('child_ids', '=', False)]"}:
86         - address in (False, None, [])
87 -
88     Test many2many operator with empty search list
89 -
90     !assert {model: res.partner, search: "[('category_id', 'in', [])]", count: 0, string: "Ids should be empty"}
91 -
92     Test many2many operator with False
93 -
94     !assert {model: res.partner, search: "[('category_id', '=', False)]"}:
95         - category_id in (False, None, [])
96 -
97     Filtering on invalid value across x2many relationship should return an empty set
98 -
99     !assert {model: res.partner, search: "[('child_ids.city','=','foo')]", count: 0, string: "Searching for address.city = foo should give empty results"}
100 -
101     Check if many2one works with empty search list
102 -
103     !assert {model: res.partner, search: "[('company_id','in', [])]", count: 0, string: "Searching for company_id in [] should be empty!" }
104 -
105     For the sake of the following tests, I will create a second company
106 -
107     !record {model: res.company, id: ymltest_company2}:
108         name: Acme 2
109 -
110     And create a few partners with that company or no company
111 -
112     !python {model: res.partner }: |
113         for r in range(4):
114             self.create(cr, uid, { 'name': 'P of Acme %d' % r,
115                     'company_id': ref('ymltest_company2') })
116         for r in range(4):
117             self.create(cr, uid, { 'name': 'P of All %d' % r,
118                     'company_id': False })
119 -
120     Check if many2one works with negative empty list
121 -
122     !python {model: res.partner }: |
123         all_ids = self.search(cr, uid, [])
124         all_ids.sort()
125         res_ids = self.search(cr, uid,['|',('company_id','not in', []), ('company_id','=',False)])
126         res_ids.sort()
127         assert all_ids == res_ids, "not in [] fails"
128 -
129     Check that many2one will pick the correct records with a list
130 -
131     !python {model: res.partner }: |
132         res_ids = self.search(cr, uid, [('company_id', 'in', [False,])])
133         assert len(res_ids) >= 4, "We created 4 partners w/company, why find %d? %r" % \
134                     (len(res_ids), res_ids)
135 -
136     Check that many2one will exclude the correct records with a list
137 -
138     !python {model: res.partner }: |
139         # assuming that the default company is #1
140         res_ids = self.search(cr, uid, [('company_id', 'not in', [1])])
141         assert len(res_ids) >= 4, "We should have found 4 records at least, only have %d! %r" % \
142             (len(res_ids), res_ids)
143 -
144     Check that we exclude the correct records, + False
145 -
146     !python {model: res.partner }: |
147         # assuming that the default company is #1
148         res_ids = self.search(cr, uid, ['|', ('company_id', 'not in', [1]), ('company_id', '=', False)])
149         assert len(res_ids) >= 8, "We should have found 8 records at least, only have %d! %r" % \
150             (len(res_ids), res_ids)
151 -
152     Check that multi-level expressions also work
153 -
154     !python {model: res.partner }: |
155         res_ids = self.search(cr, uid, [('company_id.partner_id', 'in', [])])
156         assert res_ids == [], "Searching an empty set should return empty result, not %r" % res_ids
157 -
158     Check that multi-level expressions with negative op work
159 -
160     !python {model: res.partner }: |
161         all_ids = self.search(cr, uid, [('company_id', '!=', False)])
162         all_ids.sort()
163         res_ids = self.search(cr, uid, [('company_id.partner_id', 'not in', [])])
164         res_ids.sort()
165         assert res_ids == all_ids, "Searching against empty set failed, returns %r" % res_ids
166 -
167     Test the '(not) like/in' behavior. res.partner and its parent_id column are used because
168     parent_id is a many2one, allowing to test the Null value, and there are actually some
169     null and non-null values in the demo data.
170 -
171     !python {model: res.partner }: |
172         partner_ids = self.search(cr, uid, [])
173         partner_ids.sort()
174         max_partner_id = max(partner_ids)
175
176         # Grab test sample data without using a normal
177         # search domain, because we want to test these later,
178         # so we can't rely on them!
179         partners = self.browse(cr, uid, partner_ids)
180         with_parent = []
181         without_parent = []
182         with_website = []
183         for x in partners:
184             if x.parent_id:
185                 with_parent.append(x.id)
186             else:
187                 without_parent.append(x.id)
188             if x.website:
189                 with_website.append(x.id)
190         with_parent.sort()
191         without_parent.sort()
192         with_website.sort()
193
194         # We treat null values differently than in SQL. For instance in SQL:
195         #   SELECT id FROM res_partner WHERE parent_id NOT IN (0)
196         # will return only the records with non-null parent_id.
197         #   SELECT id FROM res_partner WHERE parent_id IN (0)
198         # will return expectedly nothing (our ids always begin at 1).
199         # This means the union of those two results will give only some
200         # records, but not all present in database.
201         #
202         # When using domains and the ORM's search method, we think it is
203         # more intuitive that the union returns all the records, and that
204         # a domain like ('parent_id', 'not in', [0]) will return all
205         # the records. For instance, if you perform a search for the companies
206         # that don't have OpenERP has a parent company, you expect to find,
207         # among others, the companies that don't have parent company.
208         #
209        
210         # existing values be treated similarly if we simply check that some
211         # existing value belongs to them.
212
213         res_0 = self.search(cr, uid, [('parent_id', 'not like', 'probably_unexisting_name')]) # get all rows, included null parent_id
214         res_0.sort()
215         res_1 = self.search(cr, uid, [('parent_id', 'not in', [max_partner_id + 1])]) # get all rows, included null parent_id
216         res_1.sort()
217         res_2 = self.search(cr, uid, [('parent_id', '!=', False)]) # get rows with not null parent_id, deprecated syntax
218         res_2.sort()
219         res_3 = self.search(cr, uid, [('parent_id', 'not in', [])]) # get all rows, included null parent_id
220         res_3.sort()
221         res_4 = self.search(cr, uid, [('parent_id', 'not in', [False])]) # get rows with not null parent_id
222         res_4.sort()
223         res_4b = self.search(cr, uid, [('parent_id', 'not ilike', '')]) # get only rows without parent
224         res_4b.sort()
225         assert res_0 == partner_ids, 'res0: expected %r, got %r' % (partner_ids, res_0)
226         assert res_1 == partner_ids, 'res1: expected %r, got %r' % (partner_ids, res_1)
227         assert res_2 == with_parent, 'res2: expected %r, got %r' % (with_parent, res_2)
228         assert res_3 == partner_ids, 'res3: expected %r, got %r' % (partner_ids, res_3)
229         assert res_4 == with_parent, 'res4: expected %r, got %r' % (with_parent, res_4)
230         assert res_4b == without_parent, 'res4b: expected %r, got %r' % (without_parent, res_4b)
231         # The results of these queries, when combined with queries 0..4 must
232         # give the whole set of ids.
233         res_5 = self.search(cr, uid, [('parent_id', 'like', 'probably_unexisting_name')])
234         res_5.sort()
235         res_6 = self.search(cr, uid, [('parent_id', 'in', [max_partner_id + 1])])
236         res_6.sort()
237         res_7 = self.search(cr, uid, [('parent_id', '=', False)])
238         res_7.sort()
239         res_8 = self.search(cr, uid, [('parent_id', 'in', [])])
240         res_8.sort()
241         res_9 = self.search(cr, uid, [('parent_id', 'in', [False])])
242         res_9.sort()
243         res_9b = self.search(cr, uid, [('parent_id', 'ilike', '')]) # get those with a parent
244         res_9b.sort()
245
246         assert res_5 == [], 'res5: expected %r, got %r' % ([], res_5)
247         assert res_6 == [], 'res6: expected %r, got %r' % ([], res_6)
248         assert res_7 == without_parent, 'res7: expected %r, got %r' % (without_parent, res_7)
249         assert res_8 == [], 'res8: expected %r, got %r' % ([], res_8)
250         assert res_9 == without_parent, 'res9: expected %r, got %r' % (without_parent, res_9)
251         assert res_9b == with_parent, 'res9b: expected %r, got %r' % (with_parent, res_9b)
252         # These queries must return exactly the results than the queries 0..4,
253         # i.e. not ... in ... must be the same as ... not in ... .
254         res_10 = self.search(cr, uid, ['!', ('parent_id', 'like', 'probably_unexisting_name')])
255         res_10.sort()
256         res_11 = self.search(cr, uid, ['!', ('parent_id', 'in', [max_partner_id + 1])])
257         res_11.sort()
258         res_12 = self.search(cr, uid, ['!', ('parent_id', '=', False)])
259         res_12.sort()
260         res_13 = self.search(cr, uid, ['!', ('parent_id', 'in', [])])
261         res_13.sort()
262         res_14 = self.search(cr, uid, ['!', ('parent_id', 'in', [False])])
263         res_14.sort()
264         assert res_0 == res_10
265         assert res_1 == res_11
266         assert res_2 == res_12
267         assert res_3 == res_13
268         assert res_4 == res_14
269
270         # Testing many2one field is not enough, a regular char field is tested
271         # with in [] and must not return any result.
272         res_15 = self.search(cr, uid, [('website', 'in', [])])
273         assert res_15 == []
274         # not in [] must return everything.
275         res_16 = self.search(cr, uid, [('website', 'not in', [])])
276         res_16.sort()
277         assert res_16 == partner_ids
278
279         res_17 = self.search(cr, uid, [('website', '!=', False)])
280         res_17.sort()
281         assert res_17 == with_website
282
283 -
284     Check behavior for required many2one fields
285 -
286     !python {model: res.company }: |
287         company_ids = sorted(self.search(cr, uid, []))
288         # currency_id is required
289         res_101 = sorted(self.search(cr, uid, [('currency_id', 'not ilike', '')])) # get no companies
290         res_102 = sorted(self.search(cr, uid, [('currency_id', 'ilike', '')])) # get all companies
291         assert res_101 == [], 'res_101: expected %r, got %r' % ([], res_101)
292         assert res_102 == company_ids, 'res_102: expected %r, got %r' % (company_ids, res_102)
293 -
294     Property of the query (one2many != False).
295 -
296     !python {model: res.currency }: |
297         ids = self.search(cr, uid, [])
298         referenced_companies = set([x.company_id.id for x in self.browse(cr, uid, ids)])
299         companies = set(self.pool.get('res.company').search(cr, uid, [('currency_ids', '!=', False)]))
300         assert referenced_companies == companies
301 -
302     Property of the query (one2many = False).
303 -
304     !python {model: res.currency }: |
305         ids = self.search(cr, uid, [])
306         referenced_companies = set([x.company_id.id for x in self.browse(cr, uid, ids)])
307         unreferenced_companies = set(self.pool.get('res.company').search(cr, uid, [])).difference(referenced_companies)
308         companies = set(self.pool.get('res.company').search(cr, uid, [('currency_ids', '=', False)]))
309         assert unreferenced_companies == companies
310 -
311     Equivalent queries.
312 -
313     !python {model: res.currency }: |
314         max_currency_id = max(self.search(cr, uid, []))
315         res_0 = self.search(cr, uid, [])
316         res_1 = self.search(cr, uid, [('name', 'not like', 'probably_unexisting_name')])
317         res_2 = self.search(cr, uid, [('id', 'not in', [max_currency_id + 1003])])
318         res_3 = self.search(cr, uid, [('id', 'not in', [])])
319         res_4 = self.search(cr, uid, [('id', '!=', False)])
320         res_0.sort()
321         res_1.sort()
322         res_2.sort()
323         res_3.sort()
324         res_4.sort()
325         assert res_0 == res_1
326         assert res_0 == res_2
327         assert res_0 == res_3
328         assert res_0 == res_4
329 -
330     Equivalent queries, integer and string.
331 -
332     !python {model: res.partner }: |
333         all_ids = self.search(cr, uid, [])
334         if len(all_ids) > 1:
335             one = all_ids[0]
336             record = self.browse(cr, uid, one)
337             others = all_ids[1:]
338             res_1 = self.search(cr, uid, [('id', '=', one)])
339             # self.search(cr, uid, [('id', '!=', others)]) # not permitted
340             res_2 = self.search(cr, uid, [('id', 'not in', others)])
341             res_3 = self.search(cr, uid, ['!', ('id', '!=', one)])
342             res_4 = self.search(cr, uid, ['!', ('id', 'in', others)])
343             # res_5 = self.search(cr, uid, [('id', 'in', one)]) # TODO make it permitted, just like for child_of
344             res_6 = self.search(cr, uid, [('id', 'in', [one])])
345             res_7 = self.search(cr, uid, [('name', '=', record.name)])
346             res_8 = self.search(cr, uid, [('name', 'in', [record.name])])
347             # res_9 = self.search(cr, uid, [('name', 'in', record.name)]) # TODO
348             assert [one] == res_1
349             assert [one] == res_2
350             assert [one] == res_3
351             assert [one] == res_4
352             #assert [one] == res_5
353             assert [one] == res_6
354             assert [one] == res_7
355 -
356     Need a company with a parent_id.
357 -
358     !record {model: res.company, id: ymltest_company3}:
359         name: Acme 3
360 -
361     Need a company with a parent_id.
362 -
363     !record {model: res.company, id: ymltest_company4}:
364         name: Acme 4
365         parent_id: ymltest_company3
366 -
367     Equivalent queries, one2many.
368 -
369     !python {model: res.company }: |
370         # Search the company via its one2many (the one2many must point back at the company).
371         company = self.browse(cr, uid, ref('ymltest_company3'))
372         max_currency_id = max(self.pool.get('res.currency').search(cr, uid, []))
373         currency_ids1 = self.pool.get('res.currency').search(cr, uid, [('name', 'not like', 'probably_unexisting_name')])
374         currency_ids2 = self.pool.get('res.currency').search(cr, uid, [('id', 'not in', [max_currency_id + 1003])])
375         currency_ids3 = self.pool.get('res.currency').search(cr, uid, [('id', 'not in', [])])
376         assert currency_ids1 == currency_ids2 == currency_ids3, 'All 3 results should have be the same: all currencies'
377         default_company = self.browse(cr, uid, 1)
378         # one2many towards same model
379         res_1 = self.search(cr, uid, [('child_ids', 'in', [x.id for x in company.child_ids])]) # any company having a child of company3 as child
380         res_2 = self.search(cr, uid, [('child_ids', 'in', [company.child_ids[0].id])]) # any company having the first child of company3 as child
381         # one2many towards another model
382         res_3 = self.search(cr, uid, [('currency_ids', 'in', [x.id for x in default_company.currency_ids])]) # companies having a currency of main company
383         res_4 = self.search(cr, uid, [('currency_ids', 'in', [default_company.currency_ids[0].id])]) # companies having first currency of main company
384         res_5 = self.search(cr, uid, [('currency_ids', 'in', default_company.currency_ids[0].id)]) # companies having first currency of main company
385         # res_6 = self.search(cr, uid, [('currency_ids', 'in', [default_company.currency_ids[0].name])]) # TODO
386         res_7 = self.search(cr, uid, [('currency_ids', '=', default_company.currency_ids[0].name)])
387         res_8 = self.search(cr, uid, [('currency_ids', 'like', default_company.currency_ids[0].name)])
388         res_9 = self.search(cr, uid, [('currency_ids', 'like', 'probably_unexisting_name')])
389         # self.search(cr, uid, [('currency_ids', 'unexisting_op', 'probably_unexisting_name')]) # TODO expected exception
390         assert res_1 == [ref('ymltest_company3')]
391         assert res_2 == [ref('ymltest_company3')]
392         assert res_3 == [1]
393         assert res_4 == [1]
394         assert res_5 == [1]
395         assert res_7 == [1]
396         assert res_8 == [1]
397         assert res_9 == []
398
399         # get the companies referenced by some currency (this is normally the main company)
400         res_10 = self.search(cr, uid, [('currency_ids', 'not like', 'probably_unexisting_name')])
401         res_11 = self.search(cr, uid, [('currency_ids', 'not in', [max_currency_id + 1])])
402         res_12 = self.search(cr, uid, [('currency_ids', '!=', False)])
403         res_13 = self.search(cr, uid, [('currency_ids', 'not in', [])])
404         res_10.sort()
405         res_11.sort()
406         res_12.sort()
407         res_13.sort()
408         assert res_10 == res_11
409         assert res_10 == res_12
410         assert res_10 == res_13
411
412         # child_of x returns x and its children (direct or not).
413         company = self.browse(cr, uid, ref('ymltest_company3'))
414         expected = [ref('ymltest_company3'), ref('ymltest_company4')]
415         expected.sort()
416         res_1 = self.search(cr, uid, [('id', 'child_of', [ref('ymltest_company3')])])
417         res_1.sort()
418         res_2 = self.search(cr, uid, [('id', 'child_of', ref('ymltest_company3'))])
419         res_2.sort()
420         res_3 = self.search(cr, uid, [('id', 'child_of', [company.name])])
421         res_3.sort()
422         res_4 = self.search(cr, uid, [('id', 'child_of', company.name)])
423         res_4.sort()
424         assert res_1 == expected
425         assert res_2 == expected
426         assert res_3 == expected
427         assert res_4 == expected
428 -
429     Unaccent. Create a company with an accent in its name.
430 -
431     !record {model: res.company, id: ymltest_unaccent_company}:
432         name: Hélène
433 -
434     Test the unaccent-enabled 'ilike'.
435 -
436     !python {model: res.company}: |
437         if self.pool.has_unaccent:
438             ids = self.search(cr, uid, [('name','ilike','Helene')], {})
439             assert ids == [ref('ymltest_unaccent_company')]
440             ids = self.search(cr, uid, [('name','ilike','hélène')], {})
441             assert ids == [ref('ymltest_unaccent_company')]
442             ids = self.search(cr, uid, [('name','not ilike','Helene')], {})
443             assert ref('ymltest_unaccent_company') not in ids
444             ids = self.search(cr, uid, [('name','not ilike','hélène')], {})
445             assert ref('ymltest_unaccent_company') not in ids
446 -
447     Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on an untranslated field.
448 -
449     !python {model: res.partner }: |
450         all_ids = self.search(cr, uid, [('name', '=like', 'A_e_or')])
451         assert len(all_ids) == 1, "Must match one partner (Axelor), got %r"%all_ids
452         all_ids = self.search(cr, uid, [('name', '=ilike', 'v%')])
453         assert len(all_ids) >= 1, "Must match one partner (Vicking Direct), got %r"%all_ids
454 -
455     Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on translated field.
456 -
457     !python {model: res.country }: |
458         all_ids = self.search(cr, uid, [('name', '=like', 'Ind__')])
459         assert len(all_ids) == 1, "Must match India only, got %r"%all_ids
460         all_ids = self.search(cr, uid, [('name', '=ilike', 'z%')])
461         assert len(all_ids) == 3, "Must match only countries with names starting with Z (currently 3), got %r"%all_ids
462 -
463     Use the create_date column on res.country (which doesn't declare it in _columns).
464 -
465     !python {model: res.country }: |
466         ids = self.search(cr, uid, [('create_date', '<', '2001-01-01 12:00:00')])
467
468
469 -
470     Verify that invalid expressions are refused, even for magic fields
471 -
472     !python {model: res.country }: |
473         try:
474             self.search(cr, uid, [('does_not_exist', '=', 'foo')])
475             raise AssertionError('Invalid fields should not be accepted')
476         except ValueError:
477             pass
478
479         try:
480             self.search(cr, uid, [('create_date', '>>', 'foo')])
481             raise AssertionError('Invalid operators should not be accepted')
482         except ValueError:
483             pass
484
485         import psycopg2
486         try:
487             cr._default_log_exceptions = False
488             cr.execute('SAVEPOINT expression_failure_test')
489             self.search(cr, uid, [('create_date', '=', "1970-01-01'); --")])
490             # if the above search gives no error, the operand was not escaped!
491             cr.execute('RELEASE SAVEPOINT expression_failure_test')
492             raise AssertionError('Operands should always be SQL escaped')
493         except psycopg2.DataError:
494             # Should give: 'DataError: invalid input syntax for type timestamp' or similar
495             cr.execute('ROLLBACK TO SAVEPOINT expression_failure_test')
496 -
497     Testing for Many2Many field with category supplier and active=False
498 -
499     !python {model: res.partner }: |
500         vals = {'category_id': [(6, 0, [ref("base.res_partner_category_1")])],
501                 'name': 'OpenERP Test',
502                 'active': False,
503                 'child_ids': [(0, 0, {'name': 'address of OpenERP Test', 'country_id': ref("base.be")})]
504                 }
505         self.create(cr, uid, vals, context=context)
506         res_ids = self.search(cr, uid, [('category_id', 'ilike', 'supplier'), ('active', '=', False)])
507         assert len(res_ids) != 0, "Record not Found with category supplier and active False."
508 -
509     Testing for One2Many field with country Belgium and active=False
510 -
511     !python {model: res.partner }: |
512         res_ids = self.search(cr, uid, [('child_ids.country_id','=','Belgium'),('active','=',False)])
513         assert len(res_ids) != 0, "Record not Found with country Belgium and active False."
514