~abentley/workspace-runner/enhanced-artifacts

« back to all changes in this revision

Viewing changes to workspace_runner/tests/__init__.py

  • Committer: Aaron Bentley
  • Date: 2015-06-19 20:15:41 UTC
  • Revision ID: aaron.bentley@canonical.com-20150619201541-087rgzjy0epvgffo
Move fake/ssh distinction to a Primitives class that always has a workspace.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
from argparse import Namespace
 
2
from contextlib import contextmanager
2
3
from mock import patch
3
4
from StringIO import StringIO
4
 
from tempfile import NamedTemporaryFile
 
5
from tempfile import (
 
6
    mkdtemp,
 
7
    NamedTemporaryFile,
 
8
    )
5
9
from unittest import TestCase
6
10
 
7
11
from yaml import safe_dump
8
12
 
9
13
from workspace_runner import (
10
14
    parse_args,
 
15
    Primitives,
11
16
    workspace_run,
12
17
    Runner,
13
 
    SSHRunner,
 
18
    RunnerNotReady,
 
19
    SSHPrimitives,
14
20
    )
15
21
 
16
22
 
21
27
        self.assertEqual(args, Namespace(config='foo', host='bar'))
22
28
 
23
29
 
24
 
class FakeRunner(Runner):
25
 
    """"Class that pretends to run commands."""
 
30
class FakePrimitives(Primitives):
26
31
 
27
 
    last_instance = None
 
32
    def __init__(self, host, tempdir):
 
33
        super(FakePrimitives, self).__init__(host, tempdir)
 
34
        self.run_calls = []
28
35
 
29
36
    @classmethod
30
 
    def factory(cls, host):
31
 
        instance = cls(host)
32
 
        cls.last_instance = instance
33
 
        return instance
34
 
 
35
 
    def __init__(self, host):
36
 
        super(FakeRunner, self).__init__(host)
37
 
        self.run_calls = []
 
37
    def mktemp(cls, host):
 
38
        return mkdtemp()
38
39
 
39
40
    def run(self, args, out_file):
40
41
        self.run_calls.append(args)
41
42
        out_file.write(''.join(args))
42
43
 
43
44
 
44
 
class TestRunnerClass:
 
45
class TestPrimitives:
45
46
 
46
 
    def test_host(self):
47
 
        runner = self.runner_class('asdf')
48
 
        self.assertEqual(runner.host, 'asdf')
 
47
    @contextmanager
 
48
    def primitives_context(self):
 
49
        with Runner('asdf', self.primitives_class) as primitives:
 
50
            yield primitives
49
51
 
50
52
    def test_run(self):
51
 
        runner = self.runner_class('asdf')
52
53
        out_file = StringIO()
53
 
        self.expect_run(runner, ['foo', 'bar'], out_file)
 
54
        with self.primitives_context() as primitives:
 
55
            self.expect_run(primitives, ['foo', 'bar'], out_file)
54
56
        self.assertEqual(out_file.getvalue(), 'foobar')
55
57
 
56
58
 
57
 
class TestSSHRunner(TestRunnerClass, TestCase):
58
 
 
59
 
    runner_class = SSHRunner
 
59
class RunnerFactory:
 
60
 
 
61
    def __init__(self):
 
62
        last_instance = None
 
63
 
 
64
    def factory(self, host, primitives_class):
 
65
        instance = Runner(host, primitives_class)
 
66
        self.last_instance = instance
 
67
        return instance
 
68
 
 
69
 
 
70
class TestSSHPrimitives(TestPrimitives, TestCase):
 
71
 
 
72
    primitives_class = SSHPrimitives
 
73
 
 
74
    @contextmanager
 
75
    def primitives_context(self):
 
76
        with patch('subprocess.check_output') as co_mock:
 
77
            with Runner('asdf', self.primitives_class) as primitives:
 
78
                yield primitives
 
79
        co_mock.assert_called_once_with(
 
80
            ['ssh', 'asdf', 'mktemp', '--directory'])
60
81
 
61
82
    def expect_run(self, runner, args, out_file):
62
83
        def effect(args, stdout):
64
85
 
65
86
        with patch('subprocess.check_call', side_effect=effect,
66
87
                   autospec=True) as cc_mock:
67
 
            runner.run(args, out_file)
 
88
            with patch('subprocess.check_output', autospec=True) as co_mock:
 
89
                runner.run(args, out_file)
68
90
        cc_mock.assert_called_once_with(['ssh', 'asdf'] + args,
69
91
                                        stdout=out_file)
70
92
 
71
93
 
72
 
class TestFakeRunner(TestRunnerClass, TestCase):
 
94
class TestFakePrimitives(TestPrimitives, TestCase):
73
95
 
74
 
    runner_class = FakeRunner
 
96
    primitives_class = FakePrimitives
75
97
 
76
98
    def expect_run(self, runner, args, out_file):
77
99
        runner.run(args, out_file)
78
100
        self.assertEqual(runner.run_calls, [['foo', 'bar']])
79
101
 
80
102
 
 
103
class TestRunnerClass:
 
104
 
 
105
    def test_host(self):
 
106
        runner = Runner('asdf', self.primitives_class)
 
107
        self.assertEqual(runner.host, 'asdf')
 
108
 
 
109
 
 
110
class TestRunner(TestRunnerClass, TestCase):
 
111
 
 
112
    primitives_class = SSHPrimitives
 
113
 
 
114
    def expect_run(self, runner, args, out_file):
 
115
        def effect(args, stdout):
 
116
            stdout.write(''.join(args[2:]))
 
117
 
 
118
        with patch('subprocess.check_call', side_effect=effect,
 
119
                   autospec=True) as cc_mock:
 
120
            with patch('subprocess.check_output', autospec=True) as co_mock:
 
121
                runner.run(args, out_file)
 
122
        cc_mock.assert_called_once_with(['ssh', 'asdf'] + args,
 
123
                                        stdout=out_file)
 
124
 
 
125
 
81
126
class TestWorkspaceRun(TestCase):
82
127
 
83
128
    def test_minimal(self):
 
129
        runner_factory = RunnerFactory()
84
130
        with NamedTemporaryFile() as config_file:
85
131
            safe_dump({'command': ['run', 'this']}, config_file)
86
 
            workspace_run([config_file.name, 'bar'], FakeRunner.factory)
87
 
        runner = FakeRunner.last_instance
 
132
            workspace_run([config_file.name, 'bar'], runner_factory.factory,
 
133
                          FakePrimitives)
 
134
        runner = runner_factory.last_instance
88
135
        self.assertIsNot(runner, None)
89
 
        self.assertEqual(runner.run_calls, [['run', 'this']])
 
136
        self.assertEqual(runner.primitives.run_calls, [['run', 'this']])