~coreygoldberg/uci-engine/subunit-results

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env python
# Ubuntu Continuous Integration Engine
# Copyright 2014 Canonical Ltd.

# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License version 3, as
# published by the Free Software Foundation.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import json
import subprocess
import unittest


from ci_utils import amqp_utils
from ci_utils.testing import features
import deploy
import deployers
from ucitests import (
    assertions,
    fixtures,
)


RABBIT_SERVICE = 'ci-airline-rabbit'


def run_rabbit_cmd(args):
    deployers.juju_run(RABBIT_SERVICE,
                       'sudo rabbitmqctl {}'.format(' '.join(args)))


def create_rabbit_user(user_name, password=None):
    if password is None:
        password = user_name
    run_rabbit_cmd(['add_user', user_name, password])
    run_rabbit_cmd(['set_permissions', '-p', '/', user_name, '".*" ".*" ".*"'])


def delete_rabbit_user(user_name):
    run_rabbit_cmd(['delete_user', user_name])


class SmokeTestTestRunner(deployers.DeployerTest):
    """Integration tests for test runner service run on a juju deployment"""

    def test_worker_running(self):
        '''Ensure the rabbit worker is deployed and running.'''
        # TODO ev 2014-06-16 We should really write status APIs that
        # introspect with these sorts of tests.
        self.assert_job_running('ci-airline-tr-rabbit-worker')


class TestTestRunner(deployers.DeployerTest):

    def setUp(self):
        super(TestTestRunner, self).setUp()
        status = deploy.juju_status()
        units = status['services']['ci-airline-rabbit']['units']
        self.unit = 'ci-airline-rabbit/0'
        self.public_ip = units[self.unit]['public-address']
        # Expose rabbit service for this test.
        deployers.juju_expose(RABBIT_SERVICE)
        self.addCleanup(deployers.juju_expose, RABBIT_SERVICE, False)

        class AmqpConfig(object):

            def __init__(inner):
                inner.AMQP_HOST = self.public_ip
                inner.AMQP_VHOST = '/'
                inner.AMQP_USER = 'tester'
                inner.AMQP_PASSWORD = 's3cr3t'
        fixtures.patch(self, amqp_utils, 'get_config', AmqpConfig)
        create_rabbit_user('tester', 's3cr3t')
        self.addCleanup(delete_rabbit_user, 'tester')
        # We delay the import so it won't fail when the 'unit_config' file
        # is not available
        from ci_utils import unit_config
        conf = unit_config.get_auth_config()
        if unit_config.is_hpcloud(conf.get('glance_os_auth_url')):
            self.test_images = features.hpcloud_test_images
        else:
            self.test_images = features.canonistack_test_images

    def drain_queue(self, queue_name):
        self.messages = []

        def on_message(msg):
            body = json.loads(msg.body)
            self.messages.append(body)
            msg.channel.basic_ack(msg.delivery_tag)
            if body.get('exit'):
                # this will kick us out of the run-forever worker loop, relying
                # on the worker last message setting 'exit'
                msg.channel.basic_cancel(msg.consumer_tag)

        conf = amqp_utils.get_config()
        # Process all messages and delete the queue when done
        amqp_utils.process_queue(conf, queue_name, on_message, delete=True)
        return self.messages

    def assertStatusMsg(self, expected, msg):
        self.assertEqual('STATUS', msg['state'])
        without_state = msg.copy()
        del without_state['state']
        self.assertDictEqual(expected, without_state)

    def get_image_id(self, series):
        return self.test_images[series]

    def test_process_ticket(self):
        # Exercise the test runner API: feed a test request on the test runner
        # queue, ensure we get the expected messages back from the output
        # queue.
        ticket_id = 'process-ticket'
        progress_queue_name = 'test-progress-process'
        series = 'precise'
        params = dict(ticket_id=ticket_id,
                      progress_trigger=progress_queue_name,
                      series=series,
                      image_id=self.get_image_id(series),
                      ppa_list=[],
                      package_list=['libpng'])
        amqp_utils.send(amqp_utils.TEST_RUNNER_QUEUE, json.dumps(params),
                        raise_errors=True)
        msgs = self.drain_queue(progress_queue_name)
        assertions.assertLength(self, 6, msgs)
        self.assertStatusMsg(params, msgs[0])
        setup = 'Setting up the testbed for ticket {}'.format(ticket_id)
        self.assertStatusMsg(dict(message=setup), msgs[1])
        self.assertStatusMsg(dict(message='The test bed is ready'), msgs[2])
        self.assertStatusMsg(dict(message='Testing libpng'), msgs[3])
        completed = 'Test completed for ticket {}'.format(ticket_id)
        self.assertStatusMsg(dict(message=completed), msgs[4])
        final = msgs[5]
        # No tests for libpng on precise
        self.assertEqual('FAILED', final['result'])
        self.assertEqual('COMPLETED', final['state'])


    def test_run_tests(self):
        cdir = '/srv/ci-airline-tr-rabbit-worker/code/current/'
        args = [
            'juju', 'ssh', 'ci-airline-tr-rabbit-worker/0',
            cdir + 'run-python',
            cdir + 'test_runner/run-integration.py',
        ]
        try:
            subprocess.check_output(args, stderr=subprocess.PIPE)
        except subprocess.CalledProcessError as e:
            raise self.failureException(e.output)


if __name__ == "__main__":
    unittest.main()