소스 검색

add timing test and fix it

tangs 6 년 전
부모
커밋
6f217da809
2개의 변경된 파일146개의 추가작업 그리고 36개의 파일을 삭제
  1. 44 20
      timing.py
  2. 102 16
      timing_test.py

+ 44 - 20
timing.py

@@ -14,6 +14,7 @@ def generate_task_id():
 class Timing:
     def __init__(self, sleep_interval=1):
         self.task = {}
+        self.is_running = False
         self.lock = threading.Lock()
         self.sleep_interval = sleep_interval
 
@@ -43,22 +44,27 @@ class Timing:
             count = 0
 
         self.lock.acquire()
-        self.task[task_id] = {'name': name, 'interval': interval, 'func': func, 'count': count, '__count': 0,
-                              'args': args, 'kwargs': kwargs}
+        # exec_num: It is times which task has executed.
+        task = {'name': name, 'interval': interval, 'func': func, 'exec_num': 0,
+                'args': args, 'kwargs': kwargs}
+        if count > 0:
+            task['count'] = count
+
+        self.task[task_id] = task
         self.lock.release()
 
-    def delete_task(self, task_id):
+    def delete_tasks(self, task_ids):
         """
-        Delete the task from schedule by task_id, if exist, return it.
-        :param task_id: Unique task id.
+        Delete the task from schedule by multi task_ids, if exist, return these.
+        :param task_ids: multi task id.
         :return:
         """
-        element = None
-        self.lock.acquire()
-        if self.task.__contains__(task_id):
-            element = self.task.pop(task_id)
-        self.lock.release()
-        return element
+        elements = []
+        for key in task_ids:
+            if self.task.__contains__(key):
+                element = self.task.pop(key)
+                elements.append(element)
+        return elements
 
     def set_interval(self, interval):
         self.sleep_interval = interval
@@ -66,30 +72,44 @@ class Timing:
     def sleep(self):
         time.sleep(self.sleep_interval)
 
+    def stop(self):
+        self.is_running = False
+
     def run(self):
+        self.is_running = True
         while True:
+            if not self.is_running:
+                logging.debug('[TIMING] timing server will end.')
+                break
+
+            logging.debug('[TIMING] run with tasks length: %s', len(self.task))
             clear_keys = []
             self.lock.acquire()
-            for task_id in self.task.keys():
-                task_detail = self.task[task_id]
+            tasks = self.task
+            self.lock.release()
+
+            for task_id in tasks.keys():
+                task_detail = tasks[task_id]
                 try:
                     now = int(datetime.datetime.now().timestamp() * 1000)
                     interval = task_detail['interval']
                     if interval - (now % interval) > 1:
                         continue
                     t = threading.Thread(target=task_detail['func'], name=task_detail['name'])
+                    t.setDaemon(True)
                     t.start()
 
-                    task_detail['__count'] = task_detail['__count'] + 1
-                    if task_detail['__count'] >= task_detail['count']:
+                    task_detail['exec_num'] = task_detail['exec_num'] + 1
+                    if task_detail.__contains__('count') and task_detail['exec_num'] >= task_detail['count']:
                         clear_keys.append(task_id)
                 except Exception as e:
                     logging.error('[TIMING] timing meet error, id: %s, name: %s, error: %s',
                                   task_id, task_detail['name'], e)
-            self.lock.release()
 
-            for key in clear_keys:
-                self.delete_task(key)
+            # clear past due keys
+            self.lock.acquire()
+            self.delete_tasks(clear_keys)
+            self.lock.release()
             self.sleep()
 
 
@@ -100,8 +120,8 @@ def add_task(name, interval, func, count, task_id=generate_task_id(), *args, **k
     defaultTiming.add_task(name, interval, func, count, task_id, *args, **kwargs)
 
 
-def delete_task(task_id):
-    defaultTiming.delete_task(task_id)
+def delete_tasks(task_ids):
+    defaultTiming.delete_tasks(task_ids)
 
 
 def set_interval(interval):
@@ -110,3 +130,7 @@ def set_interval(interval):
 
 def run():
     defaultTiming.run()
+
+
+def stop():
+    defaultTiming.stop()

+ 102 - 16
timing_test.py

@@ -3,31 +3,117 @@
 
 import unittest
 import timing
-import time
 import threading
+import time
+
+exec_num = 0
 
 
 class TimingTest(unittest.TestCase):
+    def func(self):
+        global exec_num
+        self.name = 'TANGS TIMING TEST'
+        exec_num += 1
+        print(self.name)
+
     @staticmethod
-    def print_1():
-        print(1)
+    def reset():
+        global exec_num
+        exec_num = 0
 
-    def test_timing_run(self):
-        print('test_timing_run start')
-        time_start = time.time()
-        p1 = self.print_1
-        timing.add_task('task1', 3, p1, 3)
+    @staticmethod
+    def timing_start():
         t = threading.Thread(target=timing.run)
         t.setDaemon(True)
         t.start()
-        t.join(10)
-
-        time_end = time.time()
-        # print('start')
-        # time.sleep(10)
-        # print('end')
-        self.assertEqual(len(timing.defaultTiming.task), 0)
-        self.assertEqual(int(time_end - time_start), 10)
+
+    def test_timing_run(self):
+        # add task but invalid task_id
+        err = None
+        try:
+            timing.add_task(1, 1, self.func, 1, 1)
+        except Exception as e:
+            err = str(e)
+        self.assertEqual(err, 'task_id must be str')
+
+        # add task but invalid interval
+        err = None
+        try:
+            timing.add_task(1, '1', self.func, 1, 'generate_id')
+        except Exception as e:
+            err = str(e)
+        self.assertEqual(err, 'interval must be int')
+
+        # add task but interval must be bigger than 0
+        err = None
+        try:
+            timing.add_task(1, -1, self.func, 1, 'generate_id')
+        except Exception as e:
+            err = str(e)
+        self.assertEqual(err, 'interval must be bigger than 0')
+
+        # add task but func is not function
+        err = None
+        try:
+            timing.add_task(1, 1, 1, 1, 'generate_id')
+        except Exception as e:
+            err = str(e)
+        self.assertEqual(err, 'func must be func')
+
+        # add task but count is not int
+        err = None
+        try:
+            timing.add_task(1, 1, self.func, '1', 'generate_id')
+        except Exception as e:
+            err = str(e)
+        self.assertEqual(err, 'count must be int')
+
+        timing.set_interval(1)
+        timer = timing.Timing()
+        timing.defaultTiming = timer
+        #
+        # # add task success
+        # self.timing_start()
+        # timing.add_task(1, 1, self.func, 1, 'generate_id')
+        # self.assertEqual(len(timer.task), 1)
+        # time.sleep(1.5)
+        # timing.stop()
+        # self.assertEqual(exec_num, 1)
+        # self.assertEqual(len(timer.task), 0)
+        # time.sleep(1)
+        # self.reset()
+        #
+        # # add task with count 3, wait 3.5, success
+        # self.timing_start()
+        # timing.add_task(1, 1, self.func, 3, 'generate_id')
+        # self.assertEqual(len(timer.task), 1)
+        # time.sleep(3.5)
+        # timing.stop()
+        # self.assertEqual(exec_num, 3)
+        # self.assertEqual(len(timer.task), 0)
+        # time.sleep(1)
+        # self.reset()
+
+        # add task with count 4, wait 3.5, success
+        timing.set_interval(1.2)
+        self.timing_start()
+        timing.add_task(1, 1, self.func, 4, 'generate_id')
+        time.sleep(3)
+        timing.stop()
+        # self.assertAlmostEqual(exec_num, 3, delta=1)
+        self.assertEqual(exec_num, 3)
+        time.sleep(1)
+        self.reset()
+
+        # add task with count less than 0, success
+        print('-----------------------------------------')
+        timing.set_interval(1.2)
+        self.timing_start()
+        timing.add_task(1, 1, self.func, -1, 'generate_id')
+        time.sleep(3)
+        timing.stop()
+        self.assertEqual(exec_num, 3)
+        self.reset()
 
 
 if __name__ == '__main__':