1 # Copyright 2016 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import cStringIO 6 import json 7 import mock 8 import os 9 import shutil 10 import tempfile 11 import unittest 12 import urllib2 13 14 import common 15 16 from autotest_lib.site_utils import hwid_lib 17 18 19 class HwIdUnittests(unittest.TestCase): 20 """Unittest for testing get_hwid_info.""" 21 22 def setUp(self): 23 # Create tmp dir and dummy key files. 24 self.tmp_dir = tempfile.mkdtemp(prefix='hwid_test') 25 self.dummy_key = 'dummy_key' 26 self.dummy_key_file = os.path.join(self.tmp_dir, 'dummy_key') 27 with open(self.dummy_key_file, 'w') as f: 28 f.write(self.dummy_key) 29 self.dummy_key_file_spaces = os.path.join(self.tmp_dir, 30 'dummy_key_spaces') 31 with open(self.dummy_key_file_spaces, 'w') as f: 32 f.write(' %s ' % self.dummy_key) 33 self.dummy_key_file_newline = os.path.join(self.tmp_dir, 34 'dummy_key_newline') 35 with open(self.dummy_key_file_newline, 'w') as f: 36 f.write('%s\n' % self.dummy_key) 37 self.invalid_dummy_key_file = os.path.join(self.tmp_dir, 38 'invalid_dummy_key_file') 39 40 41 def tearDown(self): 42 mock.patch.stopall() 43 if os.path.exists(self.tmp_dir): 44 shutil.rmtree(self.tmp_dir) 45 46 47 def validate_exception(self, exception, *args): 48 """Helper method to validate proper exception is raised. 49 50 @param exception: The exception class to check against. 51 @param args: The unamed args to pass to func. 52 """ 53 with self.assertRaises(exception): 54 hwid_lib.get_hwid_info(*args) 55 56 57 def test_none_hwid(self): 58 """Test that an empty hwid raises a ValueError.""" 59 self.validate_exception(ValueError, None, None, None) 60 61 62 def test_invalid_info_type(self): 63 """Test that an invalid info type raises a ValueError.""" 64 self.validate_exception(ValueError, 'hwid', 'invalid_info_type', None) 65 66 67 def test_fail_open_with_nonexistent_file(self): 68 """Test that trying to open non-existent file will raise an IOError.""" 69 self.validate_exception(IOError, 'hwid', hwid_lib.HWID_INFO_BOM, 70 self.invalid_dummy_key_file) 71 72 73 @mock.patch('urllib2.urlopen', side_effect=urllib2.URLError('url error')) 74 def test_fail_to_open_url_urlerror(self, *args, **dargs): 75 """Test that failing to open a url will raise a HwIdException.""" 76 self.validate_exception(hwid_lib.HwIdException, 'hwid', 77 hwid_lib.HWID_INFO_BOM, self.dummy_key_file) 78 79 80 # pylint: disable=missing-docstring 81 @mock.patch('urllib2.urlopen') 82 def test_fail_decode_hwid(self, mock_urlopen, *args, **dargs): 83 """Test that supplying bad json raises a HwIdException.""" 84 mock_page_contents = mock.Mock(wraps=cStringIO.StringIO('bad json')) 85 mock_urlopen.return_value = mock_page_contents 86 self.validate_exception(hwid_lib.HwIdException, 'hwid', 87 hwid_lib.HWID_INFO_BOM, self.dummy_key_file) 88 mock_page_contents.close.assert_called_once_with() 89 90 91 # pylint: disable=missing-docstring 92 @mock.patch('urllib2.urlopen') 93 def test_success(self, mock_urlopen, *args, **dargs): 94 """Test that get_hwid_info successfully returns a hwid dict. 95 96 We want to check that it works on all valid info types. 97 """ 98 returned_json = '{"key1": "data1"}' 99 expected_dict = json.loads(returned_json) 100 for valid_info_type in hwid_lib.HWID_INFO_TYPES: 101 mock_page_contents = mock.Mock( 102 wraps=cStringIO.StringIO(returned_json)) 103 mock_urlopen.return_value = mock_page_contents 104 self.assertEqual(hwid_lib.get_hwid_info('hwid', valid_info_type, 105 self.dummy_key_file), 106 expected_dict) 107 mock_page_contents.close.assert_called_once_with() 108 109 110 # pylint: disable=missing-docstring 111 @mock.patch('urllib2.urlopen') 112 def test_url_properly_constructed(self, mock_urlopen, *args, **dargs): 113 """Test that the url is properly constructed. 114 115 Let's make sure that the key is properly cleaned before getting 116 inserted into the url by trying all the different dummy_key_files. 117 """ 118 info_type = hwid_lib.HWID_INFO_BOM 119 hwid = 'mock_hwid' 120 expected_url = ('%s/%s/%s/%s/?key=%s' % (hwid_lib.HWID_BASE_URL, 121 hwid_lib.HWID_VERSION, 122 info_type, hwid, 123 self.dummy_key)) 124 125 for dummy_key_file in [self.dummy_key_file, 126 self.dummy_key_file_spaces, 127 self.dummy_key_file_newline]: 128 mock_page_contents = mock.Mock(wraps=cStringIO.StringIO('{}')) 129 mock_urlopen.return_value = mock_page_contents 130 hwid_lib.get_hwid_info(hwid, info_type, dummy_key_file) 131 mock_urlopen.assert_called_with(expected_url) 132 133 134 # pylint: disable=missing-docstring 135 @mock.patch('urllib2.urlopen') 136 def test_url_properly_constructed_again(self, mock_urlopen, *args, **dargs): 137 """Test that the url is properly constructed with special hwid. 138 139 Let's make sure that a hwid with a space is properly transformed. 140 """ 141 info_type = hwid_lib.HWID_INFO_BOM 142 hwid = 'mock hwid with space' 143 hwid_quoted = 'mock%20hwid%20with%20space' 144 expected_url = ('%s/%s/%s/%s/?key=%s' % (hwid_lib.HWID_BASE_URL, 145 hwid_lib.HWID_VERSION, 146 info_type, hwid_quoted, 147 self.dummy_key)) 148 149 mock_page_contents = mock.Mock(wraps=cStringIO.StringIO('{}')) 150 mock_urlopen.return_value = mock_page_contents 151 hwid_lib.get_hwid_info(hwid, info_type, self.dummy_key_file) 152 mock_urlopen.assert_called_with(expected_url) 153 154 155 def test_dummy_key_file(self): 156 """Test that we get an empty dict with a dummy key file.""" 157 info_type = hwid_lib.HWID_INFO_BOM 158 hwid = 'mock hwid with space' 159 key_file = hwid_lib.KEY_FILENAME_NO_HWID 160 self.assertEqual(hwid_lib.get_hwid_info(hwid, info_type, key_file), {}) 161 162 163 if __name__ == '__main__': 164 unittest.main() 165