#!/usr/bin/env python # Copyright 2014 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. import os import unittest from devil import devil_env from devil.android import device_errors from devil.android import md5sum with devil_env.SysPath(devil_env.PYMOCK_PATH): import mock # pylint: disable=import-error TEST_OUT_DIR = os.path.join('test', 'out', 'directory') HOST_MD5_EXECUTABLE = os.path.join(TEST_OUT_DIR, 'md5sum_bin_host') MD5_DIST = os.path.join(TEST_OUT_DIR, 'md5sum_dist') class Md5SumTest(unittest.TestCase): def setUp(self): mocked_attrs = { 'md5sum_host': HOST_MD5_EXECUTABLE, 'md5sum_device': MD5_DIST, } self._patchers = [ mock.patch( 'devil.devil_env._Environment.FetchPath', mock.Mock(side_effect=lambda a, device=None: mocked_attrs[a])), mock.patch('os.path.exists', new=mock.Mock(return_value=True)), ] for p in self._patchers: p.start() def tearDown(self): for p in self._patchers: p.stop() def testCalculateHostMd5Sums_singlePath(self): test_path = '/test/host/file.dat' mock_get_cmd_output = mock.Mock( return_value='0123456789abcdef') with mock.patch( 'devil.utils.cmd_helper.GetCmdOutput', new=mock_get_cmd_output): out = md5sum.CalculateHostMd5Sums(test_path) self.assertEquals(1, len(out)) self.assertTrue('/test/host/file.dat' in out) self.assertEquals('0123456789abcdef', out['/test/host/file.dat']) mock_get_cmd_output.assert_called_once_with( [HOST_MD5_EXECUTABLE, "-gz", mock.ANY]) def testCalculateHostMd5Sums_list(self): test_paths = ['/test/host/file0.dat', '/test/host/file1.dat'] mock_get_cmd_output = mock.Mock( return_value='0123456789abcdef\n123456789abcdef0\n') with mock.patch( 'devil.utils.cmd_helper.GetCmdOutput', new=mock_get_cmd_output): out = md5sum.CalculateHostMd5Sums(test_paths) self.assertEquals(2, len(out)) self.assertTrue('/test/host/file0.dat' in out) self.assertEquals('0123456789abcdef', out['/test/host/file0.dat']) self.assertTrue('/test/host/file1.dat' in out) self.assertEquals('123456789abcdef0', out['/test/host/file1.dat']) mock_get_cmd_output.assert_called_once_with( [HOST_MD5_EXECUTABLE, "-gz", mock.ANY]) def testCalculateDeviceMd5Sums_noPaths(self): device = mock.NonCallableMock() device.RunShellCommand = mock.Mock(side_effect=Exception()) out = md5sum.CalculateDeviceMd5Sums([], device) self.assertEquals(0, len(out)) def testCalculateDeviceMd5Sums_singlePath(self): test_path = '/storage/emulated/legacy/test/file.dat' device = mock.NonCallableMock() device_md5sum_output = ['0123456789abcdef',] device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) with mock.patch('os.path.getsize', return_value=1337): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(1, len(out)) self.assertTrue('/storage/emulated/legacy/test/file.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file.dat']) self.assertEquals(1, len(device.RunShellCommand.call_args_list)) def testCalculateDeviceMd5Sums_list(self): test_path = [ '/storage/emulated/legacy/test/file0.dat', '/storage/emulated/legacy/test/file1.dat' ] device = mock.NonCallableMock() device_md5sum_output = [ '0123456789abcdef', '123456789abcdef0', ] device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) with mock.patch('os.path.getsize', return_value=1337): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(2, len(out)) self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file0.dat']) self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out) self.assertEquals('123456789abcdef0', out['/storage/emulated/legacy/test/file1.dat']) self.assertEquals(1, len(device.RunShellCommand.call_args_list)) def testCalculateDeviceMd5Sums_generator(self): test_path = ('/storage/emulated/legacy/test/file%d.dat' % n for n in xrange(0, 2)) device = mock.NonCallableMock() device_md5sum_output = [ '0123456789abcdef', '123456789abcdef0', ] device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) with mock.patch('os.path.getsize', return_value=1337): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(2, len(out)) self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file0.dat']) self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out) self.assertEquals('123456789abcdef0', out['/storage/emulated/legacy/test/file1.dat']) self.assertEquals(1, len(device.RunShellCommand.call_args_list)) def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self): # See crbug/479966 test_path = '/storage/emulated/legacy/test/file.dat' device = mock.NonCallableMock() device_md5sum_output = [ 'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: ' 'unused DT entry: type 0x1d arg 0x15db', 'THIS_IS_NOT_A_VALID_CHECKSUM_ZZZ some random text', '0123456789abcdef', ] device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) with mock.patch('os.path.getsize', return_value=1337): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(1, len(out)) self.assertTrue('/storage/emulated/legacy/test/file.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file.dat']) self.assertEquals(1, len(device.RunShellCommand.call_args_list)) def testCalculateDeviceMd5Sums_list_fileMissing(self): test_path = [ '/storage/emulated/legacy/test/file0.dat', '/storage/emulated/legacy/test/file1.dat' ] device = mock.NonCallableMock() device_md5sum_output = [ '0123456789abcdef', '[0819/203513:ERROR:md5sum.cc(25)] Could not open file asdf', '', ] device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) with mock.patch('os.path.getsize', return_value=1337): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(1, len(out)) self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file0.dat']) self.assertEquals(1, len(device.RunShellCommand.call_args_list)) def testCalculateDeviceMd5Sums_requiresBinary(self): test_path = '/storage/emulated/legacy/test/file.dat' device = mock.NonCallableMock() device.adb = mock.NonCallableMock() device.adb.Push = mock.Mock() device_md5sum_output = [ 'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: ' 'unused DT entry: type 0x1d arg 0x15db', 'THIS_IS_NOT_A_VALID_CHECKSUM_ZZZ some random text', '0123456789abcdef', ] error = device_errors.AdbShellCommandFailedError('cmd', 'out', 2) device.RunShellCommand = mock.Mock( side_effect=(error, '', device_md5sum_output)) with mock.patch( 'os.path.isdir', return_value=True), (mock.patch( 'os.path.getsize', return_value=1337)): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(1, len(out)) self.assertTrue('/storage/emulated/legacy/test/file.dat' in out) self.assertEquals('0123456789abcdef', out['/storage/emulated/legacy/test/file.dat']) self.assertEquals(3, len(device.RunShellCommand.call_args_list)) device.adb.Push.assert_called_once_with('test/out/directory/md5sum_dist', '/data/local/tmp/md5sum') if __name__ == '__main__': unittest.main(verbosity=2)