# Copyright 2013 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.

"""Tests for the AdbWrapper class."""

import os
import tempfile
import time
import unittest

from pylib.device import adb_wrapper
from pylib.device import device_errors


class TestAdbWrapper(unittest.TestCase):

  def setUp(self):
    devices = adb_wrapper.AdbWrapper.GetDevices()
    assert devices, 'A device must be attached'
    self._adb = devices[0]
    self._adb.WaitForDevice()

  @staticmethod
  def _MakeTempFile(contents):
    """Make a temporary file with the given contents.

    Args:
      contents: string to write to the temporary file.

    Returns:
      The absolute path to the file.
    """
    fi, path = tempfile.mkstemp()
    with os.fdopen(fi, 'wb') as f:
      f.write(contents)
    return path

  def testShell(self):
    output = self._adb.Shell('echo test', expect_rc=0)
    self.assertEqual(output.strip(), 'test')
    output = self._adb.Shell('echo test')
    self.assertEqual(output.strip(), 'test')
    self.assertRaises(device_errors.AdbShellCommandFailedError,
        self._adb.Shell, 'echo test', expect_rc=1)

  def testPushPull(self):
    path = self._MakeTempFile('foo')
    device_path = '/data/local/tmp/testfile.txt'
    local_tmpdir = os.path.dirname(path)
    self._adb.Push(path, device_path)
    self.assertEqual(self._adb.Shell('cat %s' % device_path), 'foo')
    self._adb.Pull(device_path, local_tmpdir)
    with open(os.path.join(local_tmpdir, 'testfile.txt'), 'r') as f:
      self.assertEqual(f.read(), 'foo')

  def testInstall(self):
    path = self._MakeTempFile('foo')
    self.assertRaises(device_errors.AdbCommandFailedError, self._adb.Install,
                      path)

  def testForward(self):
    self.assertRaises(device_errors.AdbCommandFailedError, self._adb.Forward,
                      0, 0)

  def testUninstall(self):
    self.assertRaises(device_errors.AdbCommandFailedError, self._adb.Uninstall,
        'some.nonexistant.package')

  def testRebootWaitForDevice(self):
    self._adb.Reboot()
    print 'waiting for device to reboot...'
    while self._adb.GetState() == 'device':
      time.sleep(1)
    self._adb.WaitForDevice()
    self.assertEqual(self._adb.GetState(), 'device')
    print 'waiting for package manager...'
    while 'package:' not in self._adb.Shell('pm path android'):
      time.sleep(1)

  def testRootRemount(self):
    self._adb.Root()
    while True:
      try:
        self._adb.Shell('start')
        break
      except device_errors.AdbCommandFailedError:
        time.sleep(1)
    self._adb.Remount()


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