# Copyright 2014 Rackspace Australia
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import sqlalchemy as sa

from tests.base import ZuulTestCase, ZuulDBTestCase


def _get_reporter_from_connection_name(reporters, connection_name):
    # Reporters are placed into lists for each action they may exist in.
    # Search through the given list for the correct reporter by its conncetion
    # name
    for r in reporters:
        if r.connection.connection_name == connection_name:
            return r


class TestConnections(ZuulTestCase):
    config_file = 'zuul-connections-same-gerrit.conf'
    tenant_config_file = 'config/zuul-connections-same-gerrit/main.yaml'

    def test_multiple_gerrit_connections(self):
        "Test multiple connections to the one gerrit"

        A = self.fake_review_gerrit.addFakeChange('org/project', 'master', 'A')
        self.addEvent('review_gerrit', A.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertEqual(len(A.patchsets[-1]['approvals']), 1)
        self.assertEqual(A.patchsets[-1]['approvals'][0]['type'], 'Verified')
        self.assertEqual(A.patchsets[-1]['approvals'][0]['value'], '1')
        self.assertEqual(A.patchsets[-1]['approvals'][0]['by']['username'],
                         'jenkins')

        B = self.fake_review_gerrit.addFakeChange('org/project', 'master', 'B')
        self.executor_server.failJob('project-test2', B)
        self.addEvent('review_gerrit', B.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertEqual(len(B.patchsets[-1]['approvals']), 1)
        self.assertEqual(B.patchsets[-1]['approvals'][0]['type'], 'Verified')
        self.assertEqual(B.patchsets[-1]['approvals'][0]['value'], '-1')
        self.assertEqual(B.patchsets[-1]['approvals'][0]['by']['username'],
                         'civoter')


class TestSQLConnection(ZuulDBTestCase):
    config_file = 'zuul-sql-driver.conf'
    tenant_config_file = 'config/sql-driver/main.yaml'
    expected_table_prefix = ''

    def test_sql_tables_created(self):
        "Test the tables for storing results are created properly"

        connection = self.connections.connections['resultsdb']
        insp = sa.engine.reflection.Inspector(connection.engine)

        table_prefix = connection.table_prefix
        self.assertEqual(self.expected_table_prefix, table_prefix)

        buildset_table = table_prefix + 'zuul_buildset'
        build_table = table_prefix + 'zuul_build'

        self.assertEqual(13, len(insp.get_columns(buildset_table)))
        self.assertEqual(10, len(insp.get_columns(build_table)))

    def test_sql_results(self):
        "Test results are entered into an sql table"
        self.executor_server.hold_jobs_in_build = True
        # Grab the sa tables
        tenant = self.sched.abide.tenants.get('tenant-one')
        reporter = _get_reporter_from_connection_name(
            tenant.layout.pipelines['check'].success_actions,
            'resultsdb'
        )

        # Add a success result
        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
        self.waitUntilSettled()
        self.orderedRelease()
        self.waitUntilSettled()

        # Add a failed result
        B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')

        self.executor_server.failJob('project-test1', B)
        self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
        self.waitUntilSettled()
        self.orderedRelease()
        self.waitUntilSettled()

        conn = self.connections.connections['resultsdb'].engine.connect()
        result = conn.execute(
            sa.sql.select([reporter.connection.zuul_buildset_table]))

        buildsets = result.fetchall()
        self.assertEqual(2, len(buildsets))
        buildset0 = buildsets[0]
        buildset1 = buildsets[1]

        self.assertEqual('check', buildset0['pipeline'])
        self.assertEqual('org/project', buildset0['project'])
        self.assertEqual(1, buildset0['change'])
        self.assertEqual('1', buildset0['patchset'])
        self.assertEqual('SUCCESS', buildset0['result'])
        self.assertEqual('Build succeeded.', buildset0['message'])
        self.assertEqual('tenant-one', buildset0['tenant'])
        self.assertEqual('https://review.example.com/%d' % buildset0['change'],
                         buildset0['ref_url'])

        buildset0_builds = conn.execute(
            sa.sql.select([reporter.connection.zuul_build_table]).
            where(
                reporter.connection.zuul_build_table.c.buildset_id ==
                buildset0['id']
            )
        ).fetchall()

        # Check the first result, which should be the project-merge job
        self.assertEqual('project-merge', buildset0_builds[0]['job_name'])
        self.assertEqual("SUCCESS", buildset0_builds[0]['result'])
        self.assertEqual(
            'finger://{hostname}/{uuid}'.format(
                hostname=self.executor_server.hostname,
                uuid=buildset0_builds[0]['uuid']),
            buildset0_builds[0]['log_url'])
        self.assertEqual('check', buildset1['pipeline'])
        self.assertEqual('org/project', buildset1['project'])
        self.assertEqual(2, buildset1['change'])
        self.assertEqual('1', buildset1['patchset'])
        self.assertEqual('FAILURE', buildset1['result'])
        self.assertEqual('Build failed.', buildset1['message'])

        buildset1_builds = conn.execute(
            sa.sql.select([reporter.connection.zuul_build_table]).
            where(
                reporter.connection.zuul_build_table.c.buildset_id ==
                buildset1['id']
            )
        ).fetchall()

        # Check the second result, which should be the project-test1 job
        # which failed
        self.assertEqual('project-test1', buildset1_builds[1]['job_name'])
        self.assertEqual("FAILURE", buildset1_builds[1]['result'])
        self.assertEqual(
            'finger://{hostname}/{uuid}'.format(
                hostname=self.executor_server.hostname,
                uuid=buildset1_builds[1]['uuid']),
            buildset1_builds[1]['log_url'])

    def test_multiple_sql_connections(self):
        "Test putting results in different databases"
        # Add a successful result
        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
        self.waitUntilSettled()

        # Add a failed result
        B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
        self.executor_server.failJob('project-test1', B)
        self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
        self.waitUntilSettled()

        # Grab the sa tables for resultsdb
        tenant = self.sched.abide.tenants.get('tenant-one')
        reporter1 = _get_reporter_from_connection_name(
            tenant.layout.pipelines['check'].success_actions,
            'resultsdb'
        )

        conn = self.connections.connections['resultsdb'].engine.connect()
        buildsets_resultsdb = conn.execute(sa.sql.select(
            [reporter1.connection.zuul_buildset_table])).fetchall()
        # Should have been 2 buildset reported to the resultsdb (both success
        # and failure report)
        self.assertEqual(2, len(buildsets_resultsdb))

        # The first one should have passed
        self.assertEqual('check', buildsets_resultsdb[0]['pipeline'])
        self.assertEqual('org/project', buildsets_resultsdb[0]['project'])
        self.assertEqual(1, buildsets_resultsdb[0]['change'])
        self.assertEqual('1', buildsets_resultsdb[0]['patchset'])
        self.assertEqual('SUCCESS', buildsets_resultsdb[0]['result'])
        self.assertEqual('Build succeeded.', buildsets_resultsdb[0]['message'])

        # Grab the sa tables for resultsdb_failures
        reporter2 = _get_reporter_from_connection_name(
            tenant.layout.pipelines['check'].failure_actions,
            'resultsdb_failures'
        )

        conn = self.connections.connections['resultsdb_failures'].\
            engine.connect()
        buildsets_resultsdb_failures = conn.execute(sa.sql.select(
            [reporter2.connection.zuul_buildset_table])).fetchall()
        # The failure db should only have 1 buildset failed
        self.assertEqual(1, len(buildsets_resultsdb_failures))

        self.assertEqual('check', buildsets_resultsdb_failures[0]['pipeline'])
        self.assertEqual(
            'org/project', buildsets_resultsdb_failures[0]['project'])
        self.assertEqual(2, buildsets_resultsdb_failures[0]['change'])
        self.assertEqual('1', buildsets_resultsdb_failures[0]['patchset'])
        self.assertEqual('FAILURE', buildsets_resultsdb_failures[0]['result'])
        self.assertEqual(
            'Build failed.', buildsets_resultsdb_failures[0]['message'])


class TestSQLConnectionPrefix(TestSQLConnection):
    config_file = 'zuul-sql-driver-prefix.conf'
    expected_table_prefix = 'prefix_'


class TestConnectionsBadSQL(ZuulDBTestCase):
    config_file = 'zuul-sql-driver-bad.conf'
    tenant_config_file = 'config/sql-driver/main.yaml'

    def test_unable_to_connect(self):
        "Test the SQL reporter fails gracefully when unable to connect"
        self.config.set('zuul', 'layout_config',
                        'tests/fixtures/layout-sql-reporter.yaml')
        self.sched.reconfigure(self.config)

        # Trigger a reporter. If no errors are raised, the reporter has been
        # disabled correctly
        A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
        self.waitUntilSettled()


class TestMultipleGerrits(ZuulTestCase):
    config_file = 'zuul-connections-multiple-gerrits.conf'
    tenant_config_file = 'config/zuul-connections-multiple-gerrits/main.yaml'

    def test_multiple_project_separate_gerrits(self):
        self.executor_server.hold_jobs_in_build = True

        A = self.fake_another_gerrit.addFakeChange(
            'org/project1', 'master', 'A')
        self.fake_another_gerrit.addEvent(A.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertBuilds([dict(name='project-test2',
                                changes='1,1',
                                project='org/project1',
                                pipeline='another_check')])

        # NOTE(jamielennox): the tests back the git repo for both connections
        # onto the same git repo on the file system. If we just create another
        # fake change the fake_review_gerrit will try to create another 1,1
        # change and git will fail to create the ref. Arbitrarily set it to get
        # around the problem.
        self.fake_review_gerrit.change_number = 50

        B = self.fake_review_gerrit.addFakeChange(
            'org/project1', 'master', 'B')
        self.fake_review_gerrit.addEvent(B.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertBuilds([
            dict(name='project-test2',
                 changes='1,1',
                 project='org/project1',
                 pipeline='another_check'),
            dict(name='project-test1',
                 changes='51,1',
                 project='org/project1',
                 pipeline='review_check'),
        ])

        self.executor_server.hold_jobs_in_build = False
        self.executor_server.release()
        self.waitUntilSettled()

    def test_multiple_project_separate_gerrits_common_pipeline(self):
        self.executor_server.hold_jobs_in_build = True

        A = self.fake_another_gerrit.addFakeChange(
            'org/project2', 'master', 'A')
        self.fake_another_gerrit.addEvent(A.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertBuilds([dict(name='project-test2',
                                changes='1,1',
                                project='org/project2',
                                pipeline='common_check')])

        # NOTE(jamielennox): the tests back the git repo for both connections
        # onto the same git repo on the file system. If we just create another
        # fake change the fake_review_gerrit will try to create another 1,1
        # change and git will fail to create the ref. Arbitrarily set it to get
        # around the problem.
        self.fake_review_gerrit.change_number = 50

        B = self.fake_review_gerrit.addFakeChange(
            'org/project2', 'master', 'B')
        self.fake_review_gerrit.addEvent(B.getPatchsetCreatedEvent(1))

        self.waitUntilSettled()

        self.assertBuilds([
            dict(name='project-test2',
                 changes='1,1',
                 project='org/project2',
                 pipeline='common_check'),
            dict(name='project-test1',
                 changes='51,1',
                 project='org/project2',
                 pipeline='common_check'),
        ])

        self.executor_server.hold_jobs_in_build = False
        self.executor_server.release()
        self.waitUntilSettled()


class TestConnectionsMerger(ZuulTestCase):
    config_file = 'zuul-connections-merger.conf'
    tenant_config_file = 'config/single-tenant/main.yaml'

    def configure_connections(self):
        super(TestConnectionsMerger, self).configure_connections(True)

    def test_connections_merger(self):
        "Test merger only configures source connections"

        self.assertIn("gerrit", self.connections.connections)
        self.assertIn("github", self.connections.connections)
        self.assertNotIn("smtp", self.connections.connections)
        self.assertNotIn("sql", self.connections.connections)
        self.assertNotIn("timer", self.connections.connections)
        self.assertNotIn("zuul", self.connections.connections)


class TestConnectionsCgit(ZuulTestCase):
    config_file = 'zuul-connections-cgit.conf'
    tenant_config_file = 'config/single-tenant/main.yaml'

    def test_cgit_web_url(self):
        self.assertIn("gerrit", self.connections.connections)
        conn = self.connections.connections['gerrit']
        source = conn.source
        proj = source.getProject('foo/bar')
        url = conn._getWebUrl(proj, '1')
        self.assertEqual(url,
                         'https://cgit.example.com/cgit/foo/bar/commit/?id=1')


class TestConnectionsGitweb(ZuulTestCase):
    config_file = 'zuul-connections-gitweb.conf'
    tenant_config_file = 'config/single-tenant/main.yaml'

    def test_gitweb_url(self):
        self.assertIn("gerrit", self.connections.connections)
        conn = self.connections.connections['gerrit']
        source = conn.source
        proj = source.getProject('foo/bar')
        url = conn._getWebUrl(proj, '1')
        url_should_be = 'https://review.example.com/' \
                        'gitweb?p=foo/bar.git;a=commitdiff;h=1'
        self.assertEqual(url, url_should_be)
