cros_interface_unittest.py revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# TODO(nduca): Rewrite what some of these tests to use mocks instead of
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# actually talking to the device. This would improve our coverage quite
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# a bit.
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import unittest
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import socket
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import sys
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core import util
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core.chrome import cros_browser_backend
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.core.chrome import cros_interface
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.test import options_for_unittests
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)from telemetry.test import run_tests
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CrOSInterfaceTest(unittest.TestCase):
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testDeviceSideProcessFailureToLaunch(self):
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def WillFail():
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dsp = cros_interface.DeviceSideProcess(
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cri,
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ['sfsdfskjflwejfweoij'])
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dsp.Close()
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertRaises(OSError, WillFail)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testDeviceSideProcessCloseDoesClose(self):
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    with cros_interface.DeviceSideProcess(
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cri,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ['sleep', '111']) as dsp:
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      procs = cri.ListProcesses()
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sleeps = [x for x in procs
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if x[1] == 'sleep 111']
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      assert dsp.IsAlive()
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    procs = cri.ListProcesses()
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sleeps = [x for x in procs
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              if x[1] == 'sleep 111']
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEquals(len(sleeps), 0)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testPushContents(self):
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri.RunCmdOnDevice(['rm', '-rf', '/tmp/testPushContents'])
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri.PushContents('hello world', '/tmp/testPushContents')
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    contents = cri.GetFileContents('/tmp/testPushContents')
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEquals(contents, 'hello world')
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testExists(self):
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo'))
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.FileExistsOnDevice('/etc/passwd'))
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj'))
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testExistsLocal(self):
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not sys.platform.startswith('linux'):
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface()
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo'))
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.FileExistsOnDevice('/etc/passwd'))
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj'))
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testGetFileContents(self): # pylint: disable=R0201
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hosts = cri.GetFileContents('/etc/hosts')
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    assert hosts.startswith('# /etc/hosts')
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testGetFileContentsForSomethingThatDoesntExist(self):
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertRaises(
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OSError,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      lambda: cri.GetFileContents('/tmp/209fuslfskjf/dfsfsf'))
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testListProcesses(self): # pylint: disable=R0201
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    with cros_interface.DeviceSideProcess(
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cri,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ['sleep', '11']):
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      procs = cri.ListProcesses()
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sleeps = [x for x in procs
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if x[1] == 'sleep 11']
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      assert len(sleeps) == 1
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testIsServiceRunning(self):
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.IsServiceRunning('openssh-server'))
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testIsServiceRunningLocal(self):
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if not sys.platform.startswith('linux'):
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface()
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.IsServiceRunning('dbus'))
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testGetRemotePortAndIsHTTPServerRunningOnPort(self):
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Create local server.
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sock = socket.socket()
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sock.bind(('', 0))
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    port = sock.getsockname()[1]
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sock.listen(0)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Get remote port and ensure that it was unused.
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_port = cri.GetRemotePort()
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port))
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Forward local server's port to remote device's remote_port.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    forwarder = cros_browser_backend.SSHForwarder(
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cri, 'R', util.PortPair(port, remote_port))
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # At this point, remote device should be able to connect to local server.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.IsHTTPServerRunningOnPort(remote_port))
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Next remote port shouldn't be the same as remote_port, since remote_port
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # is now in use.
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(cri.GetRemotePort() != remote_port)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Close forwarder and local server ports.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    forwarder.Close()
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    sock.close()
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Device should no longer be able to connect to remote_port since it is no
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # longer in use.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port))
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  @run_tests.RequiresBrowserOfType('cros-chrome')
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def testGetRemotePortReservedPorts(self):
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote = options_for_unittests.GetCopy().cros_remote
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cri = cros_interface.CrOSInterface(
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      remote,
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      options_for_unittests.GetCopy().cros_ssh_identity)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Should return 2 separate ports even though the first one isn't technically
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # being used yet.
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_port_1 = cri.GetRemotePort()
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    remote_port_2 = cri.GetRemotePort()
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(remote_port_1 != remote_port_2)
180