#!/usr/bin/env python2
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Unit test for pubsub_utils.py"""

from __future__ import print_function
import os
import unittest

import mox

# TODO(crbug.com/1050892): The unittests rely on apiclient in chromite.
import autotest_lib.utils.frozen_chromite  # pylint: disable=unused-import

from apiclient import discovery
from oauth2client.client import ApplicationDefaultCredentialsError
from oauth2client.client import GoogleCredentials
from googleapiclient.errors import UnknownApiNameOrVersion

import pubsub_utils

_TEST_CLOUD_SERVICE_ACCOUNT_FILE = '/tmp/test-credential'


class MockedPubSub(object):
    """A mocked PubSub handle."""
    def __init__(self, test, topic, msg, retry, ret_val=None,
                 raise_except=False):
        self.test = test
        self.topic = topic
        self.msg = msg
        self.retry = retry
        self.ret_val = ret_val
        self.raise_except = raise_except

    def projects(self):
        """Mocked PubSub projects."""
        return self

    def topics(self):
        """Mocked PubSub topics."""
        return self

    def publish(self, topic, body):
        """Mocked PubSub publish method.

        @param topic: PubSub topic string.
        @param body: PubSub notification body.
        """
        self.test.assertEquals(self.topic, topic)
        self.test.assertEquals(self.msg, body['messages'][0])
        return self

    def execute(self, num_retries):
        """Mocked PubSub execute method.

        @param num_retries: Number of retries.
        """
        self.test.assertEquals(self.retry, num_retries)
        if self.raise_except:
            raise Exception()
        return self.ret_val


def _create_sample_message():
    """Creates a sample pubsub message."""
    msg_payload = {'data': 'sample data'}
    msg_attributes = {}
    msg_attributes['var'] = 'value'
    msg_payload['attributes'] = msg_attributes

    return msg_payload


class PubSubTests(mox.MoxTestBase):
    """Tests for pubsub related functios."""

    def test_pubsub_with_no_service_account(self):
        """Test getting the pubsub service"""
        self.mox.StubOutWithMock(os.path, 'isfile')
        self.mox.ReplayAll()
        with self.assertRaises(pubsub_utils.PubSubException):
            pubsub_utils.PubSubClient()
        self.mox.VerifyAll()

    def test_pubsub_with_non_existing_service_account(self):
        """Test getting the pubsub service"""
        self.mox.StubOutWithMock(os.path, 'isfile')
        os.path.isfile(_TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(False)
        self.mox.ReplayAll()
        with self.assertRaises(pubsub_utils.PubSubException):
            pubsub_utils.PubSubClient(_TEST_CLOUD_SERVICE_ACCOUNT_FILE)
        self.mox.VerifyAll()

    def test_pubsub_with_corrupted_service_account(self):
        """Test pubsub with corrupted service account."""
        self.mox.StubOutWithMock(os.path, 'isfile')
        self.mox.StubOutWithMock(GoogleCredentials, 'from_stream')
        os.path.isfile(_TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(True)
        GoogleCredentials.from_stream(
            _TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndRaise(
                ApplicationDefaultCredentialsError())
        self.mox.ReplayAll()
        with self.assertRaises(pubsub_utils.PubSubException):
            pubsub_utils.PubSubClient(_TEST_CLOUD_SERVICE_ACCOUNT_FILE)
        self.mox.VerifyAll()

    def test_pubsub_with_invalid_service_account(self):
        """Test pubsubwith invalid service account."""
        self.mox.StubOutWithMock(os.path, 'isfile')
        self.mox.StubOutWithMock(GoogleCredentials, 'from_stream')
        os.path.isfile(_TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(True)
        credentials = self.mox.CreateMock(GoogleCredentials)
        GoogleCredentials.from_stream(
            _TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(credentials)
        credentials.create_scoped_required().AndReturn(True)
        credentials.create_scoped(pubsub_utils.PUBSUB_SCOPES).AndReturn(
            credentials)
        self.mox.StubOutWithMock(discovery, 'build')
        discovery.build(
            pubsub_utils.PUBSUB_SERVICE_NAME,
            pubsub_utils.PUBSUB_VERSION,
            credentials=credentials).AndRaise(UnknownApiNameOrVersion())
        self.mox.ReplayAll()
        with self.assertRaises(pubsub_utils.PubSubException):
            msg = _create_sample_message()
            pubsub_client = pubsub_utils.PubSubClient(
                _TEST_CLOUD_SERVICE_ACCOUNT_FILE)
            pubsub_client.publish_notifications('test_topic', [msg])
        self.mox.VerifyAll()

    def test_publish_notifications(self):
        """Test getting the pubsub service"""
        self.mox.StubOutWithMock(os.path, 'isfile')
        self.mox.StubOutWithMock(GoogleCredentials, 'from_stream')
        os.path.isfile(_TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(True)
        credentials = self.mox.CreateMock(GoogleCredentials)
        GoogleCredentials.from_stream(
            _TEST_CLOUD_SERVICE_ACCOUNT_FILE).AndReturn(credentials)
        credentials.create_scoped_required().AndReturn(True)
        credentials.create_scoped(pubsub_utils.PUBSUB_SCOPES).AndReturn(
            credentials)
        self.mox.StubOutWithMock(discovery, 'build')
        msg = _create_sample_message()
        discovery.build(
            pubsub_utils.PUBSUB_SERVICE_NAME,
            pubsub_utils.PUBSUB_VERSION,
            credentials=credentials).AndReturn(MockedPubSub(
                self,
                'test_topic',
                msg,
                pubsub_utils.DEFAULT_PUBSUB_NUM_RETRIES,
                # use tuple ('123') instead of list just for easy to
                # write the test.
                ret_val={'messageIds': ('123')}))

        self.mox.ReplayAll()
        pubsub_client = pubsub_utils.PubSubClient(
                _TEST_CLOUD_SERVICE_ACCOUNT_FILE)
        msg_ids = pubsub_client.publish_notifications('test_topic', [msg])
        self.assertEquals(('123'), msg_ids)

        self.mox.VerifyAll()


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