md5sum_test.py revision cef7893435aa41160dd1255c43cb8498279738cc
1#!/usr/bin/env python
2# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import os
7import unittest
8
9from devil import devil_env
10from devil.android import device_errors
11from devil.android import md5sum
12
13with devil_env.SysPath(devil_env.PYMOCK_PATH):
14  import mock  # pylint: disable=import-error
15
16TEST_OUT_DIR = os.path.join('test', 'out', 'directory')
17HOST_MD5_EXECUTABLE = os.path.join(TEST_OUT_DIR, 'md5sum_bin_host')
18MD5_DIST = os.path.join(TEST_OUT_DIR, 'md5sum_dist')
19
20
21class Md5SumTest(unittest.TestCase):
22
23  def setUp(self):
24    mocked_attrs = {
25      'md5sum_host': HOST_MD5_EXECUTABLE,
26      'md5sum_device': MD5_DIST,
27    }
28    self._patchers = [
29      mock.patch('devil.devil_env._Environment.FetchPath',
30                 mock.Mock(side_effect=lambda a, device=None: mocked_attrs[a])),
31      mock.patch('os.path.exists',
32                 new=mock.Mock(return_value=True)),
33    ]
34    for p in self._patchers:
35      p.start()
36
37  def tearDown(self):
38    for p in self._patchers:
39      p.stop()
40
41  def testCalculateHostMd5Sums_singlePath(self):
42    test_path = '/test/host/file.dat'
43    mock_get_cmd_output = mock.Mock(
44        return_value='0123456789abcdeffedcba9876543210 /test/host/file.dat')
45    with mock.patch('devil.utils.cmd_helper.GetCmdOutput',
46                    new=mock_get_cmd_output):
47      out = md5sum.CalculateHostMd5Sums(test_path)
48      self.assertEquals(1, len(out))
49      self.assertTrue('/test/host/file.dat' in out)
50      self.assertEquals('0123456789abcdeffedcba9876543210',
51                        out['/test/host/file.dat'])
52      mock_get_cmd_output.assert_called_once_with(
53          [HOST_MD5_EXECUTABLE, '/test/host/file.dat'])
54
55  def testCalculateHostMd5Sums_list(self):
56    test_paths = ['/test/host/file0.dat', '/test/host/file1.dat']
57    mock_get_cmd_output = mock.Mock(
58        return_value='0123456789abcdeffedcba9876543210 /test/host/file0.dat\n'
59                     '123456789abcdef00fedcba987654321 /test/host/file1.dat\n')
60    with mock.patch('devil.utils.cmd_helper.GetCmdOutput',
61                    new=mock_get_cmd_output):
62      out = md5sum.CalculateHostMd5Sums(test_paths)
63      self.assertEquals(2, len(out))
64      self.assertTrue('/test/host/file0.dat' in out)
65      self.assertEquals('0123456789abcdeffedcba9876543210',
66                        out['/test/host/file0.dat'])
67      self.assertTrue('/test/host/file1.dat' in out)
68      self.assertEquals('123456789abcdef00fedcba987654321',
69                        out['/test/host/file1.dat'])
70      mock_get_cmd_output.assert_called_once_with(
71          [HOST_MD5_EXECUTABLE, '/test/host/file0.dat',
72           '/test/host/file1.dat'])
73
74  def testCalculateHostMd5Sums_generator(self):
75    test_paths = ('/test/host/' + p for p in ['file0.dat', 'file1.dat'])
76    mock_get_cmd_output = mock.Mock(
77        return_value='0123456789abcdeffedcba9876543210 /test/host/file0.dat\n'
78                     '123456789abcdef00fedcba987654321 /test/host/file1.dat\n')
79    with mock.patch('devil.utils.cmd_helper.GetCmdOutput',
80                    new=mock_get_cmd_output):
81      out = md5sum.CalculateHostMd5Sums(test_paths)
82      self.assertEquals(2, len(out))
83      self.assertTrue('/test/host/file0.dat' in out)
84      self.assertEquals('0123456789abcdeffedcba9876543210',
85                        out['/test/host/file0.dat'])
86      self.assertTrue('/test/host/file1.dat' in out)
87      self.assertEquals('123456789abcdef00fedcba987654321',
88                        out['/test/host/file1.dat'])
89      mock_get_cmd_output.assert_called_once_with(
90          [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat'])
91
92  def testCalculateDeviceMd5Sums_noPaths(self):
93    device = mock.NonCallableMock()
94    device.RunShellCommand = mock.Mock(side_effect=Exception())
95
96    out = md5sum.CalculateDeviceMd5Sums([], device)
97    self.assertEquals(0, len(out))
98
99  def testCalculateDeviceMd5Sums_singlePath(self):
100    test_path = '/storage/emulated/legacy/test/file.dat'
101
102    device = mock.NonCallableMock()
103    device_md5sum_output = [
104        '0123456789abcdeffedcba9876543210 '
105            '/storage/emulated/legacy/test/file.dat',
106    ]
107    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
108
109    with mock.patch('os.path.getsize', return_value=1337):
110      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
111      self.assertEquals(1, len(out))
112      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
113      self.assertEquals('0123456789abcdeffedcba9876543210',
114                        out['/storage/emulated/legacy/test/file.dat'])
115      self.assertEquals(1, len(device.RunShellCommand.call_args_list))
116
117  def testCalculateDeviceMd5Sums_list(self):
118    test_path = ['/storage/emulated/legacy/test/file0.dat',
119                 '/storage/emulated/legacy/test/file1.dat']
120    device = mock.NonCallableMock()
121    device_md5sum_output = [
122        '0123456789abcdeffedcba9876543210 '
123            '/storage/emulated/legacy/test/file0.dat',
124        '123456789abcdef00fedcba987654321 '
125            '/storage/emulated/legacy/test/file1.dat',
126    ]
127    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
128
129    with mock.patch('os.path.getsize', return_value=1337):
130      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
131      self.assertEquals(2, len(out))
132      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
133      self.assertEquals('0123456789abcdeffedcba9876543210',
134                        out['/storage/emulated/legacy/test/file0.dat'])
135      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
136      self.assertEquals('123456789abcdef00fedcba987654321',
137                        out['/storage/emulated/legacy/test/file1.dat'])
138      self.assertEquals(1, len(device.RunShellCommand.call_args_list))
139
140  def testCalculateDeviceMd5Sums_generator(self):
141    test_path = ('/storage/emulated/legacy/test/file%d.dat' % n
142                 for n in xrange(0, 2))
143
144    device = mock.NonCallableMock()
145    device_md5sum_output = [
146        '0123456789abcdeffedcba9876543210 '
147            '/storage/emulated/legacy/test/file0.dat',
148        '123456789abcdef00fedcba987654321 '
149            '/storage/emulated/legacy/test/file1.dat',
150    ]
151    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
152
153    with mock.patch('os.path.getsize', return_value=1337):
154      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
155      self.assertEquals(2, len(out))
156      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
157      self.assertEquals('0123456789abcdeffedcba9876543210',
158                        out['/storage/emulated/legacy/test/file0.dat'])
159      self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out)
160      self.assertEquals('123456789abcdef00fedcba987654321',
161                        out['/storage/emulated/legacy/test/file1.dat'])
162      self.assertEquals(1, len(device.RunShellCommand.call_args_list))
163
164  def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self):
165    # See crbug/479966
166    test_path = '/storage/emulated/legacy/test/file.dat'
167
168    device = mock.NonCallableMock()
169    device_md5sum_output = [
170        'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: '
171            'unused DT entry: type 0x1d arg 0x15db',
172        'THIS_IS_NOT_A_VALID_CHECKSUM_ZZZ some random text',
173        '0123456789abcdeffedcba9876543210 '
174            '/storage/emulated/legacy/test/file.dat',
175    ]
176    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
177
178    with mock.patch('os.path.getsize', return_value=1337):
179      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
180      self.assertEquals(1, len(out))
181      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
182      self.assertEquals('0123456789abcdeffedcba9876543210',
183                        out['/storage/emulated/legacy/test/file.dat'])
184      self.assertEquals(1, len(device.RunShellCommand.call_args_list))
185
186  def testCalculateDeviceMd5Sums_list_fileMissing(self):
187    test_path = ['/storage/emulated/legacy/test/file0.dat',
188                 '/storage/emulated/legacy/test/file1.dat']
189    device = mock.NonCallableMock()
190    device_md5sum_output = [
191        '0123456789abcdeffedcba9876543210 '
192            '/storage/emulated/legacy/test/file0.dat',
193        '[0819/203513:ERROR:md5sum.cc(25)] Could not open file asdf',
194        '',
195    ]
196    device.RunShellCommand = mock.Mock(return_value=device_md5sum_output)
197
198    with mock.patch('os.path.getsize', return_value=1337):
199      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
200      self.assertEquals(1, len(out))
201      self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out)
202      self.assertEquals('0123456789abcdeffedcba9876543210',
203                        out['/storage/emulated/legacy/test/file0.dat'])
204      self.assertEquals(1, len(device.RunShellCommand.call_args_list))
205
206  def testCalculateDeviceMd5Sums_requiresBinary(self):
207    test_path = '/storage/emulated/legacy/test/file.dat'
208
209    device = mock.NonCallableMock()
210    device.adb = mock.NonCallableMock()
211    device.adb.Push = mock.Mock()
212    device_md5sum_output = [
213        'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: '
214            'unused DT entry: type 0x1d arg 0x15db',
215        'THIS_IS_NOT_A_VALID_CHECKSUM_ZZZ some random text',
216        '0123456789abcdeffedcba9876543210 '
217            '/storage/emulated/legacy/test/file.dat',
218    ]
219    error = device_errors.AdbShellCommandFailedError('cmd', 'out', 2)
220    device.RunShellCommand = mock.Mock(
221        side_effect=(error, '', device_md5sum_output))
222
223    with mock.patch('os.path.isdir', return_value=True), (
224         mock.patch('os.path.getsize', return_value=1337)):
225      out = md5sum.CalculateDeviceMd5Sums(test_path, device)
226      self.assertEquals(1, len(out))
227      self.assertTrue('/storage/emulated/legacy/test/file.dat' in out)
228      self.assertEquals('0123456789abcdeffedcba9876543210',
229                        out['/storage/emulated/legacy/test/file.dat'])
230      self.assertEquals(3, len(device.RunShellCommand.call_args_list))
231      device.adb.Push.assert_called_once_with(
232          'test/out/directory/md5sum_dist', '/data/local/tmp/md5sum')
233
234
235if __name__ == '__main__':
236  unittest.main(verbosity=2)
237
238