def test_make_local_config(self):
        """
        Test that making the local config looks like it is expected to
        """
        input_dictionary = OrderedDict([
            ('first_value', 1),
            ('first_word', 'word one'),
            ('second_value', 2.0),
            ('second_word', 'word two')
        ])
        expected_text = 'first_value = 1\nfirst_word = \'word one\'\n' \
                        'second_value = 2.0\nsecond_word = \'word two\''

        actual_text = IntegrationTestWorker.make_local_config(input_dictionary)

        self.assertEqual(expected_text, actual_text)
    def test_workflow_of_integration_worker(self, mock_run_test):
        """
        General work flow of the integration worker from receiving a packet,
        to finishing with a packet.
        """
        # Worker receives a packet, most likely from the deploy worker
        # Example packet:
        #
        #  {
        #    'application': 'staging',
        #    'service': 'adsws',
        #    'release': '',
        #    'config': {},
        #  }
        #
        #
        example_packet = {
            'application': 'staging',
            'service': 'adsws',
            'tag': 'v1.0.0',
            'commit': 'gf9gd8f',
            'config': {},
            'action': 'test'
        }

        expected_packet = example_packet.copy()
        expected_packet['tested'] = True
        # Override the run test returned value. This means the logic of the test
        # does not have to be mocked
        mock_run_test.return_value = expected_packet

        with MiniRabbit(RABBITMQ_URL) as w:
            w.publish(route='in', exchange='test', payload=json.dumps(example_packet))

        # Worker runs the tests
        params = {
            'RABBITMQ_URL': RABBITMQ_URL,
            'exchange': 'test',
            'subscribe': 'in',
            'publish': 'out',
            'status': 'database',
            'TEST_RUN': True
        }
        test_worker = IntegrationTestWorker(params=params)
        test_worker.run()
        test_worker.connection.close()

        # Worker sends a packet to the next worker
        with MiniRabbit(RABBITMQ_URL) as w:

            m_in = w.message_count(queue='in')
            m_out = w.message_count(queue='out')

            p = w.get_packet(queue='out')

        self.assertEqual(m_in, 0)
        self.assertEqual(m_out, 1)

        # Remove values that are not in the starting packet
        self.assertTrue(p.pop('tested'))
        self.assertEqual(
            p,
            example_packet
        )
    def test_db_writes_on_test_pass(self, mocked_run_test):
        """
        Check that the database is being written to when a test passes
        """
        # Stub data
        packet = {
            'application': 'adsws',
            'environment': 'staging',
            'tag': 'v1.0.0',
            'commit': 'gf9gd8f',
        }
        expected_packet = packet.copy()
        expected_packet['tested'] = True
        mocked_run_test.return_value = expected_packet

        # Start the IntegrationTester worker
        params = {
            'RABBITMQ_URL': RABBITMQ_URL,
            'exchange': 'test',
            'subscribe': 'in',
            'publish': 'out',
            'status': 'database',
            'TEST_RUN': True
        }

        # Push to rabbitmq
        with MiniRabbit(RABBITMQ_URL) as w:
            w.publish(route='in', exchange='test', payload=json.dumps(packet))

        test_worker = IntegrationTestWorker(params=params)
        test_worker.run()
        test_worker.connection.close()

        # Assert there is a packet on the publish queue
        with MiniRabbit(RABBITMQ_URL) as w:
            self.assertEqual(w.message_count('out'), 1)
            self.assertEqual(w.message_count('database'), 1)

        # Start the DB Writer worker
        params = {
            'RABBITMQ_URL': RABBITMQ_URL,
            'exchange': 'test',
            'subscribe': 'database',
            'TEST_RUN': True
        }
        db_worker = DatabaseWriterWorker(params=params)
        db_worker.app = self.app
        db_worker.run()
        db_worker.connection.close()

        with self.app.session_scope() as session:

            all_deployments = session.query(Deployment).all()
            self.assertEqual(
                len(all_deployments),
                1,
                msg='More (or less) than 1 deployment entry: {}'
                    .format(all_deployments)
            )
            deployment = all_deployments[0]

            for key in packet:
                self.assertEqual(
                    packet[key],
                    getattr(deployment, key)
                )
            self.assertEqual(deployment.tested, True)
    def test_worker_running_test(self, mocked_publish, mocked_clone, mocked_subprocess, mocked_rmtree, mocked_cd, mocked_isdir, mocked_open):
        """
        Test that the integration worker follows the expected workflow:
        """

        # Mock responses
        # 1. File object
        file_instance = mocked_open.return_value
        file_instance.__enter__.return_value = file_instance
        file_instance.__exit__.return_value = None

        # 2. Change Directory
        instance_cd = mocked_cd.return_value
        instance_cd.__enter__.return_value = instance_cd
        instance_cd.__exit__.return_value = None

        # 3. Subprocess
        process = mock.Mock()
        process.communicate.return_value = '10 passed', ''
        mocked_subprocess.Popen.return_value = process

        # 4. Others
        mocked_isdir.return_value = True
        mocked_publish.return_value = None
        mocked_clone.return_value = None

        example_payload = {
            'application': 'staging',
            'service': 'adsws',
            'release': 'v1.0.0',
            'config': {},
            'action': 'test'
        }

        worker = IntegrationTestWorker()
        result = worker.run_test(example_payload)

        # The worker downloads the repository that contains the integration
        # tests
        mocked_clone.assert_has_calls(
            [mock.call('https://github.com/adsabs/adsrex.git', '/tmp/adsrex', branch='develop')]
        )

        # Test that the local config gets produced
        mocked_open.assert_has_calls(
            [mock.call('/tmp/adsrex/v1/local_config.py', 'w')]
        )

        # The worker changes into the directory and runs the tests using
        # a bash script
        mocked_subprocess.Popen.assert_has_calls(
            [mock.call(['py.test'], stdin=mocked_subprocess.PIPE, stdout=mocked_subprocess.PIPE)]
        )

        # The test repository should also no longer exist
        mocked_rmtree.assert_has_calls(
            [mock.call('/tmp/adsrex')]
        )

        # The test passes and it forwards a packet on to the relevant worker,
        # with the updated keyword for test pass
        example_payload['tested'] = True
        self.assertEqual(
            example_payload,
            result
        )
    def test_git_raises_error(self, mocked_publish, mocked_clone, mocked_subprocess, mocked_rmtree, mocked_cd, mocked_isdir, mocked_open):
        """
        Test that nothing breaks if git pull fails
        """

        # Mock responses
        # 1. File object
        file_instance = mocked_open.return_value
        file_instance.__enter__.return_value = file_instance
        file_instance.__exit__.return_value = None

        # 2. Change Directory
        instance_cd = mocked_cd.return_value
        instance_cd.__enter__.return_value = instance_cd
        instance_cd.__exit__.return_value = None

        # 3. Subprocess
        process = mock.Mock()
        process.communicate.return_value = '10 passed', ''
        mocked_subprocess.Popen.return_value = process

        # 4. Others
        mocked_isdir.return_value = True
        mocked_publish.return_value = None
        mocked_clone.side_effect = ValueError('ValueError')

        example_payload = {
            'application': 'staging',
            'service': 'adsws',
            'release': 'v1.0.0',
            'config': {},
            'action': 'test'
        }

        worker = IntegrationTestWorker()
        result = worker.run_test(example_payload.copy())

        # The worker downloads the repository that contains the integration
        # tests
        mocked_clone.assert_has_calls(
            [mock.call('https://github.com/adsabs/adsrex.git', '/tmp/adsrex', branch='develop')]
        )

        # Test that the local config does not get produced
        self.assertFalse(mocked_open.called)

        # Subprocess should not be called
        self.assertFalse(mocked_subprocess.called)

        # Regardless, rmtree should still be called to cleanup any folders
        mocked_rmtree.assert_has_calls(
            [mock.call('/tmp/adsrex')]
        )

        # The test passes and it forwards a packet on to the relevant worker,
        # with the updated keyword for test pass
        example_payload['tested'] = False

        self.assertEqual(
            example_payload,
            result
        )