Files
deb-python-oslo.service/tests/unit/test_periodic.py
Zhongyue Luo cd8e53c37d Use timestamp in periodic tasks
All time related data in periodic tasks are in seconds.
Therefore creating datetime objects only adds overhead to the module.
This patch replaces all datetime objects with utc timestamps in periodic_tasks.
Changes to test scripts were made accordingly.

Change-Id: I5bf77fba26aac62856fe30585577b7cf66dd6257
2014-02-14 03:34:07 +00:00

254 lines
8.3 KiB
Python

# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Unit Tests for periodic_task decorator and PeriodicTasks class.
"""
import mock
from openstack.common.fixture import config
from openstack.common import periodic_task
from openstack.common import test
from testtools import matchers
class AnException(Exception):
pass
class AService(periodic_task.PeriodicTasks):
def __init__(self):
super(AService, self).__init__()
self.called = {'doit': 0, 'urg': 0, 'ticks': 0}
@periodic_task.periodic_task
def doit(self, context):
self.called['doit'] += 1
@periodic_task.periodic_task
def crashit(self, context):
self.called['urg'] += 1
raise AnException('urg')
@periodic_task.periodic_task(spacing=10, run_immediately=True)
def doit_with_kwargs_odd(self, context):
self.called['ticks'] += 1
class PeriodicTasksTestCase(test.BaseTestCase):
"""Test cases for PeriodicTasks."""
def test_is_called(self):
serv = AService()
serv.run_periodic_tasks(None)
self.assertEqual(serv.called['doit'], 1)
self.assertEqual(serv.called['urg'], 1)
self.assertEqual(serv.called['ticks'], 1)
def test_called_twice(self):
serv = AService()
serv.run_periodic_tasks(None)
serv.run_periodic_tasks(None)
self.assertEqual(serv.called['doit'], 2)
self.assertEqual(serv.called['urg'], 2)
# doit_with_kwargs_odd will only be called the first time because its
# spacing time interval will not have elapsed between the calls.
self.assertEqual(serv.called['ticks'], 1)
def test_raises(self):
serv = AService()
self.assertRaises(AnException,
serv.run_periodic_tasks,
None, raise_on_error=True)
class ManagerMetaTestCase(test.BaseTestCase):
"""Tests for the meta class which manages the creation of periodic tasks.
"""
def test_meta(self):
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task
def foo(self):
return 'foo'
@periodic_task.periodic_task(spacing=4)
def bar(self):
return 'bar'
@periodic_task.periodic_task(enabled=False)
def baz(self):
return 'baz'
m = Manager()
self.assertThat(m._periodic_tasks, matchers.HasLength(2))
self.assertIsNone(m._periodic_spacing['foo'])
self.assertEqual(4, m._periodic_spacing['bar'])
self.assertThat(
m._periodic_spacing, matchers.Not(matchers.Contains('baz')))
class ManagerTestCase(test.BaseTestCase):
"""Tests the periodic tasks portion of the manager class."""
def setUp(self):
super(ManagerTestCase, self).setUp()
self.config = self.useFixture(config.Config()).config
def test_periodic_tasks_with_idle(self):
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=200)
def bar(self):
return 'bar'
m = Manager()
self.assertThat(m._periodic_tasks, matchers.HasLength(1))
self.assertEqual(200, m._periodic_spacing['bar'])
# Now a single pass of the periodic tasks
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(60, idle, 1)
def test_periodic_tasks_constant(self):
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=0)
def bar(self):
return 'bar'
m = Manager()
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(60, idle, 1)
@mock.patch('time.time')
def test_periodic_tasks_idle_calculation(self, mock_time):
fake_time = 32503680000.0
mock_time.return_value = fake_time
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=10)
def bar(self, context):
return 'bar'
m = Manager()
# Ensure initial values are correct
self.assertEqual(1, len(m._periodic_tasks))
task_name, task = m._periodic_tasks[0]
# Test task values
self.assertEqual('bar', task_name)
self.assertEqual(10, task._periodic_spacing)
self.assertEqual(True, task._periodic_enabled)
self.assertEqual(False, task._periodic_external_ok)
self.assertEqual(False, task._periodic_immediate)
self.assertAlmostEqual(32503680000.0,
task._periodic_last_run)
# Test the manager's representation of those values
self.assertEqual(10, m._periodic_spacing[task_name])
self.assertAlmostEqual(32503680000.0,
m._periodic_last_run[task_name])
mock_time.return_value = fake_time + 5
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(5, idle, 1)
self.assertAlmostEqual(32503680000.0,
m._periodic_last_run[task_name])
mock_time.return_value = fake_time + 10
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(10, idle, 1)
self.assertAlmostEqual(32503680010.0,
m._periodic_last_run[task_name])
@mock.patch('time.time')
def test_periodic_tasks_immediate_runs_now(self, mock_time):
fake_time = 32503680000.0
mock_time.return_value = fake_time
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=10, run_immediately=True)
def bar(self, context):
return 'bar'
m = Manager()
# Ensure initial values are correct
self.assertEqual(1, len(m._periodic_tasks))
task_name, task = m._periodic_tasks[0]
# Test task values
self.assertEqual('bar', task_name)
self.assertEqual(10, task._periodic_spacing)
self.assertEqual(True, task._periodic_enabled)
self.assertEqual(False, task._periodic_external_ok)
self.assertEqual(True, task._periodic_immediate)
self.assertIsNone(task._periodic_last_run)
# Test the manager's representation of those values
self.assertEqual(10, m._periodic_spacing[task_name])
self.assertIsNone(m._periodic_last_run[task_name])
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(32503680000.0,
m._periodic_last_run[task_name])
self.assertAlmostEqual(10, idle, 1)
mock_time.return_value = fake_time + 5
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(5, idle, 1)
def test_periodic_tasks_disabled(self):
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=-1)
def bar(self):
return 'bar'
m = Manager()
idle = m.run_periodic_tasks(None)
self.assertAlmostEqual(60, idle, 1)
def test_external_running_here(self):
self.config(run_external_periodic_tasks=True)
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=200, external_process_ok=True)
def bar(self):
return 'bar'
m = Manager()
self.assertThat(m._periodic_tasks, matchers.HasLength(1))
def test_external_running_elsewhere(self):
self.config(run_external_periodic_tasks=False)
class Manager(periodic_task.PeriodicTasks):
@periodic_task.periodic_task(spacing=200, external_process_ok=True)
def bar(self):
return 'bar'
m = Manager()
self.assertEqual([], m._periodic_tasks)