class TestWorker(object): def setup(self): with patch('%s.Config' % pbm) as mock_config: self.cls = Worker() self.config = mock_config.return_value def test_parse_args(self): argv = ['-V'] res = self.cls.parse_args(argv) assert isinstance(res, argparse.Namespace) assert res.version is True def test_parse_args_parser(self): argv = ['-V'] desc = 'PiFace input change event queue processor/worker' with patch('%s.argparse.ArgumentParser' % pbm, spec_set=argparse.ArgumentParser) as mock_parser: self.cls.parse_args(argv) assert mock_parser.mock_calls == [ call(description=desc), call().add_argument('-w', '--no-process', dest='process_events', action='store_false', default=True, help='do not process events, just log what ' 'would be done (note this will cause events to ' 'pile up on disk)'), call().add_argument('-v', '--verbose', dest='verbose', action='count', default=0, help='verbose output. specify twice ' 'for debug-level output.'), call().add_argument('-V', '--version', dest='version', action='store_true', default=False, help='print version number and exit.'), call().parse_args(argv), ] def test_entry_point_version(self, capsys): argv = ['piface-worker', '-V'] with patch.object(sys, 'argv', argv): with patch('%s.run' % pb) as mock_run: with pytest.raises(SystemExit) as excinfo: self.cls.console_entry_point() out, err = capsys.readouterr() assert out == "pyface-webhooks %s " \ "<https://github.com/jantman/piface_webhooks>\n" % VERSION assert err == '' assert excinfo.value.code == 0 assert mock_run.mock_calls == [] def test_entry_verbose(self, capsys): argv = ['piface-worker', '-v'] with patch.object(sys, 'argv', argv): with patch('%s.logger.setLevel' % pbm) as mock_set_level: with patch('%s.run' % pb) as mock_run: self.cls.console_entry_point() out, err = capsys.readouterr() assert out == '' assert err == '' assert mock_set_level.mock_calls == [call(logging.INFO)] assert mock_run.mock_calls == [call()] def test_entry_debug(self, capsys): argv = ['piface-worker', '-vv'] with patch.object(sys, 'argv', argv): with patch('%s.logger.setLevel' % pbm) as mock_set_level: with patch('%s.run' % pb) as mock_run: self.cls.console_entry_point() out, err = capsys.readouterr() assert out == '' assert err == '' assert mock_set_level.mock_calls == [call(logging.DEBUG)] assert mock_run.mock_calls == [call()] def test_entry_none(self, capsys): argv = ['piface-worker'] with patch.object(sys, 'argv', argv): with patch('%s.logger.setLevel' % pbm) as mock_set_level: with patch('%s.run' % pb) as mock_run: self.cls.console_entry_point() out, err = capsys.readouterr() assert out == '' assert err == '' assert mock_set_level.mock_calls == [] assert mock_run.mock_calls == [call()] assert self.cls.process_events is True def test_entry_no_write(self, capsys): argv = ['piface-worker', '--no-process'] with patch.object(sys, 'argv', argv): with patch('%s.logger.setLevel' % pbm) as mock_set_level: with patch('%s.run' % pb) as mock_run: self.cls.console_entry_point() out, err = capsys.readouterr() assert out == '' assert err == '' assert mock_set_level.mock_calls == [] assert mock_run.mock_calls == [call()] assert self.cls.process_events is False def test_run(self): with patch('%s._alwaystrue' % pb) as mock_true: with patch('%s.handle_files' % pb) as mock_handle: with patch('%s.logger' % pbm) as mock_logger: mock_true.side_effect = [True, True, False] self.cls.run() assert mock_true.mock_calls == [call(), call(), call()] assert mock_handle.mock_calls == [call(), call()] assert mock_logger.mock_calls == [ call.info("Beginning file handling loop") ] def test_alwaystrue(self): assert self.cls._alwaystrue() is True def test_handle_files(self): flist = [ 'foobar', 'pinevent_1420863332.123456_pin2_state1', 'pinevent_csds_pin3_state1', 'pinevent_1420863326.123456_pin3_state0', 'pinevent_1420863326.123456_pin2_state1', 'xsfjef_fhejfec_dfhe', 'pinevent_1420863326.456789_pin3_state2', ] ex = Exception('foo') def se_handle(fname, evt_datetime, pin, state): if fname == 'pinevent_1420863332.123456_pin2_state1': raise ex type(self.config).QUEUE_PATH = '/foo/bar' with patch('%s.logger' % pbm) as mock_logger: with patch('%s.os.listdir' % pbm) as mock_listdir: with patch('%s.handle_one_file' % pb) as mock_handle: with patch('%s.os.unlink' % pbm) as mock_unlink: mock_listdir.return_value = flist mock_handle.side_effect = se_handle self.cls.handle_files() assert mock_logger.mock_calls == [ call.info("Found %d new events", 3), call.debug('File handled; removing: %s', 'pinevent_1420863326.123456_pin2_state1'), call.debug('File handled; removing: %s', 'pinevent_1420863326.123456_pin3_state0'), call.exception('Execption while handling event file %s', 'pinevent_1420863332.123456_pin2_state1'), ] assert mock_listdir.mock_calls == [call('/foo/bar')] assert mock_handle.mock_calls == [ call('pinevent_1420863326.123456_pin2_state1', datetime(2015, 1, 9, 23, 15, 26, 123456), 2, 1), call('pinevent_1420863326.123456_pin3_state0', datetime(2015, 1, 9, 23, 15, 26, 123456), 3, 0), call('pinevent_1420863332.123456_pin2_state1', datetime(2015, 1, 9, 23, 15, 32, 123456), 2, 1), ] assert mock_unlink.mock_calls == [ call('/foo/bar/pinevent_1420863326.123456_pin2_state1'), call('/foo/bar/pinevent_1420863326.123456_pin3_state0') ] def test_handle_files_keyboard_interrupt(self): flist = [ 'pinevent_1420863332.123456_pin2_state1', 'pinevent_1420863326.123456_pin3_state0', ] def se_handle(fname, evt_datetime, pin, state): if fname == 'pinevent_1420863332.123456_pin2_state1': raise KeyboardInterrupt type(self.config).QUEUE_PATH = '/foo/bar' with patch('%s.logger' % pbm) as mock_logger: with patch('%s.os.listdir' % pbm) as mock_listdir: with patch('%s.handle_one_file' % pb) as mock_handle: with patch('%s.os.unlink' % pbm) as mock_unlink: mock_listdir.return_value = flist mock_handle.side_effect = se_handle with pytest.raises(KeyboardInterrupt): self.cls.handle_files() assert mock_logger.mock_calls == [ call.info("Found %d new events", 2), call.debug('File handled; removing: %s', 'pinevent_1420863326.123456_pin3_state0'), ] assert mock_listdir.mock_calls == [call('/foo/bar')] assert mock_handle.mock_calls == [ call('pinevent_1420863326.123456_pin3_state0', datetime(2015, 1, 9, 23, 15, 26, 123456), 3, 0), call('pinevent_1420863332.123456_pin2_state1', datetime(2015, 1, 9, 23, 15, 32, 123456), 2, 1), ] assert mock_unlink.mock_calls == [ call('/foo/bar/pinevent_1420863326.123456_pin3_state0'), ] def test_handle_files_none(self): flist = [ 'foobar', ] type(self.config).QUEUE_PATH = '/foo/bar' with patch('%s.logger' % pbm) as mock_logger: with patch('%s.os.listdir' % pbm) as mock_listdir: with patch('%s.handle_one_file' % pb) as mock_handle: with patch('%s.os.unlink' % pbm) as mock_unlink: mock_listdir.return_value = flist self.cls.handle_files() assert mock_logger.mock_calls == [] assert mock_listdir.mock_calls == [call('/foo/bar')] assert mock_handle.mock_calls == [] assert mock_unlink.mock_calls == [] def test_handle_one_file(self): def se_exc(*argv): raise Exception() mock_cb1 = Mock() mock_cb2 = Mock() mock_cb2.side_effect = se_exc cbs = [mock_cb1, mock_cb2] pins = [ {'name': 'pin0', 'states': ['pin0state0', 'pin0state1']}, {'name': 'pin1', 'states': ['pin1state0', 'pin1state1']}, {'name': 'pin2', 'states': ['pin2state0', 'pin2state1']}, {'name': 'pin3', 'states': ['pin3state0', 'pin3state1']}, ] type(self.config).CALLBACKS = cbs type(self.config).PINS = pins with patch('%s.logger' % pbm) as mock_logger: self.cls.handle_one_file( 'myfname', datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0) assert mock_logger.mock_calls == [ call.debug("Handling event: pin=%d state=%d dt=%s (%s)", 2, 0, datetime(2015, 2, 13, 1, 2, 3, 123456), 'myfname'), call.debug("Running callback: %s", mock_cb1), call.debug("Callback finished"), call.debug("Running callback: %s", mock_cb2), call.exception("Callback raised an exception."), call.debug("All callbacks finished.") ] assert mock_cb1.mock_calls == [ call(datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0, 'pin2', 'pin2state0') ] assert mock_cb2.mock_calls == [ call(datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0, 'pin2', 'pin2state0') ] def test_handle_one_file_keyboard_interrupt(self): def se_exc(*argv): raise KeyboardInterrupt() mock_cb1 = Mock() mock_cb2 = Mock() mock_cb2.side_effect = se_exc cbs = [mock_cb1, mock_cb2] pins = [ {'name': 'pin0', 'states': ['pin0state0', 'pin0state1']}, {'name': 'pin1', 'states': ['pin1state0', 'pin1state1']}, {'name': 'pin2', 'states': ['pin2state0', 'pin2state1']}, {'name': 'pin3', 'states': ['pin3state0', 'pin3state1']}, ] type(self.config).CALLBACKS = cbs type(self.config).PINS = pins with patch('%s.logger' % pbm) as mock_logger: with pytest.raises(KeyboardInterrupt): self.cls.handle_one_file( 'myfname', datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0) assert mock_logger.mock_calls == [ call.debug("Handling event: pin=%d state=%d dt=%s (%s)", 2, 0, datetime(2015, 2, 13, 1, 2, 3, 123456), 'myfname'), call.debug("Running callback: %s", mock_cb1), call.debug("Callback finished"), call.debug("Running callback: %s", mock_cb2), ] assert mock_cb1.mock_calls == [ call(datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0, 'pin2', 'pin2state0') ] assert mock_cb2.mock_calls == [ call(datetime(2015, 2, 13, 1, 2, 3, 123456), 2, 0, 'pin2', 'pin2state0') ]
def setup(self): with patch('%s.Config' % pbm) as mock_config: self.cls = Worker() self.config = mock_config.return_value
def test_init(self): with patch('%s.Config' % pbm) as mock_config: cls = Worker() assert mock_config.mock_calls == [call()] assert cls.config == mock_config.return_value assert cls.process_events is True