|
@ -0,0 +1,94 @@ |
|
|
|
|
|
# Copyright (C) 2018 Camptocamp |
|
|
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|
|
|
|
|
# pylint: disable=anomalous-backslash-in-string |
|
|
|
|
|
|
|
|
|
|
|
from odoo import api |
|
|
|
|
|
from odoo.tests import common |
|
|
|
|
|
|
|
|
|
|
|
import datetime |
|
|
|
|
|
import mock |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MOCK_PATH = 'odoo.addons.base_cron_oneshot.models.ir_cron' |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OneshotTestCase(common.SavepointCase): |
|
|
|
|
|
|
|
|
|
|
|
@property |
|
|
|
|
|
def cron_model(self): |
|
|
|
|
|
return self.env['ir.cron'] |
|
|
|
|
|
|
|
|
|
|
|
@mock.patch(MOCK_PATH + '.datetime') |
|
|
|
|
|
def test_defaults(self, mocked_dt): |
|
|
|
|
|
mocked_dt.now.return_value = datetime.datetime(2018, 8, 31, 10, 30) |
|
|
|
|
|
cron = self.cron_model.create({ |
|
|
|
|
|
'oneshot': True, |
|
|
|
|
|
'name': 'Foo', |
|
|
|
|
|
'model_id': self.env['ir.model']._get('ir.cron').id, |
|
|
|
|
|
'state': 'code', |
|
|
|
|
|
'code': 'model.some_method()', |
|
|
|
|
|
'interval_number': 1, |
|
|
|
|
|
'interval_type': 'days', |
|
|
|
|
|
'numbercall': 5, # won't have any effect |
|
|
|
|
|
}) |
|
|
|
|
|
self.assertRegexpMatches(cron.name, 'Oneshot#\d+ Foo') |
|
|
|
|
|
self.assertEqual(cron.numbercall, 1) |
|
|
|
|
|
# call postponed by 10mins |
|
|
|
|
|
self.assertEqual(cron.nextcall, '2018-08-31 10:40:00') |
|
|
|
|
|
|
|
|
|
|
|
def test_schedule_oneshot_check(self): |
|
|
|
|
|
with self.assertRaises(AssertionError) as err: |
|
|
|
|
|
self.cron_model.schedule_oneshot('res.partner') |
|
|
|
|
|
self.assertEqual(str(err.exception), 'Provide a method or some code!') |
|
|
|
|
|
|
|
|
|
|
|
@mock.patch(MOCK_PATH + '.datetime') |
|
|
|
|
|
def test_schedule_oneshot_method(self, mocked_dt): |
|
|
|
|
|
mocked_dt.now.return_value = datetime.datetime(2018, 8, 31, 16, 30) |
|
|
|
|
|
cron = self.cron_model.schedule_oneshot( |
|
|
|
|
|
'res.partner', method='read', delay=('minutes', 30)) |
|
|
|
|
|
self.assertRegexpMatches(cron.name, 'Oneshot#\d+') |
|
|
|
|
|
self.assertEqual(cron.numbercall, 1) |
|
|
|
|
|
self.assertEqual(cron.code, 'model.read()') |
|
|
|
|
|
self.assertEqual( |
|
|
|
|
|
cron.model_id, self.env['ir.model']._get('res.partner')) |
|
|
|
|
|
self.assertEqual(cron.nextcall, '2018-08-31 17:00:00') |
|
|
|
|
|
|
|
|
|
|
|
def test_schedule_oneshot_code(self): |
|
|
|
|
|
cron = self.cron_model.schedule_oneshot( |
|
|
|
|
|
'res.partner', code='env["res.partner"].search([])') |
|
|
|
|
|
self.assertRegexpMatches(cron.name, 'Oneshot#\d+') |
|
|
|
|
|
self.assertEqual(cron.numbercall, 1) |
|
|
|
|
|
self.assertEqual(cron.state, 'code') |
|
|
|
|
|
self.assertEqual(cron.code, 'env["res.partner"].search([])') |
|
|
|
|
|
self.assertEqual( |
|
|
|
|
|
cron.model_id, self.env['ir.model']._get('res.partner')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OneshotProcessTestCase(common.TransactionCase): |
|
|
|
|
|
|
|
|
|
|
|
def setUp(self): |
|
|
|
|
|
super().setUp() |
|
|
|
|
|
deleted = [] |
|
|
|
|
|
|
|
|
|
|
|
@api.multi |
|
|
|
|
|
def unlink(self): |
|
|
|
|
|
deleted.extend(self.ids) |
|
|
|
|
|
# do nothing as the original one will try to read the lock |
|
|
|
|
|
# for the current record which is NOT committed |
|
|
|
|
|
# and has no real ID. |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
self.env['ir.cron']._patch_method('unlink', unlink) |
|
|
|
|
|
self.addCleanup(self.env['ir.cron']._revert_method, 'unlink') |
|
|
|
|
|
self.deleted = deleted |
|
|
|
|
|
|
|
|
|
|
|
def test_schedule_oneshot_cleanup(self): |
|
|
|
|
|
cron1 = self.env['ir.cron'].schedule_oneshot( |
|
|
|
|
|
'res.partner', code='env["res.partner"].search([])') |
|
|
|
|
|
cron2 = self.env['ir.cron'].schedule_oneshot( |
|
|
|
|
|
'res.partner', code='env["res.partner"].read([])') |
|
|
|
|
|
# simulate excuted |
|
|
|
|
|
cron1.write({'numbercall': 0, 'active': False}) |
|
|
|
|
|
self.env['ir.cron'].cron_oneshot_cleanup() |
|
|
|
|
|
self.assertIn(cron1.id, self.deleted) |
|
|
|
|
|
self.assertNotIn(cron2.id, self.deleted) |