Source code for armi.utils.tests.test_codeTiming

# Copyright 2019 TerraPower, LLC
#
# 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 code timing."""

import time
import unittest

from armi.utils import codeTiming


[docs] class CodeTimingTest(unittest.TestCase): def setUp(self): codeTiming._Timer._frozen = False codeTiming.MasterTimer._instance = None def tearDown(self): codeTiming._Timer._frozen = False codeTiming.MasterTimer._instance = None
[docs] def test_methodDefinitions(self): """Test that the timer decorators work and don't interupt the code.""" @codeTiming.timed def someMethod(boop): time.sleep(0.01) return boop @codeTiming.timed("I have this name") def someOtherMethod(boop): time.sleep(0.01) return boop # verify the decorator allows the code to run x = someMethod("dingdong") y = someOtherMethod("bingbong") self.assertEqual(x, "dingdong") self.assertEqual(y, "bingbong") # verify the decorators work table = codeTiming.MasterTimer.report(inclusionCutoff=0.01, totalTime=True) self.assertIn(" AVERAGE ", table) self.assertIn(" CUMULATIVE ", table) self.assertIn(" NUM ITERS", table) self.assertIn("TIMER REPORTS ", table) self.assertIn("TOTAL TIME ", table) self.assertIn("someMethod", table) self.assertIn("I have this name", table)
[docs] def test_countStartsStops(self): """Test the start and stop counting logic.""" # test the start() and stop() methods, and their side effects master = codeTiming.MasterTimer.getMasterTimer() timer = master.startTimer("bananananana") t0 = timer.stop() self.assertEqual(timer.overStart, 0) # run start a few times in a row, to trip the overstart for i in range(5): time.sleep(0.01) t1 = timer.start() self.assertGreater(t1, t0) t0 = t1 self.assertEqual(timer.overStart, i) # run stop a few times in a row, which is allowed for race conditions for i in range(5): time.sleep(0.01) t2 = timer.stop() self.assertGreater(t2, t1) t1 = t2 self.assertEqual(timer.overStart, 3 - i if 3 - i > 0 else 0) # start will always work from a stopped state time.sleep(0.01) t6 = timer.start() self.assertGreater(t6, t2) self.assertEqual(timer.overStart, 0) # start a second timer to show two can run at once time.sleep(0.01) timer2 = master.endTimer("wazzlewazllewazzzle") t7 = timer2.start() self.assertGreater(t7, t6) self.assertEqual(timer2.overStart, 0) # use the timers as context managers with timer2: with timer: pass # There should be one start/stop each, leaving the over start count the same self.assertEqual(timer.overStart, 0) self.assertEqual(timer2.overStart, 0)
[docs] def test_propertyAccess(self): """Test property access is okay.""" master = codeTiming.MasterTimer.getMasterTimer() timer = master.startTimer("sometimer") t0 = timer.time time.sleep(0.01) self.assertGreaterEqual(t0, 0) ts = timer.times self.assertEqual(len(ts), 1) self.assertEqual(len(ts[0]), 2) self.assertGreaterEqual(ts[0][0], 0) self.assertGreaterEqual(ts[0][1], 0) tName = timer.name self.assertEqual(tName, "sometimer") tActive = timer.isActive self.assertTrue(tActive)
[docs] def test_master(self): master = codeTiming.MasterTimer.getMasterTimer() _ = master.time master.startAll() actives = master.getActiveTimers() self.assertEqual(list(master.timers.values()), actives) master.stopAll() actives = master.getActiveTimers() self.assertEqual([], actives) with self.assertRaises(RuntimeError): codeTiming.MasterTimer()
[docs] def test_messyStartsAndStops(self): master = codeTiming.MasterTimer.getMasterTimer() name = "sometimerthatihaventmadeyet" larger_time_start = master.time() time.sleep(0.01) timer = master.getTimer(name) time.sleep(0.01) lesser_time_start = master.time() timer.start() # 1st time pair timer.start() # 2nd time pair timer.start() # 3rd time pair timer.stop() self.assertIn(name, str(timer)) self.assertTrue(timer.isActive) timer.stop() timer.stop() self.assertFalse(timer.isActive) timer.stop() timer.stop() timer.start() # 4th time pair self.assertTrue(timer.isActive) lesser_time_end = master.time() time.sleep(0.01) timer.stop() self.assertIn(name, str(timer)) self.assertEqual(len(timer.times), 4) time.sleep(0.01) larger_time_end = master.time() # even with all the starts and stops the total time needs to be between these two values. self.assertGreater(timer.time, lesser_time_end - lesser_time_start) self.assertLess(timer.time, larger_time_end - larger_time_start) self.assertEqual(timer.numIterations, 3)
[docs] def test_report(self): master = codeTiming.MasterTimer.getMasterTimer() name1 = "test_report1" timer1 = master.getTimer(name1) timer1.start() time.sleep(0.01) timer1.stop() name2 = "test_report2" timer2 = master.getTimer(name2) timer2.start() time.sleep(0.01) timer2.stop() # basic validation of the reports table = codeTiming.MasterTimer.report(inclusionCutoff=0.01, totalTime=True) self.assertIn(" AVERAGE ", table) self.assertIn(" CUMULATIVE ", table) self.assertIn(" NUM ITERS", table) self.assertIn("TIMER REPORTS ", table) self.assertIn(name1, table) self.assertIn(name2, table) lines = table.strip().split("\n") self.assertEqual(len(lines), 4) self.assertEqual(len(lines[1].strip().split()), 4) self.assertEqual(len(lines[2].strip().split()), 4)