Files
tryton/trytond/tests/test_trigger.py
T

481 lines
15 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
2014-12-02 12:54:01 +01:00
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
2021-12-11 17:58:45 +01:00
import unittest
2014-01-31 00:02:03 +01:00
from itertools import combinations
2021-12-11 17:58:45 +01:00
from trytond.ir.exceptions import TriggerConditionError
2018-12-29 14:19:08 +01:00
from trytond.model.exceptions import SQLConstraintError
2021-12-11 17:58:45 +01:00
from trytond.pool import Pool
from trytond.pyson import Eval, PYSONEncoder
from trytond.tests.test_tryton import activate_module, with_transaction
2013-09-16 11:38:11 +02:00
from trytond.tests.trigger import TRIGGER_LOGS
2010-08-19 22:01:12 +02:00
from trytond.transaction import Transaction
2018-12-29 14:19:08 +01:00
class TriggerTestCase(unittest.TestCase):
2014-01-12 19:58:22 +01:00
'Test Trigger'
2016-02-06 19:10:35 +01:00
@classmethod
def setUpClass(cls):
activate_module('tests')
2020-03-28 17:13:12 +01:00
def setUp(self):
TRIGGER_LOGS.clear()
def run_tasks(self):
pool = Pool()
Queue = pool.get('ir.queue')
transaction = Transaction()
while transaction.tasks:
task = Queue(transaction.tasks.pop())
task.run()
2016-02-06 19:10:35 +01:00
@with_transaction()
def test_constraints(self):
2014-01-12 19:58:22 +01:00
'Test constraints'
2016-02-06 19:10:35 +01:00
pool = Pool()
Model = pool.get('ir.model')
Trigger = pool.get('ir.trigger')
transaction = Transaction()
2016-02-06 19:10:35 +01:00
model, = Model.search([
('model', '=', 'test.triggered'),
])
values = {
'name': 'Test',
'model': model.id,
'on_time': True,
'condition': 'true',
2020-03-28 23:56:19 +01:00
'action': 'test.trigger_action|trigger',
2016-02-06 19:10:35 +01:00
}
2018-06-26 19:11:19 +02:00
self.assertTrue(Trigger.create([values]))
2016-02-06 19:10:35 +01:00
transaction.rollback()
# on_exclusive
for i in range(1, 4):
for combination in combinations(
['create', 'write', 'delete'], i):
2016-02-06 19:10:35 +01:00
combination_values = values.copy()
for mode in combination:
combination_values['on_%s' % mode] = True
2018-12-29 14:19:08 +01:00
self.assertRaises(SQLConstraintError, Trigger.create,
2016-02-06 19:10:35 +01:00
[combination_values])
transaction.rollback()
2016-02-06 19:10:35 +01:00
# check_condition
condition_values = values.copy()
condition_values['condition'] = '='
2018-12-29 14:19:08 +01:00
self.assertRaises(TriggerConditionError, Trigger.create,
2016-02-06 19:10:35 +01:00
[condition_values])
transaction.rollback()
2016-02-06 19:10:35 +01:00
# Restart the cache on the get_triggers method of ir.trigger
Trigger._get_triggers_cache.clear()
2016-02-06 19:10:35 +01:00
@with_transaction()
def test_on_create(self):
2014-01-12 19:58:22 +01:00
'Test on_create'
2016-02-06 19:10:35 +01:00
pool = Pool()
Model = pool.get('ir.model')
Trigger = pool.get('ir.trigger')
Triggered = pool.get('test.triggered')
2016-02-06 19:10:35 +01:00
model, = Model.search([
('model', '=', 'test.triggered'),
])
2016-02-06 19:10:35 +01:00
trigger, = Trigger.create([{
'name': 'Test',
'model': model.id,
'on_create': True,
2015-03-09 19:40:41 +01:00
'condition': 'true',
2020-03-28 23:56:19 +01:00
'action': 'test.trigger_action|trigger',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
triggered, = Triggered.create([{
'name': 'Test',
}])
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
# Trigger with condition
condition = PYSONEncoder().encode(
Eval('self', {}).get('name') == 'Bar')
Trigger.write([trigger], {
'condition': condition,
})
# Matching condition
triggered, = Triggered.create([{
'name': 'Bar',
}])
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
# Non matching condition
triggered, = Triggered.create([{
'name': 'Foo',
}])
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [])
# With limit number
Trigger.write([trigger], {
'condition': 'true',
'limit_number': 1,
})
triggered, = Triggered.create([{
'name': 'Test',
}])
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
# With minimum delay
Trigger.write([trigger], {
'limit_number': 0,
'minimum_time_delay': datetime.timedelta(hours=1),
})
triggered, = Triggered.create([{
'name': 'Test',
}])
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
# Restart the cache on the get_triggers method of ir.trigger
Trigger._get_triggers_cache.clear()
@with_transaction()
2020-03-28 17:13:12 +01:00
def test_on_write(self):
2014-01-12 19:58:22 +01:00
'Test on_write'
2016-02-06 19:10:35 +01:00
pool = Pool()
Model = pool.get('ir.model')
Trigger = pool.get('ir.trigger')
2020-03-28 17:13:12 +01:00
TriggerLog = pool.get('ir.trigger.log')
2016-02-06 19:10:35 +01:00
Triggered = pool.get('test.triggered')
2016-02-06 19:10:35 +01:00
model, = Model.search([
('model', '=', 'test.triggered'),
])
2016-02-06 19:10:35 +01:00
trigger, = Trigger.create([{
'name': 'Test',
'model': model.id,
'on_write': True,
'condition': 'true',
2020-03-28 23:56:19 +01:00
'action': 'test.trigger_action|trigger',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
triggered, = Triggered.create([{
'name': 'Test',
}])
Triggered.write([triggered], {
'name': 'Foo',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [])
# Trigger with condition
condition = PYSONEncoder().encode(
Eval('self', {}).get('name') == 'Bar')
Trigger.write([trigger], {
'condition': condition,
})
# Matching condition
Triggered.write([triggered], {
'name': 'Bar',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
# No change in condition
Triggered.write([triggered], {
'name': 'Bar',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [])
# Different change in condition
Triggered.write([triggered], {
'name': 'Foo',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [])
# With limit number
condition = PYSONEncoder().encode(
Eval('self', {}).get('name') == 'Bar')
Trigger.write([trigger], {
'condition': condition,
'limit_number': 1,
})
triggered, = Triggered.create([{
2012-09-24 22:16:53 +02:00
'name': 'Foo',
2016-02-06 19:10:35 +01:00
}])
Triggered.write([triggered], {
'name': 'Bar',
})
Triggered.write([triggered], {
'name': 'Foo',
})
Triggered.write([triggered], {
'name': 'Bar',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
# With minimum delay
Trigger.write([trigger], {
'limit_number': 0,
'minimum_time_delay': datetime.timedelta.max,
})
triggered, = Triggered.create([{
2012-09-24 22:16:53 +02:00
'name': 'Foo',
2016-02-06 19:10:35 +01:00
}])
for name in ('Bar', 'Foo', 'Bar'):
Triggered.write([triggered], {
'name': name,
2012-09-24 22:16:53 +02:00
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
2016-02-06 19:10:35 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
Trigger.write([trigger], {
'minimum_time_delay': datetime.timedelta(seconds=1),
})
triggered, = Triggered.create([{
2012-09-24 22:16:53 +02:00
'name': 'Foo',
2016-02-06 19:10:35 +01:00
}])
for name in ('Bar', 'Foo'):
Triggered.write([triggered], {
2020-03-28 17:13:12 +01:00
'name': name,
})
self.run_tasks()
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
Transaction().trigger_records.clear()
# Make time pass by moving back in time the log creation
trigger_log = TriggerLog.__table__()
cursor = Transaction().connection.cursor()
cursor.execute(*trigger_log.update(
[trigger_log.create_date],
[datetime.datetime.now() - datetime.timedelta(days=1)],
where=trigger_log.record_id == triggered.id))
2016-02-06 19:10:35 +01:00
Triggered.write([triggered], {
'name': 'Bar',
})
2020-03-28 17:13:12 +01:00
self.run_tasks()
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
# Restart the cache on the get_triggers method of ir.trigger
Trigger._get_triggers_cache.clear()
2016-02-06 19:10:35 +01:00
@with_transaction()
2020-03-28 17:13:12 +01:00
def test_on_delete(self):
2014-01-12 19:58:22 +01:00
'Test on_delete'
2016-02-06 19:10:35 +01:00
pool = Pool()
Model = pool.get('ir.model')
Trigger = pool.get('ir.trigger')
Triggered = pool.get('test.triggered')
TriggerLog = pool.get('ir.trigger.log')
2016-02-06 19:10:35 +01:00
model, = Model.search([
('model', '=', 'test.triggered'),
])
2016-02-06 19:10:35 +01:00
triggered, = Triggered.create([{
'name': 'Test',
}])
2016-02-06 19:10:35 +01:00
trigger, = Trigger.create([{
'name': 'Test',
'model': model.id,
'on_delete': True,
2015-03-09 19:40:41 +01:00
'condition': 'true',
2020-03-28 23:56:19 +01:00
'action': 'test.trigger_action|trigger',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
Triggered.delete([triggered])
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
Transaction().delete = {}
2016-02-06 19:10:35 +01:00
# Trigger with condition
condition = PYSONEncoder().encode(
Eval('self', {}).get('name') == 'Bar')
Trigger.write([trigger], {
'condition': condition,
})
2016-02-06 19:10:35 +01:00
triggered, = Triggered.create([{
2012-09-24 22:16:53 +02:00
'name': 'Bar',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
# Matching condition
Triggered.delete([triggered])
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
Transaction().delete = {}
triggered, = Triggered.create([{
2012-09-24 22:16:53 +02:00
'name': 'Foo',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
# Non matching condition
Triggered.delete([triggered])
self.assertEqual(TRIGGER_LOGS, [])
Transaction().delete = {}
triggered, = Triggered.create([{
'name': 'Test',
}])
# With limit number
Trigger.write([trigger], {
'condition': 'true',
'limit_number': 1,
})
Triggered.delete([triggered])
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
Transaction().delete = {}
# Delete trigger logs because SQLite reuse the same triggered_id
TriggerLog.delete(TriggerLog.search([
('trigger', '=', trigger.id),
]))
triggered, = Triggered.create([{
'name': 'Test',
}])
# With minimum delay
Trigger.write([trigger], {
'limit_number': 0,
'minimum_time_delay': datetime.timedelta(hours=1),
})
Triggered.delete([triggered])
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
TRIGGER_LOGS.pop()
Transaction().delete = {}
# Restart the cache on the get_triggers method of ir.trigger
Trigger._get_triggers_cache.clear()
@with_transaction()
def test_on_time(self):
'Test on_time'
pool = Pool()
Model = pool.get('ir.model')
Trigger = pool.get('ir.trigger')
Triggered = pool.get('test.triggered')
TriggerLog = pool.get('ir.trigger.log')
model, = Model.search([
('model', '=', 'test.triggered'),
])
trigger, = Trigger.create([{
'name': 'Test',
'model': model.id,
'on_time': True,
2015-03-09 19:40:41 +01:00
'condition': 'true',
2020-03-28 23:56:19 +01:00
'action': 'test.trigger_action|trigger',
2016-02-06 19:10:35 +01:00
}])
2016-02-06 19:10:35 +01:00
triggered, = Triggered.create([{
'name': 'Test',
}])
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
# Trigger with condition
condition = PYSONEncoder().encode(
Eval('self', {}).get('name') == 'Bar')
Trigger.write([trigger], {
'condition': condition,
})
2016-02-06 19:10:35 +01:00
# Matching condition
Triggered.write([triggered], {
'name': 'Bar',
})
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
2016-02-06 19:10:35 +01:00
# Non matching condition
Triggered.write([triggered], {
'name': 'Foo',
})
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(TRIGGER_LOGS, [])
2016-02-06 19:10:35 +01:00
# With limit number
Trigger.write([trigger], {
'condition': 'true',
'limit_number': 1,
})
Trigger.trigger_time()
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
# Delete trigger logs of limit number test
TriggerLog.delete(TriggerLog.search([
('trigger', '=', trigger.id),
]))
# With minimum delay
Trigger.write([trigger], {
'limit_number': 0,
'minimum_time_delay': datetime.timedelta.max,
})
Trigger.trigger_time()
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(TRIGGER_LOGS, [([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
Transaction().delete = {}
# Delete trigger logs of previous minimum delay test
TriggerLog.delete(TriggerLog.search([
('trigger', '=', trigger.id),
]))
Trigger.write([trigger], {
'minimum_time_delay': datetime.timedelta(seconds=1),
})
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
# Make time pass by moving back in time the log creation
trigger_log = TriggerLog.__table__()
cursor = Transaction().connection.cursor()
cursor.execute(*trigger_log.update(
[trigger_log.create_date],
[datetime.datetime.now() - datetime.timedelta(days=1)],
where=trigger_log.record_id == triggered.id))
2016-02-06 19:10:35 +01:00
Trigger.trigger_time()
2020-03-28 17:13:12 +01:00
self.assertEqual(
TRIGGER_LOGS, [([triggered], trigger), ([triggered], trigger)])
2016-02-06 19:10:35 +01:00
TRIGGER_LOGS.pop()
TRIGGER_LOGS.pop()
Transaction().delete = {}
# Restart the cache on the get_triggers method of ir.trigger
Trigger._get_triggers_cache.clear()