github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/jujupy/tests/test_timeout.py (about) 1 from argparse import Namespace 2 from contextlib import contextmanager 3 import datetime 4 import random 5 from signal import SIGTERM 6 from unittest import TestCase 7 8 try: 9 from mock import ( 10 call, 11 patch, 12 ) 13 except ImportError: 14 from unittest.mock import ( 15 call, 16 patch, 17 ) 18 19 from jujupy.timeout import ( 20 main, 21 parse_args, 22 run_command, 23 signals, 24 ) 25 from tests import parse_error 26 27 28 class TestParseArgs(TestCase): 29 30 def test_parse_args(self): 31 args, command = parse_args(['500', 'foo', 'bar']) 32 self.assertEqual(args, Namespace(duration=500.0, signal='TERM')) 33 self.assertEqual(command, ['foo', 'bar']) 34 35 def test_parse_args_command_options(self): 36 args, command = parse_args(['500', 'foo', '--bar']) 37 self.assertEqual(args, Namespace(duration=500.0, signal='TERM')) 38 self.assertEqual(command, ['foo', '--bar']) 39 40 def test_parse_args_signal(self): 41 args, command = parse_args(['500', '--', 'foo', '--signal']) 42 self.assertEqual(args, Namespace(duration=500.0, signal='TERM')) 43 self.assertEqual(command, ['foo', '--signal']) 44 45 def test_parse_args_signal_novalue(self): 46 with parse_error(self) as stderr: 47 args, command = parse_args(['500', 'foo', '--signal']) 48 self.assertRegexpMatches( 49 stderr.getvalue(), 'argument --signal: expected one argument') 50 51 52 class TestMain(TestCase): 53 54 def test_main(self): 55 signal_name, signal_value = random.choice(list(signals.items())) 56 with patch('jujupy.timeout.run_command', autospec=True) as rc_mock: 57 main(['500', '--signal', signal_name, 'foo', 'bar']) 58 rc_mock.assert_called_once_with(500, signal_value, ['foo', 'bar']) 59 60 61 class TestRunCommand(TestCase): 62 63 @contextmanager 64 def patch_po(self): 65 with patch('subprocess.Popen', autospec=True) as po_mock: 66 with patch('time.sleep') as sleep_mock: 67 yield po_mock, po_mock.return_value.poll, sleep_mock 68 69 def test_run_and_poll(self): 70 with self.patch_po() as (po_mock, poll_mock, sleep_mock): 71 poll_mock = po_mock.return_value.poll 72 poll_mock.return_value = 123 73 self.assertEqual(run_command(57.5, SIGTERM, ['ls', 'foo']), 74 123) 75 po_mock.assert_called_once_with(['ls', 'foo'], creationflags=0) 76 poll_mock.assert_called_once_with() 77 self.assertEqual(sleep_mock.call_count, 0) 78 79 def test_multiple_polls(self): 80 with self.patch_po() as (po_mock, poll_mock, sleep_mock): 81 poll_mock.side_effect = [None, None, 123, 124] 82 self.assertEqual(run_command(57.5, SIGTERM, ['ls', 'foo']), 83 123) 84 self.assertEqual( 85 poll_mock.mock_calls, [call(), call(), call()]) 86 self.assertEqual( 87 sleep_mock.mock_calls, [call(0.1), call(0.1)]) 88 89 def test_duration_elapsed(self): 90 start = datetime.datetime(2015, 1, 1) 91 middle = start + datetime.timedelta(seconds=57.4) 92 end = start + datetime.timedelta(seconds=57.6) 93 with self.patch_po() as (po_mock, poll_mock, sleep_mock): 94 poll_mock.side_effect = [None, None, None, None] 95 with patch('utility.until_timeout.now') as utn_mock: 96 utn_mock.side_effect = [start, middle, end, end] 97 self.assertEqual(run_command(57.5, SIGTERM, ['ls', 'foo']), 98 124) 99 self.assertEqual( 100 poll_mock.mock_calls, [call(), call()]) 101 self.assertEqual( 102 sleep_mock.mock_calls, [call(0.1), call(0.1)]) 103 self.assertEqual(utn_mock.mock_calls, [call(), call(), call()]) 104 po_mock.return_value.send_signal.assert_called_once_with(SIGTERM) 105 po_mock.return_value.wait.assert_called_once_with()