#!/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.

"""Setups a local Rietveld instance to test against a live server for
integration tests.

It makes sure Google AppEngine SDK is found, download Rietveld and Django code
if necessary and starts the server on a free inbound TCP port.
"""

import logging
import optparse
import os
import shutil
import socket
import sys
import tempfile
import time

try:
  import subprocess2
except ImportError:
  sys.path.append(
      os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
  import subprocess2


class Failure(Exception):
  pass


def test_port(port):
  s = socket.socket()
  try:
    return s.connect_ex(('127.0.0.1', port)) == 0
  finally:
    s.close()


def find_free_port(start_port):
  """Search for a free port starting at specified port."""
  for port in xrange(start_port, (2<<16)):
    if not test_port(port):
      return port
  raise Failure('Having issues finding an available port')


class LocalRietveld(object):
  """Downloads everything needed to run a local instance of Rietveld."""

  def __init__(self, base_dir=None):
    # Paths
    self.base_dir = base_dir
    if not self.base_dir:
      self.base_dir = os.path.dirname(os.path.abspath(__file__))
    # TODO(maruel): This should be in /tmp but that would mean having to fetch
    # everytime. This test is already annoyingly slow.
    self.rietveld = os.path.join(self.base_dir, '_rietveld')
    self.rietveld_app = os.path.join(
        self.rietveld, 'appengine', 'chromium_rietveld')
    self.test_server = None
    self.port = None
    self.tempdir = None

    # Find the GAE SDK
    previous_dir = ''
    self.sdk_path = ''
    base_dir = self.base_dir
    while base_dir != previous_dir:
      previous_dir = base_dir
      self.sdk_path = os.path.join(base_dir, 'google_appengine')
      if not os.path.isfile(os.path.join(self.sdk_path, 'VERSION')):
        base_dir = os.path.dirname(base_dir)
    self.dev_app = os.path.join(self.sdk_path, 'dev_appserver.py')

  def install_prerequisites(self):
    # First, verify the Google AppEngine SDK is available.
    if not os.path.isfile(self.dev_app):
      raise Failure(
          'Install google_appengine sdk in %s or higher up' % self.base_dir)

    if os.path.isdir(os.path.join(self.rietveld, '.svn')):
      # Left over from subversion. Delete it.
      print('Deleting deprecated subversion rietveld files...')
      shutil.rmtree(self.rietveld)

    if os.path.isdir(os.path.join(self.rietveld, '.hg')):
      # Left over from mercurial. Delete it.
      print('Deleting deprecated mercurial rietveld files...')
      shutil.rmtree(self.rietveld)

    # Second, checkout rietveld if not available.
    if not os.path.isdir(self.rietveld):
      print('Checking out rietveld...')
      try:
        subprocess2.check_call(['git', 'init', self.rietveld])
        subprocess2.check_call(
            ['git', 'remote', 'add', '-f', 'origin',
             'https://chromium.googlesource.com/infra/infra.git'],
            cwd=self.rietveld)
        subprocess2.check_call(
            ['git', 'config', 'core.sparseCheckout', 'true'],
            cwd=self.rietveld)
        with file(os.path.join(self.rietveld, '.git/info/sparse-checkout'),
                  'w') as sparse_file:
          sparse_file.write('appengine/chromium_rietveld')
        subprocess2.check_call(
            ['git', 'pull', 'origin', 'master'],
            cwd=self.rietveld)
      except (OSError, subprocess2.CalledProcessError), e:
        raise Failure('Failed to clone rietveld. \n%s' % e)
    else:
      print('Syncing rietveld...')
      try:
        subprocess2.check_call(
            ['git', 'pull', 'origin', 'master'],
            cwd=self.rietveld)
      except (OSError, subprocess2.CalledProcessError), e:
        raise Failure('Failed to sync rietveld\n%s' % e)

  def start_server(self, verbose=False):
    self.install_prerequisites()
    assert not self.tempdir
    self.tempdir = tempfile.mkdtemp(prefix='rietveld_test')
    self.port = find_free_port(10000)
    admin_port = find_free_port(self.port + 1)
    if verbose:
      stdout = stderr = None
    else:
      stdout = subprocess2.PIPE
      stderr = subprocess2.STDOUT
    cmd = [
        sys.executable,
        self.dev_app,
        './app.yaml',  # Explicitly specify file to avoid bringing up backends.
        '--port', str(self.port),
        '--admin_port', str(admin_port),
        '--storage', self.tempdir,
        '--clear_search_indexes',
        '--skip_sdk_update_check',
    ]

    # CHEAP TRICK
    # By default you only want to bind on loopback but I'm testing over a
    # headless computer so it's useful to be able to access the test instance
    # remotely.
    if os.environ.get('GAE_LISTEN_ALL', '') == 'true':
      cmd.extend(('-a', '0.0.0.0'))
    logging.info(' '.join(cmd))
    self.test_server = subprocess2.Popen(
        cmd, stdout=stdout, stderr=stderr, cwd=self.rietveld_app)
    # Loop until port 127.0.0.1:port opens or the process dies.
    while not test_port(self.port):
      self.test_server.poll()
      if self.test_server.returncode is not None:
        if not verbose:
          out = self.test_server.communicate()[0]
        shutil.rmtree(self.tempdir)
        self.tempdir = None
        raise Failure(
            'Test rietveld instance failed early on port %s\n%s' %
              (self.port, out))
      time.sleep(0.01)

  def stop_server(self):
    if self.test_server:
      try:
        self.test_server.kill()
      except OSError:
        pass
      self.test_server.wait()
      self.test_server = None
      self.port = None
    if self.tempdir:
      shutil.rmtree(self.tempdir)
      self.tempdir = None


def main():
  parser = optparse.OptionParser()
  parser.add_option('-v', '--verbose', action='store_true')
  options, args = parser.parse_args()
  if args:
    parser.error('Unknown arguments: %s' % ' '.join(args))
  instance = LocalRietveld()
  try:
    instance.start_server(verbose=options.verbose)
    print 'Local rietveld instance started on port %d' % instance.port
    while True:
      time.sleep(0.1)
  finally:
    instance.stop_server()


if __name__ == '__main__':
  main()
