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 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)from telemetry.unittest import options_for_unittests 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)from telemetry.unittest import RequiresBrowserOfType 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CrOSInterfaceTest(unittest.TestCase): 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testPushContents(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) cri.RunCmdOnDevice(['rm', '-rf', '/tmp/testPushContents']) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri.PushContents('hello world', '/tmp/testPushContents') 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents = cri.GetFileContents('/tmp/testPushContents') 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertEquals(contents, 'hello world') 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testExists(self): 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo')) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.FileExistsOnDevice('/etc/passwd')) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj')) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testExistsLocal(self): 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not sys.platform.startswith('linux'): 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface() 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.FileExistsOnDevice('/proc/cpuinfo')) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.FileExistsOnDevice('/etc/passwd')) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertFalse(cri.FileExistsOnDevice('/etc/sdlfsdjflskfjsflj')) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetFileContents(self): # pylint: disable=R0201 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) hosts = cri.GetFileContents('/etc/hosts') 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert hosts.startswith('# /etc/hosts') 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetFileContentsForSomethingThatDoesntExist(self): 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertRaises( 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OSError, 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) lambda: cri.GetFileContents('/tmp/209fuslfskjf/dfsfsf')) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testIsServiceRunning(self): 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.IsServiceRunning('openssh-server')) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testIsServiceRunningLocal(self): 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if not sys.platform.startswith('linux'): 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface() 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.IsServiceRunning('dbus')) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetRemotePortAndIsHTTPServerRunningOnPort(self): 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Create local server. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sock = socket.socket() 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sock.bind(('', 0)) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) port = sock.getsockname()[1] 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sock.listen(0) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Get remote port and ensure that it was unused. 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_port = cri.GetRemotePort() 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port)) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Forward local server's port to remote device's remote_port. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) forwarder = cros_browser_backend.SSHForwarder( 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri, 'R', util.PortPair(port, remote_port)) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # At this point, remote device should be able to connect to local server. 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.IsHTTPServerRunningOnPort(remote_port)) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Next remote port shouldn't be the same as remote_port, since remote_port 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # is now in use. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(cri.GetRemotePort() != remote_port) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Close forwarder and local server ports. 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) forwarder.Close() 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) sock.close() 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Device should no longer be able to connect to remote_port since it is no 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # longer in use. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertFalse(cri.IsHTTPServerRunningOnPort(remote_port)) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @RequiresBrowserOfType('cros-chrome') 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) def testGetRemotePortReservedPorts(self): 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote = options_for_unittests.GetCopy().cros_remote 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cri = cros_interface.CrOSInterface( 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote, 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Should return 2 separate ports even though the first one isn't technically 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # being used yet. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_port_1 = cri.GetRemotePort() 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remote_port_2 = cri.GetRemotePort() 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) self.assertTrue(remote_port_1 != remote_port_2) 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # TODO(tengs): It would be best if we can filter this test and other tests 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) # that need to be run locally based on the platform of the system browser. 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) def testEscapeCmdArguments(self): 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ''' Commands and their arguments that are executed through the cros 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) interface should follow bash syntax. This test needs to run on remotely 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) and locally on the device to check for consistency. 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ''' 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if not sys.platform.startswith('linux'): 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) cri = cros_interface.CrOSInterface( 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) options_for_unittests.GetCopy().cros_remote, 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) options_for_unittests.GetCopy().cros_ssh_identity) 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Check arguments with no special characters 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stdout, _ = cri.RunCmdOnDevice(['echo', '--arg1=value1', '--arg2=value2', 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) '--arg3="value3"']) 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assert(stdout.strip() == '--arg1=value1 --arg2=value2 --arg3=value3') 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Check argument with special characters escaped 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stdout, _ = cri.RunCmdOnDevice(['echo', '--arg=A\\; echo \\"B\\"']) 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assert(stdout.strip() == '--arg=A; echo "B"') 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Check argument with special characters in quotes 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) stdout, _ = cri.RunCmdOnDevice(['echo', "--arg='$HOME;;$PATH'"]) 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) assert(stdout.strip() == "--arg=$HOME;;$PATH") 159