#!/usr/bin/env python
# Copyright (c) 2012 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.

"""Unit tests for gcl.py."""

# pylint: disable=E1103,E1101,E1120

import os
import sys

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from testing_support.super_mox import mox, SuperMoxTestBase

import gcl
import presubmit_support


class GclTestsBase(SuperMoxTestBase):
  """Setups and tear downs the mocks but doesn't test anything as-is."""
  def setUp(self):
    SuperMoxTestBase.setUp(self)
    self.fake_root_dir = self.RootDir()
    self.mox.StubOutWithMock(gcl, 'RunShell')
    self.mox.StubOutWithMock(gcl.SVN, '_CaptureInfo')
    self.mox.StubOutWithMock(gcl.SVN, 'GetCheckoutRoot')
    self.mox.StubOutWithMock(gcl, 'tempfile')
    self.mox.StubOutWithMock(gcl.upload, 'RealMain')
    self.mox.StubOutWithMock(gcl.gclient_utils, 'FileRead')
    self.mox.StubOutWithMock(gcl.gclient_utils, 'FileWrite')
    gcl.REPOSITORY_ROOT = None
    self.old_review_settings = gcl.CODEREVIEW_SETTINGS
    self.assertEquals(gcl.CODEREVIEW_SETTINGS, {})

  def tearDown(self):
    gcl.CODEREVIEW_SETTINGS = self.old_review_settings

  def fakeChange(self, files=None):  # pylint: disable=R0201
    if files == None:
      files = [('A', 'aa'), ('M', 'bb')]

    change_info = self.mox.CreateMock(gcl.ChangeInfo)
    change_info.name = 'naame'
    change_info.issue = 1
    change_info.patchset = 0
    change_info.description = 'deescription'
    change_info.files = files
    change_info.GetFiles = lambda : change_info.files
    change_info.GetIssueDescription = lambda : change_info.description
    change_info.GetFileNames = lambda : [f[1] for f in change_info.files]
    change_info.GetLocalRoot = lambda : 'proout'
    change_info.patch = None
    change_info.rietveld = 'https://my_server'
    change_info._closed = False
    change_info._deleted = False
    change_info._comments_added = []

    class RpcServer(object):
      # pylint: disable=R0201,W0613
      def get_issue_properties(self, issue, messages):
        return { 'patchsets': [1337] }
    change_info.RpcServer = RpcServer

    def AddComment(comment):
      # pylint: disable=W0212
      change_info._comments_added.append(comment)
    change_info.AddComment = AddComment

    def Delete():
      change_info._deleted = True
    change_info.Delete = Delete

    def CloseIssue():
      change_info._closed = True
    change_info.CloseIssue = CloseIssue

    return change_info


class GclUnittest(GclTestsBase):
  """General gcl.py tests."""
  def tearDown(self):
    gcl.CODEREVIEW_SETTINGS = {}

  def testMembersChanged(self):
    self.mox.ReplayAll()
    members = [
        'CODEREVIEW_SETTINGS', 'CODEREVIEW_SETTINGS_FILE',
        'CODEREVIEW_SETTINGS_FILE_NOT_FOUND',
        'CMDchange', 'CMDchanges', 'CMDcommit', 'CMDdelete', 'CMDdeleteempties',
        'CMDdescription', 'CMDdiff', 'CMDhelp', 'CMDlint', 'CMDnothave',
        'CMDopened', 'CMDpassthru', 'CMDpresubmit', 'CMDrename', 'CMDsettings',
        'CMDstatus', 'CMDtry', 'CMDupload',
        'ChangeInfo', 'Command', 'DEFAULT_LINT_IGNORE_REGEX',
        'DEFAULT_LINT_REGEX', 'CheckHomeForFile', 'DoPresubmitChecks',
        'ErrorExit', 'FILES_CACHE', 'FilterFlag', 'GenUsage',
        'GenerateChangeName', 'GenerateDiff', 'GetCLs', 'GetCacheDir',
        'GetCachedFile', 'GetChangelistInfoFile', 'GetChangesDir',
        'GetCodeReviewSetting', 'GetFilesNotInCL', 'GetInfoDir',
        'GetModifiedFiles', 'GetRepositoryRoot', 'GetTreeStatus', 'ListFiles',
        'LoadChangelistInfoForMultiple', 'MISSING_TEST_MSG',
        'OptionallyDoPresubmitChecks', 'REPOSITORY_ROOT',
        'RunShell', 'RunShellWithReturnCode', 'SVN',
        'TryChange', 'UnknownFiles', 'Warn',
        'attrs', 'auth', 'breakpad', 'defer_attributes', 'fix_encoding',
        'gclient_utils', 'git_cl', 'json', 'main', 'need_change',
        'need_change_and_args', 'no_args', 'optparse', 'os',
        'presubmit_support', 'random', 're', 'rietveld',
        'ssl', 'string', 'subprocess2', 'sys', 'tempfile', 'time',
        'upload', 'urllib2',
    ]
    # If this test fails, you should add the relevant test.
    self.compareMembers(gcl, members)

  def testIsSVNMoved(self):
    # TODO(maruel): TEST ME
    pass

  def testGetSVNFileProperty(self):
    # TODO(maruel): TEST ME
    pass

  def testUnknownFiles(self):
    # TODO(maruel): TEST ME
    pass

  def testCheckHomeForFile(self):
    # TODO(maruel): TEST ME
    pass

  def testDefaultSettings(self):
    self.assertEquals({}, gcl.CODEREVIEW_SETTINGS)

  def testGetCodeReviewSettingOk(self):
    self.mox.StubOutWithMock(gcl, 'GetCachedFile')
    gcl.GetCachedFile(gcl.CODEREVIEW_SETTINGS_FILE).AndReturn(
        'foo:bar\n'
        '# comment\n'
        ' c : d \n\r'
        'e: f')
    self.mox.ReplayAll()
    self.assertEquals('bar', gcl.GetCodeReviewSetting('foo'))
    self.assertEquals('d', gcl.GetCodeReviewSetting('c'))
    self.assertEquals('f', gcl.GetCodeReviewSetting('e'))
    self.assertEquals('', gcl.GetCodeReviewSetting('other'))
    self.assertEquals(
        {'foo': 'bar', 'c': 'd', 'e': 'f', '__just_initialized': None},
        gcl.CODEREVIEW_SETTINGS)

  def testGetCodeReviewSettingFail(self):
    self.mox.StubOutWithMock(gcl, 'GetCachedFile')
    gcl.GetCachedFile(gcl.CODEREVIEW_SETTINGS_FILE).AndReturn(
        'aaa\n'
        ' c : d \n\r'
        'e: f')
    self.mox.ReplayAll()
    try:
      gcl.GetCodeReviewSetting('c')
      self.fail()
    except gcl.gclient_utils.Error:
      pass
    self.assertEquals({}, gcl.CODEREVIEW_SETTINGS)

  def testGetRepositoryRootNone(self):
    gcl.os.getcwd().AndReturn(self.fake_root_dir)
    gcl.SVN.GetCheckoutRoot(self.fake_root_dir).AndReturn(None)
    self.mox.ReplayAll()
    self.assertRaises(gcl.gclient_utils.Error, gcl.GetRepositoryRoot)

  def testGetRepositoryRootGood(self):
    root_path = gcl.os.path.join('bleh', 'prout', 'pouet')
    gcl.os.getcwd().AndReturn(root_path)
    gcl.SVN.GetCheckoutRoot(root_path).AndReturn(root_path + '.~')
    self.mox.ReplayAll()
    self.assertEquals(gcl.GetRepositoryRoot(), root_path + '.~')

  def testHelp(self):
    gcl.sys.stdout.write = lambda x: None
    self.mox.ReplayAll()
    gcl.CMDhelp([])


class ChangeInfoUnittest(GclTestsBase):
  def setUp(self):
    GclTestsBase.setUp(self)
    self.mox.StubOutWithMock(gcl, 'GetChangelistInfoFile')
    self.mox.StubOutWithMock(gcl, 'GetRepositoryRoot')

  def testChangeInfoMembers(self):
    self.mox.ReplayAll()
    members = [
      'AddComment', 'CloseIssue', 'Delete', 'Exists', 'GetFiles',
      'GetApprovingReviewers', 'GetFileNames', 'GetIssueDescription',
      'GetLocalRoot', 'Load',
      'MissingTests', 'NeedsUpload', 'PrimeLint', 'RpcServer', 'Save',
      'SendToRietveld',
      'SEPARATOR',
      'UpdateDescriptionFromIssue', 'UpdateRietveldDescription',
      'append_footer',
      'description', 'force_description', 'get_reviewers', 'issue', 'name',
      'needs_upload', 'patch', 'patchset', 'rietveld', 'update_reviewers',
    ]
    # If this test fails, you should add the relevant test.
    self.compareMembers(
        gcl.ChangeInfo('', 0, 0, '', None, self.fake_root_dir, 'foo', False),
        members)

  def testChangeInfoBase(self):
    files = [('M', 'foo'), ('A', 'bar')]
    self.mox.ReplayAll()
    o = gcl.ChangeInfo(
        'name2',
        '42',
        '53',
        'description2',
        files,
        self.fake_root_dir,
        'foo',
        False)
    self.assertEquals(o.name, 'name2')
    self.assertEquals(o.issue, 42)
    self.assertEquals(o.patchset, 53)
    self.assertEquals(o.description, 'description2')
    self.assertEquals(o.patch, None)
    self.assertEquals(o.GetFileNames(), ['foo', 'bar'])
    self.assertEquals(o.GetFiles(), files)
    self.assertEquals(o.GetLocalRoot(), self.fake_root_dir)

  def testLoadWithIssue(self):
    self.mox.StubOutWithMock(gcl, 'GetCodeReviewSetting')
    description = ["This is some description.", "force an extra separator."]
    gcl.GetChangelistInfoFile('bleh').AndReturn('bleeeh')
    gcl.os.path.exists('bleeeh').AndReturn(True)
    gcl.gclient_utils.FileRead('bleeeh').AndReturn(
      gcl.ChangeInfo.SEPARATOR.join(["42, 53", "G      b.cc"] + description))
    gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('foo')
    # Does an upgrade.
    gcl.GetChangelistInfoFile('bleh').AndReturn('bleeeh')
    gcl.gclient_utils.FileWrite('bleeeh', mox.IgnoreArg())
    self.mox.ReplayAll()

    change_info = gcl.ChangeInfo.Load('bleh', self.fake_root_dir, True, False)
    self.assertEquals(change_info.name, 'bleh')
    self.assertEquals(change_info.issue, 42)
    self.assertEquals(change_info.patchset, 53)
    self.assertEquals(change_info.description,
                      gcl.ChangeInfo.SEPARATOR.join(description))
    self.assertEquals(change_info.GetFiles(), [('G      ', 'b.cc')])

  def testLoadEmpty(self):
    self.mox.StubOutWithMock(gcl, 'GetCodeReviewSetting')
    gcl.GetChangelistInfoFile('bleh').AndReturn('bleeeh')
    gcl.os.path.exists('bleeeh').AndReturn(True)
    gcl.gclient_utils.FileRead('bleeeh').AndReturn(
        gcl.ChangeInfo.SEPARATOR.join(["", "", ""]))
    gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('foo')
    # Does an upgrade.
    gcl.GetChangelistInfoFile('bleh').AndReturn('bleeeh')
    gcl.gclient_utils.FileWrite('bleeeh', mox.IgnoreArg())
    self.mox.ReplayAll()

    change_info = gcl.ChangeInfo.Load('bleh', self.fake_root_dir, True, False)
    self.assertEquals(change_info.name, 'bleh')
    self.assertEquals(change_info.issue, 0)
    self.assertEquals(change_info.patchset, 0)
    self.assertEquals(change_info.description, "")
    self.assertEquals(change_info.GetFiles(), [])

  def testSaveEmpty(self):
    gcl.GetChangelistInfoFile('').AndReturn('foo')
    values = {
        'description': '', 'patchset': 2, 'issue': 1,
        'files': [], 'needs_upload': False, 'rietveld': 'https://foo'}
    gcl.gclient_utils.FileWrite(
        'foo', gcl.json.dumps(values, sort_keys=True, indent=2))
    self.mox.ReplayAll()

    change_info = gcl.ChangeInfo(
        '', 1, 2, '', None, self.fake_root_dir, 'foo', False)
    change_info.Save()

  def testSaveDirty(self):
    gcl.GetChangelistInfoFile('n').AndReturn('foo')
    values = {
        'description': 'des', 'patchset': 0, 'issue': 0,
        'files': [], 'needs_upload': True, 'rietveld': 'https://foo'}
    gcl.gclient_utils.FileWrite(
        'foo', gcl.json.dumps(values, sort_keys=True, indent=2))
    self.mox.ReplayAll()

    change_info = gcl.ChangeInfo('n', 0, 0, 'des', None, self.fake_root_dir,
                                 'foo', needs_upload=True)
    change_info.Save()


class CMDuploadUnittest(GclTestsBase):
  def setUp(self):
    GclTestsBase.setUp(self)
    self.mox.StubOutWithMock(gcl, 'CheckHomeForFile')
    self.mox.StubOutWithMock(gcl, 'DoPresubmitChecks')
    self.mox.StubOutWithMock(gcl, 'GenerateDiff')
    self.mox.StubOutWithMock(gcl, 'GetCodeReviewSetting')
    self.mox.StubOutWithMock(gcl, 'GetRepositoryRoot')
    self.mox.StubOutWithMock(gcl.ChangeInfo, 'SendToRietveld')
    self.mox.StubOutWithMock(gcl, 'TryChange')
    self.mox.StubOutWithMock(gcl.ChangeInfo, 'Load')

  def testNew(self):
    change_info = self.mox.CreateMock(gcl.ChangeInfo)
    change_info.name = 'naame'
    change_info.issue = 1
    change_info.patchset = 0
    change_info.description = 'deescription\n\nR=foo@bar.com',
    change_info.files = [('A', 'aa'), ('M', 'bb')]
    change_info.patch = None
    change_info.rietveld = 'https://my_server'
    files = [item[1] for item in change_info.files]
    output = presubmit_support.PresubmitOutput()
    gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
    #gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server')
    gcl.os.getcwd().AndReturn('somewhere')
    change_info.GetFiles().AndReturn(change_info.files)
    gcl.os.chdir('proout')
    change_info.get_reviewers().AndReturn('foo@bar.com')
    change_info.GetFileNames().AndReturn(files)
    gcl.GenerateDiff(files)
    gcl.upload.RealMain(['upload.py', '-y', '--server=https://my_server',
                         '-r', 'georges@example.com',
                         '--issue=1', '--title= '],
                         change_info.patch).AndReturn(("1",
                                                                    "2"))
    change_info.GetLocalRoot().AndReturn('proout')
    change_info.Save()
    change_info.PrimeLint()
    gcl.os.chdir('somewhere')
    gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to"
                         " submit a try. ***")
    gcl.sys.stdout.write("\n")
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    self.mox.ReplayAll()

    gcl.CMDupload(['naame', '-r', 'georges@example.com'])
    self.checkstdout('*** Upload does not submit a try; use gcl try to submit '
        'a try. ***\n'
        '*** Upload does not submit a try; use gcl try to submit a try. ***\n')

  def testServerOverride(self):
    change_info = gcl.ChangeInfo(
        'naame',
        0,
        0,
        'deescription',
        [('A', 'aa'), ('M', 'bb')],
        self.fake_root_dir,
        'my_server',
        False)
    self.mox.StubOutWithMock(change_info, 'Save')
    change_info.Save()
    output = presubmit_support.PresubmitOutput()
    gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
    gcl.tempfile.mkstemp(text=True).AndReturn((42, 'descfile'))
    gcl.os.write(42, change_info.description)
    gcl.os.close(42)
    gcl.GetCodeReviewSetting('CC_LIST')
    gcl.GetCodeReviewSetting('PRIVATE')
    gcl.GetCodeReviewSetting('PROJECT')
    gcl.os.getcwd().AndReturn('somewhere')
    gcl.os.chdir(change_info.GetLocalRoot())
    gcl.GenerateDiff(change_info.GetFileNames())
    gcl.upload.RealMain(
        [ 'upload.py', '-y', '--server=https://my_server', '--server=a',
          '--file=descfile'],
        change_info.patch).AndReturn(("1", "2"))
    gcl.os.remove('descfile')
    change_info.SendToRietveld("/lint/issue%s_%s" % ('1', '2'), timeout=60)
    gcl.os.chdir('somewhere')
    gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to"
                         " submit a try. ***")
    gcl.sys.stdout.write("\n")
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    self.mox.ReplayAll()

    gcl.CMDupload(['naame', '--server=a', '--no_watchlists'])
    self.checkstdout('*** Upload does not submit a try; use gcl try to submit '
        'a try. ***\n'
        '*** Upload does not submit a try; use gcl try to submit a try. ***\n')

  def testNormal(self):
    change_info = gcl.ChangeInfo(
        'naame',
        0,
        0,
        'deescription',
        [('A', 'aa'), ('M', 'bb')],
        self.fake_root_dir,
        'my_server',
        False)
    self.mox.StubOutWithMock(change_info, 'Save')
    change_info.Save()
    output = presubmit_support.PresubmitOutput()
    gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
    gcl.tempfile.mkstemp(text=True).AndReturn((42, 'descfile'))
    gcl.os.write(42, change_info.description)
    gcl.os.close(42)
    gcl.GetCodeReviewSetting('CC_LIST')
    gcl.GetCodeReviewSetting('PRIVATE')
    gcl.GetCodeReviewSetting('PROJECT')
    gcl.os.getcwd().AndReturn('somewhere')
    gcl.os.chdir(change_info.GetLocalRoot())
    gcl.GenerateDiff(change_info.GetFileNames())
    gcl.upload.RealMain(
        ['upload.py', '-y', '--server=https://my_server', "--file=descfile" ],
        change_info.patch).AndReturn(("1", "2"))
    gcl.os.remove('descfile')
    change_info.SendToRietveld("/lint/issue%s_%s" % ('1', '2'), timeout=60)
    gcl.os.chdir('somewhere')
    gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to"
                         " submit a try. ***")
    gcl.sys.stdout.write("\n")
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    self.mox.ReplayAll()

    gcl.CMDupload(['naame', '--no_watchlists'])
    self.assertEquals(change_info.issue, 1)
    self.assertEquals(change_info.patchset, 2)
    self.checkstdout('*** Upload does not submit a try; use gcl try to submit '
        'a try. ***\n'
        '*** Upload does not submit a try; use gcl try to submit a try. ***\n')

  def testNoServer(self):
    self.mox.StubOutWithMock(gcl.sys, 'stderr')
    gcl.sys.stderr.write(
        'Don\'t use the -s flag, fix codereview.settings instead')
    gcl.sys.stderr.write('\n')
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(1)
    self.mox.ReplayAll()

    try:
      gcl.CMDupload(['naame', '-s', 'foo'])
      self.fail()
    except SystemExit:
      pass

  def testReviewersInDescription(self):
    change_info = self.mox.CreateMock(gcl.ChangeInfo)
    change_info.name = 'naame'
    change_info.issue = 1
    change_info.patchset = 0
    change_info.description = 'deescription\n\nR=georges@example.com',
    change_info.files = [('A', 'aa'), ('M', 'bb')]
    change_info.patch = None
    change_info.rietveld = 'https://my_server'
    files = [item[1] for item in change_info.files]
    output = presubmit_support.PresubmitOutput()
    gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
    #gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server')
    gcl.os.getcwd().AndReturn('somewhere')
    change_info.GetFiles().AndReturn(change_info.files)
    change_info.get_reviewers().AndReturn(['georges@example.com'])
    change_info.GetFileNames().AndReturn(files)
    change_info.GetLocalRoot().AndReturn('proout')
    gcl.os.chdir('proout')
    gcl.GenerateDiff(files)
    gcl.upload.RealMain(['upload.py', '-y', '--server=https://my_server',
                         '--reviewers=georges@example.com',
                         '--issue=1', '--title= '],
                         change_info.patch).AndReturn(("1", "2"))
    change_info.Save()
    change_info.PrimeLint()
    gcl.os.chdir('somewhere')
    gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to"
                         " submit a try. ***")
    gcl.sys.stdout.write("\n")
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    self.mox.ReplayAll()

    gcl.CMDupload(['naame'])
    self.checkstdout('*** Upload does not submit a try; use gcl try to submit '
        'a try. ***\n'
        '*** Upload does not submit a try; use gcl try to submit a try. ***\n')

  def testSuggestReviewers(self):
    change_info = self.fakeChange()
    output = presubmit_support.PresubmitOutput()
    output.reviewers = ['foo@example.com', 'bar@example.com']
    gcl.DoPresubmitChecks(change_info, False, True).AndReturn(output)
    #gcl.GetCodeReviewSetting('CODE_REVIEW_SERVER').AndReturn('my_server')
    gcl.os.getcwd().AndReturn('somewhere')
    gcl.os.chdir('proout')
    gcl.GenerateDiff(change_info.GetFileNames())
    gcl.upload.RealMain(['upload.py', '-y', '--server=https://my_server',
                         '--reviewers=foo@example.com,bar@example.com',
                         '--issue=1', '--title= '],
                         change_info.patch).AndReturn(("1", "2"))
    change_info.get_reviewers().AndReturn(['foo@example.com,bar@example.com'])
    change_info.Save()
    change_info.PrimeLint()
    gcl.os.chdir('somewhere')
    gcl.sys.stdout.write("*** Upload does not submit a try; use gcl try to"
                         " submit a try. ***")
    gcl.sys.stdout.write("\n")
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    self.mox.ReplayAll()

    gcl.CMDupload(['naame'])
    self.checkstdout('*** Upload does not submit a try; use gcl try to submit '
        'a try. ***\n'
        '*** Upload does not submit a try; use gcl try to submit a try. ***\n')


class CMDCommitUnittest(GclTestsBase):
  def mockLoad(self, files=None):
    self.mox.StubOutWithMock(gcl, 'GetRepositoryRoot')
    self.mox.StubOutWithMock(gcl.ChangeInfo, 'Load')
    gcl.GetRepositoryRoot().AndReturn(self.fake_root_dir)
    change_info = self.fakeChange(files)
    gcl.ChangeInfo.Load('naame', self.fake_root_dir, True, True
        ).AndReturn(change_info)
    return change_info

  def mockPresubmit(self, change_info, fail):
    self.mox.StubOutWithMock(gcl, 'OptionallyDoPresubmitChecks')
    output = presubmit_support.PresubmitOutput()
    if fail:
      output.fail()
    gcl.OptionallyDoPresubmitChecks(change_info, True, []).AndReturn(output)

  def mockCommit(self, change_info, commit_message, shell_output):
    gcl.tempfile.mkstemp(text=True).AndReturn((42, 'commit'))
    gcl.os.write(42, commit_message)
    gcl.os.close(42)
    gcl.tempfile.mkstemp(text=True).AndReturn((43, 'files'))
    gcl.os.write(43, '\n'.join(change_info.GetFileNames()))
    gcl.os.close(43)

    gcl.RunShell(['svn', 'commit', '--file=commit', '--targets=files'],
        True).AndReturn(shell_output)
    if 'Committed' in shell_output:
      self.mox.StubOutWithMock(gcl, 'GetCodeReviewSetting')
      gcl.GetCodeReviewSetting('VIEW_VC').AndReturn('http://view/')

    gcl.os.remove('commit')
    gcl.os.remove('files')

  def testPresubmitEmpty(self):
    self.mockLoad(files=[])
    self.mox.ReplayAll()

    retval = gcl.CMDcommit(['naame'])

    self.assertEquals(retval, 1)

  def testPresubmitFails(self):
    change_info = self.mockLoad()
    self.mockPresubmit(change_info, fail=True)
    self.mox.ReplayAll()

    retval = gcl.CMDcommit(['naame'])

    self.assertEquals(retval, 1)

  def testPresubmitSucceeds(self):
    change_info = self.mockLoad()
    self.mockPresubmit(change_info, fail=False)
    self.mockCommit(
        change_info, 'deescription\n\nReview URL: https://my_server/1', '')
    change_info.UpdateDescriptionFromIssue()
    change_info.GetApprovingReviewers().AndReturn(['a@c'])
    change_info.update_reviewers(['a@c'])
    self.mox.ReplayAll()

    retval = gcl.CMDcommit(['naame'])

    self.assertEquals(retval, 0)
    self.assertEquals(change_info.description, 'deescription')
    # pylint: disable=W0212
    self.assertFalse(change_info._deleted)
    self.assertFalse(change_info._closed)

  def testPresubmitSucceedsWithCommittedMessage(self):
    change_info = self.mockLoad()
    self.mockPresubmit(change_info, fail=False)
    self.mockCommit(
        change_info,
        'deescription\n\nReview URL: https://my_server/1',
        '\nCommitted revision 12345')
    change_info.UpdateDescriptionFromIssue()
    change_info.GetApprovingReviewers().AndReturn(['a@c'])
    change_info.update_reviewers(['a@c'])
    change_info.append_footer('Committed: http://view/12345')
    self.mox.ReplayAll()

    retval = gcl.CMDcommit(['naame'])
    self.assertEquals(retval, 0)
    # This is because append_footer is mocked.
    self.assertEquals(change_info.description, 'deescription')
    # pylint: disable=W0212
    self.assertTrue(change_info._deleted)
    self.assertTrue(change_info._closed)
    self.assertEqual(
        change_info._comments_added,
        ["Committed patchset #1 (id:1337) manually as r12345 (presubmit "
         "successful)."])


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