# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""Tests for issueattachmenttext."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import mock
import unittest

import ezt
from google.appengine.ext import testbed
from google.cloud import storage

import webapp2

from framework import permissions
from proto import tracker_pb2
from services import service_manager
from testing import fake
from testing import testing_helpers
from tracker import issueattachmenttext


class IssueAttachmentTextTest(unittest.TestCase):

  def setUp(self):
    self.testbed = testbed.Testbed()
    self.testbed.activate()
    self.testbed.init_app_identity_stub()

    services = service_manager.Services(
        project=fake.ProjectService(),
        config=fake.ConfigService(),
        issue=fake.IssueService(),
        user=fake.UserService())
    self.project = services.project.TestAddProject('proj')
    self.servlet = issueattachmenttext.AttachmentText(
        'req', 'res', services=services)

    services.user.TestAddUser('commenter@example.com', 111)

    self.issue = tracker_pb2.Issue()
    self.issue.local_id = 1
    self.issue.issue_id = 1
    self.issue.summary = 'sum'
    self.issue.project_name = 'proj'
    self.issue.project_id = self.project.project_id
    services.issue.TestAddIssue(self.issue)

    self.comment0 = tracker_pb2.IssueComment()
    self.comment0.content = 'this is the description'
    self.comment0.user_id = 111
    self.comment1 = tracker_pb2.IssueComment()
    self.comment1.content = 'this is a comment'
    self.comment1.user_id = 111

    self.attach0 = tracker_pb2.Attachment(
        attachment_id=4567, filename='b.txt', mimetype='text/plain',
        gcs_object_id='/pid/attachments/abcd')
    self.comment0.attachments.append(self.attach0)

    self.attach1 = tracker_pb2.Attachment(
        attachment_id=1234, filename='a.txt', mimetype='text/plain',
        gcs_object_id='/pid/attachments/abcdefg')
    self.comment0.attachments.append(self.attach1)

    self.bin_attach = tracker_pb2.Attachment(
        attachment_id=2468, mimetype='application/octets',
        gcs_object_id='/pid/attachments/\0\0\0\0\0\1\2\3')
    self.comment1.attachments.append(self.bin_attach)

    self.comment0.project_id = self.project.project_id
    services.issue.TestAddComment(self.comment0, self.issue.local_id)
    self.comment1.project_id = self.project.project_id
    services.issue.TestAddComment(self.comment1, self.issue.local_id)
    services.issue.TestAddAttachment(
        self.attach0, self.comment0.id, self.issue.issue_id)
    services.issue.TestAddAttachment(
        self.attach1, self.comment1.id, self.issue.issue_id)
    # TODO(jrobbins): add tests for binary content

    self.client = mock.MagicMock()
    self.bucket = mock.MagicMock()
    self.blob = mock.MagicMock()
    self.client.get_bucket = mock.MagicMock(return_value=self.bucket)
    self.bucket.get_blob = mock.MagicMock(return_value=self.blob)
    self.blob.download_as_bytes = mock.MagicMock()
    mock.patch.object(storage, 'Client', return_value=self.client).start()

  def tearDown(self):
    self.testbed.deactivate()
    mock.patch.stopall()

  def testGatherPageData_CommentDeleted(self):
    """If the attachment's comment was deleted, give a 403."""
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/a/d.com/p/proj/issues/attachmentText?aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    self.servlet.GatherPageData(mr)  # OK
    self.comment1.deleted_by = 111
    self.assertRaises(  # 403
        permissions.PermissionException,
        self.servlet.GatherPageData, mr)

  def testGatherPageData_IssueNotViewable(self):
    """If the attachment's issue is not viewable, give a 403."""
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachment?aid=1234',
        perms=permissions.EMPTY_PERMISSIONSET)  # No VIEW
    self.assertRaises(
        permissions.PermissionException,
        self.servlet.GatherPageData, mr)

  def testGatherPageData_IssueDeleted(self):
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachment?aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    self.issue.deleted = True
    self.assertRaises(  # Issue was deleted
        permissions.PermissionException,
        self.servlet.GatherPageData, mr)

  def testGatherPageData_IssueRestricted(self):
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachment?aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    self.issue.labels.append('Restrict-View-Nobody')
    self.assertRaises(  # Issue is restricted
        permissions.PermissionException,
        self.servlet.GatherPageData, mr)

  def testGatherPageData_NoSuchAttachment(self):
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachmentText?aid=9999',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    with self.assertRaises(webapp2.HTTPException) as cm:
      self.servlet.GatherPageData(mr)
    self.assertEqual(404, cm.exception.code)

  def testGatherPageData_AttachmentDeleted(self):
    """If the attachment was deleted, give a 404."""
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachmentText?aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    self.attach1.deleted = True
    with self.assertRaises(webapp2.HTTPException) as cm:
      self.servlet.GatherPageData(mr)
    self.assertEqual(404, cm.exception.code)

  def testGatherPageData_Normal(self):
    self.blob.download_as_bytes = mock.MagicMock(
        return_value='/app_default_bucket/pid/attachments/abcdefg')

    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachmentText?id=1&aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    page_data = self.servlet.GatherPageData(mr)
    self.assertEqual(1, page_data['local_id'])
    self.assertEqual('a.txt', page_data['filename'])
    self.assertEqual('43 bytes', page_data['filesize'])
    self.assertEqual(ezt.boolean(False), page_data['should_prettify'])
    self.assertEqual(ezt.boolean(False), page_data['is_binary'])
    self.assertEqual(ezt.boolean(False), page_data['too_large'])

    file_lines = page_data['file_lines']
    self.assertEqual(1, len(file_lines))
    self.assertEqual(1, file_lines[0].num)
    self.assertEqual('/app_default_bucket/pid/attachments/abcdefg',
                     file_lines[0].line)

    self.assertEqual(None, page_data['code_reviews'])

  @mock.patch('framework.filecontent.DecodeFileContents')
  def testGatherPageData_HugeFile(self, mock_DecodeFileContents):
    _request, mr = testing_helpers.GetRequestObjects(
        project=self.project,
        path='/p/proj/issues/attachmentText?id=1&aid=1234',
        perms=permissions.READ_ONLY_PERMISSIONSET)
    mock_DecodeFileContents.return_value = (
        'too large text', False, True)

    page_data = self.servlet.GatherPageData(mr)

    self.assertEqual(ezt.boolean(False), page_data['should_prettify'])
    self.assertEqual(ezt.boolean(False), page_data['is_binary'])
    self.assertEqual(ezt.boolean(True), page_data['too_large'])
