1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from contextlib import contextmanager
import unittest
import psycopg2
import psycopg2.errorcodes
import odoo
from odoo.tests import common
ADMIN_USER_ID = common.ADMIN_USER_ID
@contextmanager
def environment():
""" Return an environment with a new cursor for the current database; the
cursor is committed and closed after the context block.
"""
registry = odoo.registry(common.get_db_name())
with registry.cursor() as cr:
yield odoo.api.Environment(cr, ADMIN_USER_ID, {})
cr.commit()
def drop_sequence(code):
with environment() as env:
seq = env['ir.sequence'].search([('code', '=', code)])
seq.unlink()
class TestIrSequenceStandard(unittest.TestCase):
""" A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """
def test_ir_sequence_create(self):
""" Try to create a sequence object. """
with environment() as env:
seq = env['ir.sequence'].create({
'code': 'test_sequence_type',
'name': 'Test sequence',
})
self.assertTrue(seq)
def test_ir_sequence_search(self):
""" Try a search. """
with environment() as env:
seqs = env['ir.sequence'].search([])
self.assertTrue(seqs)
def test_ir_sequence_draw(self):
""" Try to draw a number. """
with environment() as env:
n = env['ir.sequence'].next_by_code('test_sequence_type')
self.assertTrue(n)
def test_ir_sequence_draw_twice(self):
""" Try to draw a number from two transactions. """
with environment() as env0:
with environment() as env1:
n0 = env0['ir.sequence'].next_by_code('test_sequence_type')
self.assertTrue(n0)
n1 = env1['ir.sequence'].next_by_code('test_sequence_type')
self.assertTrue(n1)
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type')
class TestIrSequenceNoGap(unittest.TestCase):
""" Copy of the previous tests for a 'No gap' sequence. """
def test_ir_sequence_create_no_gap(self):
""" Try to create a sequence object. """
with environment() as env:
seq = env['ir.sequence'].create({
'code': 'test_sequence_type_2',
'name': 'Test sequence',
'implementation': 'no_gap',
})
self.assertTrue(seq)
def test_ir_sequence_draw_no_gap(self):
""" Try to draw a number. """
with environment() as env:
n = env['ir.sequence'].next_by_code('test_sequence_type_2')
self.assertTrue(n)
def test_ir_sequence_draw_twice_no_gap(self):
""" Try to draw a number from two transactions.
This is expected to not work.
"""
with environment() as env0:
with environment() as env1:
env1.cr._default_log_exceptions = False # Prevent logging a traceback
with self.assertRaises(psycopg2.OperationalError) as e:
n0 = env0['ir.sequence'].next_by_code('test_sequence_type_2')
self.assertTrue(n0)
n1 = env1['ir.sequence'].next_by_code('test_sequence_type_2')
self.assertEqual(e.exception.pgcode, psycopg2.errorcodes.LOCK_NOT_AVAILABLE, msg="postgresql returned an incorrect errcode")
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type_2')
class TestIrSequenceChangeImplementation(unittest.TestCase):
""" Create sequence objects and change their ``implementation`` field. """
def test_ir_sequence_1_create(self):
""" Try to create a sequence object. """
with environment() as env:
seq = env['ir.sequence'].create({
'code': 'test_sequence_type_3',
'name': 'Test sequence',
})
self.assertTrue(seq)
seq = env['ir.sequence'].create({
'code': 'test_sequence_type_4',
'name': 'Test sequence',
'implementation': 'no_gap',
})
self.assertTrue(seq)
def test_ir_sequence_2_write(self):
with environment() as env:
domain = [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])]
seqs = env['ir.sequence'].search(domain)
seqs.write({'implementation': 'standard'})
seqs.write({'implementation': 'no_gap'})
def test_ir_sequence_3_unlink(self):
with environment() as env:
domain = [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])]
seqs = env['ir.sequence'].search(domain)
seqs.unlink()
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type_3')
drop_sequence('test_sequence_type_4')
class TestIrSequenceGenerate(unittest.TestCase):
""" Create sequence objects and generate some values. """
def test_ir_sequence_create(self):
""" Try to create a sequence object. """
with environment() as env:
seq = env['ir.sequence'].create({
'code': 'test_sequence_type_5',
'name': 'Test sequence',
})
self.assertTrue(seq)
with environment() as env:
for i in range(1, 10):
n = env['ir.sequence'].next_by_code('test_sequence_type_5')
self.assertEqual(n, str(i))
def test_ir_sequence_create_no_gap(self):
""" Try to create a sequence object. """
with environment() as env:
seq = env['ir.sequence'].create({
'code': 'test_sequence_type_6',
'name': 'Test sequence',
'implementation': 'no_gap',
})
self.assertTrue(seq)
with environment() as env:
for i in range(1, 10):
n = env['ir.sequence'].next_by_code('test_sequence_type_6')
self.assertEqual(n, str(i))
@classmethod
def tearDownClass(cls):
drop_sequence('test_sequence_type_5')
drop_sequence('test_sequence_type_6')
class TestIrSequenceInit(common.TransactionCase):
def test_00(self):
""" test whether the read method returns the right number_next value
(from postgreSQL sequence and not ir_sequence value)
"""
# first creation of sequence (normal)
seq = self.env['ir.sequence'].create({
'number_next': 1,
'company_id': 1,
'padding': 4,
'number_increment': 1,
'implementation': 'standard',
'name': 'test-sequence-00',
})
# Call next() 4 times, and check the last returned value
seq.next_by_id()
seq.next_by_id()
seq.next_by_id()
n = seq.next_by_id()
self.assertEqual(n, "0004", 'The actual sequence value must be 4. reading : %s' % n)
# reset sequence to 1 by write()
seq.write({'number_next': 1})
# Read the value of the current sequence
n = seq.next_by_id()
self.assertEqual(n, "0001", 'The actual sequence value must be 1. reading : %s' % n)
|