Files
odoo_source/odoo/addons/test_new_api/tests/test_schema.py
T
Martin TrigauxandRaphaël Collet 7593b887df [REF] fields: use ir.model.fields.selection
The selection values of a selection field are now stored in database in the
model ir.model.fields.selection

This will allow to have a modular approche on selections and each selection
is now linked to the module that declared it.
Previously to this change, the selections were linked to the field, meaning
uninstalling a module had no impact on the selections stored on database.

With this change, the selections will now be translated in the correct module
(having an external id) and the records having a used selection will now be
reset to null.

closes odoo/odoo#30228

Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>


Co-authored-by: Raphaël Collet <rco@odoo.com>
2019-08-19 11:44:34 +00:00

541 lines
23 KiB
Python

# -*- coding: utf-8 -*-
from odoo.models import MetaModel
from odoo.tests import common
class TestReflection(common.TransactionCase):
""" Test the reflection into 'ir.model', 'ir.model.fields', etc. """
def test_models_fields(self):
""" check that all models and fields are reflected as expected. """
# retrieve the models defined in this module, and check them
model_names = {cls._name for cls in MetaModel.module_to_models['test_new_api']}
ir_models = self.env['ir.model'].search([('model', 'in', list(model_names))])
self.assertEqual(len(ir_models), len(model_names))
for ir_model in ir_models:
model = self.env[ir_model.model]
self.assertEqual(ir_model.name, model._description or False)
self.assertEqual(ir_model.state, 'manual' if model._custom else 'base')
self.assertEqual(ir_model.transient, bool(model._transient))
self.assertItemsEqual(ir_model.mapped('field_id.name'), list(model._fields))
for ir_field in ir_model.field_id:
field = model._fields[ir_field.name]
self.assertEqual(ir_field.model, field.model_name)
self.assertEqual(ir_field.field_description, field.string)
self.assertEqual(ir_field.help, field.help or False)
self.assertEqual(ir_field.ttype, field.type)
self.assertEqual(ir_field.state, 'manual' if field.manual else 'base')
self.assertEqual(ir_field.index, bool(field.index))
self.assertEqual(ir_field.store, bool(field.store))
self.assertEqual(ir_field.copied, bool(field.copy))
self.assertEqual(ir_field.related, bool(field.related) and ".".join(field.related))
self.assertEqual(ir_field.readonly, bool(field.readonly))
self.assertEqual(ir_field.required, bool(field.required))
self.assertEqual(ir_field.selectable, bool(field.search or field.store))
self.assertEqual(ir_field.translate, bool(field.translate))
if field.relational:
self.assertEqual(ir_field.relation, field.comodel_name)
if field.type == 'one2many' and field.store:
self.assertEqual(ir_field.relation_field, field.inverse_name)
if field.type == 'many2many' and field.store:
self.assertEqual(ir_field.relation_table, field.relation)
self.assertEqual(ir_field.column1, field.column1)
self.assertEqual(ir_field.column2, field.column2)
relation = self.env['ir.model.relation'].search([('name', '=', field.relation)])
self.assertTrue(relation)
self.assertIn(relation.model.model, [field.model_name, field.comodel_name])
if field.type == 'selection':
selection = [(sel.value, sel.name) for sel in ir_field.selection_ids]
if isinstance(field.selection, list):
self.assertEqual(selection, field.selection)
else:
self.assertEqual(selection, [])
class TestSchema(common.TransactionCase):
def get_table_data(self, tablename):
query = ''' SELECT table_catalog, table_schema, table_name, table_type,
user_defined_type_catalog, user_defined_type_schema,
user_defined_type_name, is_insertable_into, is_typed
FROM information_schema.tables
WHERE table_name=%s '''
self.cr.execute(query, [tablename])
return self.cr.dictfetchone()
def get_columns_data(self, tablename):
query = ''' SELECT table_catalog, table_schema, table_name, column_name,
column_default, data_type, is_nullable, is_updatable,
character_maximum_length, numeric_precision,
numeric_precision_radix, numeric_scale,
datetime_precision, udt_catalog, udt_schema, udt_name
FROM information_schema.columns
WHERE table_name=%s '''
self.cr.execute(query, [tablename])
return {row['column_name']: row for row in self.cr.dictfetchall()}
def get_foreign_keys(self, tablename):
query = ''' SELECT a.table_name, a.column_name,
b.table_name, b.column_name, c.delete_rule
FROM information_schema.referential_constraints c,
information_schema.key_column_usage a,
information_schema.constraint_column_usage b
WHERE a.constraint_schema=c.constraint_schema
AND a.constraint_name=c.constraint_name
AND b.constraint_schema=c.constraint_schema
AND b.constraint_name=c.constraint_name
AND a.table_name=%s '''
self.cr.execute(query, [tablename])
return self.cr.fetchall()
def test_00_table(self):
""" check the database schema of a model """
model = self.env['test_new_api.foo']
self.assertEqual(model._table, 'test_new_api_foo')
# retrieve schema data about that table
table_data = self.get_table_data('test_new_api_foo')
self.assertEqual(table_data, {
'is_insertable_into': u'YES',
'is_typed': u'NO',
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_foo',
'table_schema': u'public',
'table_type': u'BASE TABLE',
'user_defined_type_catalog': None,
'user_defined_type_name': None,
'user_defined_type_schema': None,
})
# retrieve schema data about the table's columns
columns_data = self.get_columns_data('test_new_api_foo')
self.assertEqual(set(columns_data),
{'id', 'create_date', 'create_uid', 'write_date',
'write_uid', 'name', 'value1', 'value2'})
# retrieve schema data about the table's foreign keys
foreign_keys = self.get_foreign_keys('test_new_api_foo')
self.assertItemsEqual(foreign_keys, [
('test_new_api_foo', 'create_uid', 'res_users', 'id', 'SET NULL'),
('test_new_api_foo', 'write_uid', 'res_users', 'id', 'SET NULL'),
])
def test_10_boolean(self):
""" check the database representation of a boolean field """
model = self.env['test_new_api.message']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['important'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'important',
'data_type': u'boolean',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_message',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'bool',
'udt_schema': u'pg_catalog',
})
def test_10_integer(self):
""" check the database representation of an integer field """
model = self.env['test_new_api.category']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['color'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'color',
'data_type': u'integer',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': 32,
'numeric_precision_radix': 2,
'numeric_scale': 0,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_category',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'int4',
'udt_schema': u'pg_catalog',
})
def test_10_float(self):
""" check the database representation of a float field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['number'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'number',
'data_type': u'numeric',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': 10,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'numeric',
'udt_schema': u'pg_catalog',
})
def test_10_monetary(self):
""" check the database representation of a monetary field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['amount'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'amount',
'data_type': u'numeric',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': 10,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'numeric',
'udt_schema': u'pg_catalog',
})
def test_10_char(self):
""" check the database representation of a char field """
model = self.env['res.country']
self.assertFalse(type(model).code.required)
self.assertEqual(type(model).code.size, 2)
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['code'], {
'character_maximum_length': 2,
'column_default': None,
'column_name': u'code',
'data_type': u'character varying',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'res_country',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'varchar',
'udt_schema': u'pg_catalog',
})
model = self.env['test_new_api.message']
self.assertFalse(type(model).name.required)
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['name'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'name',
'data_type': u'character varying',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_message',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'varchar',
'udt_schema': u'pg_catalog',
})
model = self.env['test_new_api.category']
self.assertTrue(type(model).name.required)
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['name'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'name',
'data_type': u'character varying',
'datetime_precision': None,
'is_nullable': u'NO',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_category',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'varchar',
'udt_schema': u'pg_catalog',
})
def test_10_text(self):
""" check the database representation of a text field """
model = self.env['test_new_api.message']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['body'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'body',
'data_type': u'text',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_message',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'text',
'udt_schema': u'pg_catalog',
})
def test_10_html(self):
""" check the database representation of an html field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['comment1'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'comment1',
'data_type': u'text',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'text',
'udt_schema': u'pg_catalog',
})
def test_10_date(self):
""" check the database representation of a date field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['date'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'date',
'data_type': u'date',
'datetime_precision': 0,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'date',
'udt_schema': u'pg_catalog',
})
def test_10_datetime(self):
""" check the database representation of a datetime field """
model = self.env['ir.property']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['value_datetime'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'value_datetime',
'data_type': u'timestamp without time zone',
'datetime_precision': 6,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'ir_property',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'timestamp',
'udt_schema': u'pg_catalog',
})
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['create_date'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'create_date',
'data_type': u'timestamp without time zone',
'datetime_precision': 6,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'timestamp',
'udt_schema': u'pg_catalog',
})
def test_10_selection(self):
""" check the database representation of a selection field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['lang'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'lang',
'data_type': u'character varying',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'varchar',
'udt_schema': u'pg_catalog',
})
def test_10_reference(self):
""" check the database representation of a reference field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['reference'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'reference',
'data_type': u'character varying',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': None,
'numeric_precision_radix': None,
'numeric_scale': None,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'varchar',
'udt_schema': u'pg_catalog',
})
def test_10_many2one(self):
""" check the database representation of a many2one field """
model = self.env['test_new_api.mixed']
columns_data = self.get_columns_data(model._table)
self.assertEqual(columns_data['currency_id'], {
'character_maximum_length': None,
'column_default': None,
'column_name': u'currency_id',
'data_type': u'integer',
'datetime_precision': None,
'is_nullable': u'YES',
'is_updatable': u'YES',
'numeric_precision': 32,
'numeric_precision_radix': 2,
'numeric_scale': 0,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_mixed',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'int4',
'udt_schema': u'pg_catalog',
})
foreign_keys = self.get_foreign_keys(model._table)
self.assertIn(
('test_new_api_mixed', 'currency_id', 'res_currency', 'id', 'SET NULL'),
foreign_keys,
)
def test_10_many2many(self):
""" check the database representation of a many2many field """
model = self.env['test_new_api.discussion']
field = type(model).categories
comodel = self.env[field.comodel_name]
self.assertTrue(field.relation)
self.assertTrue(field.column1)
self.assertTrue(field.column2)
columns_data = self.get_columns_data(model._table)
self.assertNotIn('categories', columns_data)
table_data = self.get_table_data(field.relation)
self.assertEqual(table_data, {
'is_insertable_into': u'YES',
'is_typed': u'NO',
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_discussion_category',
'table_schema': u'public',
'table_type': u'BASE TABLE',
'user_defined_type_catalog': None,
'user_defined_type_name': None,
'user_defined_type_schema': None,
})
columns_data = self.get_columns_data(field.relation)
self.assertEqual(columns_data, {
field.column1: {
'character_maximum_length': None,
'column_default': None,
'column_name': u'discussion',
'data_type': u'integer',
'datetime_precision': None,
'is_nullable': u'NO',
'is_updatable': u'YES',
'numeric_precision': 32,
'numeric_precision_radix': 2,
'numeric_scale': 0,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_discussion_category',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'int4',
'udt_schema': u'pg_catalog',
},
field.column2: {
'character_maximum_length': None,
'column_default': None,
'column_name': u'category',
'data_type': u'integer',
'datetime_precision': None,
'is_nullable': u'NO',
'is_updatable': u'YES',
'numeric_precision': 32,
'numeric_precision_radix': 2,
'numeric_scale': 0,
'table_catalog': self.cr.dbname,
'table_name': u'test_new_api_discussion_category',
'table_schema': u'public',
'udt_catalog': self.cr.dbname,
'udt_name': u'int4',
'udt_schema': u'pg_catalog'
},
})
foreign_keys = self.get_foreign_keys(field.relation)
self.assertItemsEqual(foreign_keys, [
(field.relation, field.column1, model._table, 'id', 'CASCADE'),
(field.relation, field.column2, comodel._table, 'id', 'CASCADE'),
])