# # Copyright (c) 2009, 2010 Testrepository Contributors # # Licensed under either the Apache License, Version 2.0 or the BSD 3-clause # license at the users choice. A copy of both licenses are available in the # project source as Apache-2.0 and BSD. You may not use this file except in # compliance with one of these two licences. # # Unless required by applicable law or agreed to in writing, software # distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # license you chose for the specific language governing permissions and # limitations under that license. """Tests for the commands module.""" import optparse import os.path import sys from testresources import TestResource from testtools.matchers import ( IsInstance, MatchesException, raises, ) from testrepository import commands from testrepository.repository import file from testrepository.tests import ResourcedTestCase from testrepository.tests.monkeypatch import monkeypatch from testrepository.tests.stubpackage import ( StubPackageResource, ) from testrepository.ui import cli, model class TemporaryCommand(object): """A temporary command.""" class TemporaryCommandResource(TestResource): def __init__(self, cmd_name): TestResource.__init__(self) cmd_name = cmd_name.replace('-', '_') self.resources.append(('pkg', StubPackageResource('commands', [('%s.py' % cmd_name, """from testrepository.commands import Command class %s(Command): def run(self): pass """ % cmd_name)], init=False))) self.cmd_name = cmd_name def make(self, dependency_resources): pkg = dependency_resources['pkg'] result = TemporaryCommand() result.path = os.path.join(pkg.base, 'commands') commands.__path__.append(result.path) return result def clean(self, resource): commands.__path__.remove(resource.path) name = 'testrepository.commands.%s' % self.cmd_name if name in sys.modules: del sys.modules[name] class TestFindCommand(ResourcedTestCase): resources = [('cmd', TemporaryCommandResource('foo'))] def test_looksupcommand(self): cmd = commands._find_command('foo') self.assertIsInstance(cmd(None), commands.Command) def test_missing_command(self): self.assertThat(lambda: commands._find_command('bar'), raises(KeyError)) def test_sets_name(self): cmd = commands._find_command('foo') self.assertEqual('foo', cmd.name) class TestNameMangling(ResourcedTestCase): resources = [('cmd', TemporaryCommandResource('foo-bar'))] def test_looksupcommand(self): cmd = commands._find_command('foo-bar') self.assertIsInstance(cmd(None), commands.Command) def test_sets_name(self): cmd = commands._find_command('foo-bar') # The name is preserved, so that 'testr commands' shows something # sensible. self.assertEqual('foo-bar', cmd.name) class TestIterCommands(ResourcedTestCase): resources = [ ('cmd1', TemporaryCommandResource('one')), ('cmd2', TemporaryCommandResource('two')), ] def test_iter_commands(self): cmds = list(commands.iter_commands()) cmds = [cmd(None).name for cmd in cmds] # We don't care about all the built in commands cmds = [cmd for cmd in cmds if cmd in ('one', 'two')] self.assertEqual(['one', 'two'], cmds) class TestRunArgv(ResourcedTestCase): def stub__find_command(self, cmd_run): self.calls = [] self.addCleanup(monkeypatch('testrepository.commands._find_command', self._find_command)) self.cmd_run = cmd_run def _find_command(self, cmd_name): self.calls.append(cmd_name) real_run = self.cmd_run class SampleCommand(commands.Command): """A command that is used for testing.""" def execute(self): return real_run(self) return SampleCommand def test_looks_up_cmd(self): self.stub__find_command(lambda x:0) commands.run_argv(['testr', 'foo'], 'in', 'out', 'err') self.assertEqual(['foo'], self.calls) def test_looks_up_cmd_skips_options(self): self.stub__find_command(lambda x:0) commands.run_argv(['testr', '--version', 'foo'], 'in', 'out', 'err') self.assertEqual(['foo'], self.calls) def test_no_cmd_issues_help(self): self.stub__find_command(lambda x:0) commands.run_argv(['testr', '--version'], 'in', 'out', 'err') self.assertEqual(['help'], self.calls) def capture_ui(self, cmd): self.ui = cmd.ui return 0 def test_runs_cmd_with_CLI_UI(self): self.stub__find_command(self.capture_ui) commands.run_argv(['testr', '--version', 'foo'], 'in', 'out', 'err') self.assertEqual(['foo'], self.calls) self.assertIsInstance(self.ui, cli.UI) def test_returns_0_when_None_returned_from_execute(self): self.stub__find_command(lambda x:None) self.assertEqual(0, commands.run_argv(['testr', 'foo'], 'in', 'out', 'err')) def test_returns_execute_result(self): self.stub__find_command(lambda x:1) self.assertEqual(1, commands.run_argv(['testr', 'foo'], 'in', 'out', 'err')) class TestGetCommandParser(ResourcedTestCase): def test_trivial(self): cmd = InstrumentedCommand(model.UI()) parser = commands.get_command_parser(cmd) self.assertThat(parser, IsInstance(optparse.OptionParser)) class InstrumentedCommand(commands.Command): """A command which records methods called on it. The first line is the summary. """ def _init(self): self.calls = [] def execute(self): self.calls.append('execute') return commands.Command.execute(self) def run(self): self.calls.append('run') class TestAbstractCommand(ResourcedTestCase): def test_execute_calls_run(self): cmd = InstrumentedCommand(model.UI()) self.assertEqual(0, cmd.execute()) self.assertEqual(['execute', 'run'], cmd.calls) def test_execute_calls_set_command(self): ui = model.UI() cmd = InstrumentedCommand(ui) cmd.execute() self.assertEqual(cmd, ui.cmd) def test_execute_does_not_run_if_set_command_errors(self): class FailUI(object): def set_command(self, ui): return False cmd = InstrumentedCommand(FailUI()) self.assertEqual(1, cmd.execute()) def test_shows_errors_from_execute_returns_3(self): class FailCommand(commands.Command): def run(self): raise Exception("foo") ui = model.UI() cmd = FailCommand(ui) self.assertEqual(3, cmd.execute()) self.assertEqual(1, len(ui.outputs)) self.assertEqual('error', ui.outputs[0][0]) self.assertThat(ui.outputs[0][1], MatchesException(Exception('foo'))) def test_default_repository_factory(self): cmd = commands.Command(model.UI()) self.assertIsInstance(cmd.repository_factory, file.RepositoryFactory) def test_get_summary(self): cmd = InstrumentedCommand self.assertEqual('A command which records methods called on it.', cmd.get_summary())