1*9c5db199SXin Li#!/usr/bin/python3 2*9c5db199SXin Li 3*9c5db199SXin Li# pylint: disable=missing-docstring 4*9c5db199SXin Li 5*9c5db199SXin Lifrom __future__ import absolute_import, division, print_function 6*9c5db199SXin Li 7*9c5db199SXin Liimport errno 8*9c5db199SXin Liimport io 9*9c5db199SXin Liimport itertools 10*9c5db199SXin Liimport logging 11*9c5db199SXin Liimport os 12*9c5db199SXin Liimport select 13*9c5db199SXin Liimport socket 14*9c5db199SXin Liimport subprocess 15*9c5db199SXin Liimport time 16*9c5db199SXin Liimport unittest 17*9c5db199SXin Li 18*9c5db199SXin Li# mock 1.0.0 (in site-packages/chromite/third_party/mock.py) 19*9c5db199SXin Li# which is an ancestor of Python's default library starting from Python 3.3. 20*9c5db199SXin Li# See https://docs.python.org/3/library/unittest.mock.html 21*9c5db199SXin Liimport mock as pymock 22*9c5db199SXin Liimport six 23*9c5db199SXin Lifrom six.moves import range, urllib 24*9c5db199SXin Li 25*9c5db199SXin Liimport common 26*9c5db199SXin Li 27*9c5db199SXin Lifrom autotest_lib.client.common_lib import autotemp, utils 28*9c5db199SXin Lifrom autotest_lib.client.common_lib.test_utils import mock 29*9c5db199SXin Li 30*9c5db199SXin Limetrics = utils.metrics_mock 31*9c5db199SXin Li 32*9c5db199SXin Li 33*9c5db199SXin Liclass test_read_one_line(unittest.TestCase): 34*9c5db199SXin Li def setUp(self): 35*9c5db199SXin Li self.god = mock.mock_god(ut=self) 36*9c5db199SXin Li self.god.stub_function(utils, "open") 37*9c5db199SXin Li 38*9c5db199SXin Li 39*9c5db199SXin Li def tearDown(self): 40*9c5db199SXin Li self.god.unstub_all() 41*9c5db199SXin Li 42*9c5db199SXin Li 43*9c5db199SXin Li def test_ip_to_long(self): 44*9c5db199SXin Li self.assertEqual(utils.ip_to_long('0.0.0.0'), 0) 45*9c5db199SXin Li self.assertEqual(utils.ip_to_long('255.255.255.255'), 4294967295) 46*9c5db199SXin Li self.assertEqual(utils.ip_to_long('192.168.0.1'), 3232235521) 47*9c5db199SXin Li self.assertEqual(utils.ip_to_long('1.2.4.8'), 16909320) 48*9c5db199SXin Li 49*9c5db199SXin Li 50*9c5db199SXin Li def test_long_to_ip(self): 51*9c5db199SXin Li self.assertEqual(utils.long_to_ip(0), '0.0.0.0') 52*9c5db199SXin Li self.assertEqual(utils.long_to_ip(4294967295), '255.255.255.255') 53*9c5db199SXin Li self.assertEqual(utils.long_to_ip(3232235521), '192.168.0.1') 54*9c5db199SXin Li self.assertEqual(utils.long_to_ip(16909320), '1.2.4.8') 55*9c5db199SXin Li 56*9c5db199SXin Li 57*9c5db199SXin Li def test_create_subnet_mask(self): 58*9c5db199SXin Li self.assertEqual(utils.create_subnet_mask(0), 0) 59*9c5db199SXin Li self.assertEqual(utils.create_subnet_mask(32), 4294967295) 60*9c5db199SXin Li self.assertEqual(utils.create_subnet_mask(25), 4294967168) 61*9c5db199SXin Li 62*9c5db199SXin Li 63*9c5db199SXin Li def test_format_ip_with_mask(self): 64*9c5db199SXin Li self.assertEqual(utils.format_ip_with_mask('192.168.0.1', 0), 65*9c5db199SXin Li '0.0.0.0/0') 66*9c5db199SXin Li self.assertEqual(utils.format_ip_with_mask('192.168.0.1', 32), 67*9c5db199SXin Li '192.168.0.1/32') 68*9c5db199SXin Li self.assertEqual(utils.format_ip_with_mask('192.168.0.1', 26), 69*9c5db199SXin Li '192.168.0.0/26') 70*9c5db199SXin Li self.assertEqual(utils.format_ip_with_mask('192.168.0.255', 26), 71*9c5db199SXin Li '192.168.0.192/26') 72*9c5db199SXin Li 73*9c5db199SXin Li 74*9c5db199SXin Li def create_test_file(self, contents): 75*9c5db199SXin Li test_file = six.StringIO(contents) 76*9c5db199SXin Li utils.open.expect_call("filename", "r").and_return(test_file) 77*9c5db199SXin Li 78*9c5db199SXin Li 79*9c5db199SXin Li def test_reads_one_line_file(self): 80*9c5db199SXin Li self.create_test_file("abc\n") 81*9c5db199SXin Li self.assertEqual("abc", utils.read_one_line("filename")) 82*9c5db199SXin Li self.god.check_playback() 83*9c5db199SXin Li 84*9c5db199SXin Li 85*9c5db199SXin Li def test_strips_read_lines(self): 86*9c5db199SXin Li self.create_test_file("abc \n") 87*9c5db199SXin Li self.assertEqual("abc ", utils.read_one_line("filename")) 88*9c5db199SXin Li self.god.check_playback() 89*9c5db199SXin Li 90*9c5db199SXin Li 91*9c5db199SXin Li def test_drops_extra_lines(self): 92*9c5db199SXin Li self.create_test_file("line 1\nline 2\nline 3\n") 93*9c5db199SXin Li self.assertEqual("line 1", utils.read_one_line("filename")) 94*9c5db199SXin Li self.god.check_playback() 95*9c5db199SXin Li 96*9c5db199SXin Li 97*9c5db199SXin Li def test_works_on_empty_file(self): 98*9c5db199SXin Li self.create_test_file("") 99*9c5db199SXin Li self.assertEqual("", utils.read_one_line("filename")) 100*9c5db199SXin Li self.god.check_playback() 101*9c5db199SXin Li 102*9c5db199SXin Li 103*9c5db199SXin Li def test_works_on_file_with_no_newlines(self): 104*9c5db199SXin Li self.create_test_file("line but no newline") 105*9c5db199SXin Li self.assertEqual("line but no newline", 106*9c5db199SXin Li utils.read_one_line("filename")) 107*9c5db199SXin Li self.god.check_playback() 108*9c5db199SXin Li 109*9c5db199SXin Li 110*9c5db199SXin Li def test_preserves_leading_whitespace(self): 111*9c5db199SXin Li self.create_test_file(" has leading whitespace") 112*9c5db199SXin Li self.assertEqual(" has leading whitespace", 113*9c5db199SXin Li utils.read_one_line("filename")) 114*9c5db199SXin Li 115*9c5db199SXin Li 116*9c5db199SXin Liclass test_write_one_line(unittest.TestCase): 117*9c5db199SXin Li def setUp(self): 118*9c5db199SXin Li self.god = mock.mock_god(ut=self) 119*9c5db199SXin Li self.god.stub_function(utils, "open") 120*9c5db199SXin Li 121*9c5db199SXin Li 122*9c5db199SXin Li def tearDown(self): 123*9c5db199SXin Li self.god.unstub_all() 124*9c5db199SXin Li 125*9c5db199SXin Li 126*9c5db199SXin Li def get_write_one_line_output(self, content): 127*9c5db199SXin Li test_file = mock.SaveDataAfterCloseStringIO() 128*9c5db199SXin Li utils.open.expect_call("filename", "w").and_return(test_file) 129*9c5db199SXin Li utils.write_one_line("filename", content) 130*9c5db199SXin Li self.god.check_playback() 131*9c5db199SXin Li return test_file.final_data 132*9c5db199SXin Li 133*9c5db199SXin Li 134*9c5db199SXin Li def test_writes_one_line_file(self): 135*9c5db199SXin Li self.assertEqual("abc\n", self.get_write_one_line_output("abc")) 136*9c5db199SXin Li 137*9c5db199SXin Li 138*9c5db199SXin Li def test_preserves_existing_newline(self): 139*9c5db199SXin Li self.assertEqual("abc\n", self.get_write_one_line_output("abc\n")) 140*9c5db199SXin Li 141*9c5db199SXin Li 142*9c5db199SXin Li def test_preserves_leading_whitespace(self): 143*9c5db199SXin Li self.assertEqual(" abc\n", self.get_write_one_line_output(" abc")) 144*9c5db199SXin Li 145*9c5db199SXin Li 146*9c5db199SXin Li def test_preserves_trailing_whitespace(self): 147*9c5db199SXin Li self.assertEqual("abc \n", self.get_write_one_line_output("abc ")) 148*9c5db199SXin Li 149*9c5db199SXin Li 150*9c5db199SXin Li def test_handles_empty_input(self): 151*9c5db199SXin Li self.assertEqual("\n", self.get_write_one_line_output("")) 152*9c5db199SXin Li 153*9c5db199SXin Li 154*9c5db199SXin Liclass test_open_write_close(unittest.TestCase): 155*9c5db199SXin Li def setUp(self): 156*9c5db199SXin Li self.god = mock.mock_god(ut=self) 157*9c5db199SXin Li self.god.stub_function(utils, "open") 158*9c5db199SXin Li 159*9c5db199SXin Li 160*9c5db199SXin Li def tearDown(self): 161*9c5db199SXin Li self.god.unstub_all() 162*9c5db199SXin Li 163*9c5db199SXin Li 164*9c5db199SXin Li def test_simple_functionality(self): 165*9c5db199SXin Li data = "\n\nwhee\n" 166*9c5db199SXin Li test_file = mock.SaveDataAfterCloseStringIO() 167*9c5db199SXin Li utils.open.expect_call("filename", "w").and_return(test_file) 168*9c5db199SXin Li utils.open_write_close("filename", data) 169*9c5db199SXin Li self.god.check_playback() 170*9c5db199SXin Li self.assertEqual(data, test_file.final_data) 171*9c5db199SXin Li 172*9c5db199SXin Li def test_binary_functionality(self): 173*9c5db199SXin Li data = bytearray([0, 1, 3, 23, 0, 71, 254, 255, 127, 128]) 174*9c5db199SXin Li test_file = mock.SaveDataAfterCloseBytesIO() 175*9c5db199SXin Li utils.open.expect_call("filename", "wb").and_return(test_file) 176*9c5db199SXin Li utils.open_write_close("filename", data, is_binary=True) 177*9c5db199SXin Li self.god.check_playback() 178*9c5db199SXin Li self.assertEqual(data, test_file.final_data) 179*9c5db199SXin Li 180*9c5db199SXin Li 181*9c5db199SXin Liclass test_read_keyval(unittest.TestCase): 182*9c5db199SXin Li def setUp(self): 183*9c5db199SXin Li self.god = mock.mock_god(ut=self) 184*9c5db199SXin Li self.god.stub_function(utils, "open") 185*9c5db199SXin Li self.god.stub_function(os.path, "isdir") 186*9c5db199SXin Li self.god.stub_function(os.path, "exists") 187*9c5db199SXin Li 188*9c5db199SXin Li 189*9c5db199SXin Li def tearDown(self): 190*9c5db199SXin Li self.god.unstub_all() 191*9c5db199SXin Li 192*9c5db199SXin Li 193*9c5db199SXin Li def create_test_file(self, filename, contents): 194*9c5db199SXin Li test_file = six.StringIO(contents) 195*9c5db199SXin Li os.path.exists.expect_call(filename).and_return(True) 196*9c5db199SXin Li utils.open.expect_call(filename).and_return(test_file) 197*9c5db199SXin Li 198*9c5db199SXin Li 199*9c5db199SXin Li def read_keyval(self, contents): 200*9c5db199SXin Li os.path.isdir.expect_call("file").and_return(False) 201*9c5db199SXin Li self.create_test_file("file", contents) 202*9c5db199SXin Li keyval = utils.read_keyval("file") 203*9c5db199SXin Li self.god.check_playback() 204*9c5db199SXin Li return keyval 205*9c5db199SXin Li 206*9c5db199SXin Li 207*9c5db199SXin Li def test_returns_empty_when_file_doesnt_exist(self): 208*9c5db199SXin Li os.path.isdir.expect_call("file").and_return(False) 209*9c5db199SXin Li os.path.exists.expect_call("file").and_return(False) 210*9c5db199SXin Li self.assertEqual({}, utils.read_keyval("file")) 211*9c5db199SXin Li self.god.check_playback() 212*9c5db199SXin Li 213*9c5db199SXin Li 214*9c5db199SXin Li def test_accesses_files_directly(self): 215*9c5db199SXin Li os.path.isdir.expect_call("file").and_return(False) 216*9c5db199SXin Li self.create_test_file("file", "") 217*9c5db199SXin Li utils.read_keyval("file") 218*9c5db199SXin Li self.god.check_playback() 219*9c5db199SXin Li 220*9c5db199SXin Li 221*9c5db199SXin Li def test_accesses_directories_through_keyval_file(self): 222*9c5db199SXin Li os.path.isdir.expect_call("dir").and_return(True) 223*9c5db199SXin Li self.create_test_file("dir/keyval", "") 224*9c5db199SXin Li utils.read_keyval("dir") 225*9c5db199SXin Li self.god.check_playback() 226*9c5db199SXin Li 227*9c5db199SXin Li 228*9c5db199SXin Li def test_values_are_rstripped(self): 229*9c5db199SXin Li keyval = self.read_keyval("a=b \n") 230*9c5db199SXin Li self.assertEquals(keyval, {"a": "b"}) 231*9c5db199SXin Li 232*9c5db199SXin Li 233*9c5db199SXin Li def test_comments_are_ignored(self): 234*9c5db199SXin Li keyval = self.read_keyval("a=b # a comment\n") 235*9c5db199SXin Li self.assertEquals(keyval, {"a": "b"}) 236*9c5db199SXin Li 237*9c5db199SXin Li 238*9c5db199SXin Li def test_integers_become_ints(self): 239*9c5db199SXin Li keyval = self.read_keyval("a=1\n") 240*9c5db199SXin Li self.assertEquals(keyval, {"a": 1}) 241*9c5db199SXin Li self.assertEquals(int, type(keyval["a"])) 242*9c5db199SXin Li 243*9c5db199SXin Li 244*9c5db199SXin Li def test_float_values_become_floats(self): 245*9c5db199SXin Li keyval = self.read_keyval("a=1.5\n") 246*9c5db199SXin Li self.assertEquals(keyval, {"a": 1.5}) 247*9c5db199SXin Li self.assertEquals(float, type(keyval["a"])) 248*9c5db199SXin Li 249*9c5db199SXin Li 250*9c5db199SXin Li def test_multiple_lines(self): 251*9c5db199SXin Li keyval = self.read_keyval("a=one\nb=two\n") 252*9c5db199SXin Li self.assertEquals(keyval, {"a": "one", "b": "two"}) 253*9c5db199SXin Li 254*9c5db199SXin Li 255*9c5db199SXin Li def test_the_last_duplicate_line_is_used(self): 256*9c5db199SXin Li keyval = self.read_keyval("a=one\nb=two\na=three\n") 257*9c5db199SXin Li self.assertEquals(keyval, {"a": "three", "b": "two"}) 258*9c5db199SXin Li 259*9c5db199SXin Li 260*9c5db199SXin Li def test_extra_equals_are_included_in_values(self): 261*9c5db199SXin Li keyval = self.read_keyval("a=b=c\n") 262*9c5db199SXin Li self.assertEquals(keyval, {"a": "b=c"}) 263*9c5db199SXin Li 264*9c5db199SXin Li 265*9c5db199SXin Li def test_non_alphanumeric_keynames_are_rejected(self): 266*9c5db199SXin Li self.assertRaises(ValueError, self.read_keyval, "a$=one\n") 267*9c5db199SXin Li 268*9c5db199SXin Li 269*9c5db199SXin Li def test_underscores_are_allowed_in_key_names(self): 270*9c5db199SXin Li keyval = self.read_keyval("a_b=value\n") 271*9c5db199SXin Li self.assertEquals(keyval, {"a_b": "value"}) 272*9c5db199SXin Li 273*9c5db199SXin Li 274*9c5db199SXin Li def test_dashes_are_allowed_in_key_names(self): 275*9c5db199SXin Li keyval = self.read_keyval("a-b=value\n") 276*9c5db199SXin Li self.assertEquals(keyval, {"a-b": "value"}) 277*9c5db199SXin Li 278*9c5db199SXin Li def test_empty_value_is_allowed(self): 279*9c5db199SXin Li keyval = self.read_keyval("a=\n") 280*9c5db199SXin Li self.assertEquals(keyval, {"a": ""}) 281*9c5db199SXin Li 282*9c5db199SXin Li 283*9c5db199SXin Liclass test_write_keyval(unittest.TestCase): 284*9c5db199SXin Li def setUp(self): 285*9c5db199SXin Li self.god = mock.mock_god(ut=self) 286*9c5db199SXin Li self.god.stub_function(utils, "open") 287*9c5db199SXin Li self.god.stub_function(os.path, "isdir") 288*9c5db199SXin Li 289*9c5db199SXin Li 290*9c5db199SXin Li def tearDown(self): 291*9c5db199SXin Li self.god.unstub_all() 292*9c5db199SXin Li 293*9c5db199SXin Li 294*9c5db199SXin Li def assertHasLines(self, value, lines): 295*9c5db199SXin Li vlines = value.splitlines() 296*9c5db199SXin Li vlines.sort() 297*9c5db199SXin Li self.assertEquals(vlines, sorted(lines)) 298*9c5db199SXin Li 299*9c5db199SXin Li 300*9c5db199SXin Li def write_keyval(self, filename, dictionary, expected_filename=None, 301*9c5db199SXin Li type_tag=None): 302*9c5db199SXin Li if expected_filename is None: 303*9c5db199SXin Li expected_filename = filename 304*9c5db199SXin Li test_file = six.StringIO() 305*9c5db199SXin Li self.god.stub_function(test_file, "close") 306*9c5db199SXin Li utils.open.expect_call(expected_filename, "a").and_return(test_file) 307*9c5db199SXin Li test_file.close.expect_call() 308*9c5db199SXin Li if type_tag is None: 309*9c5db199SXin Li utils.write_keyval(filename, dictionary) 310*9c5db199SXin Li else: 311*9c5db199SXin Li utils.write_keyval(filename, dictionary, type_tag) 312*9c5db199SXin Li return test_file.getvalue() 313*9c5db199SXin Li 314*9c5db199SXin Li 315*9c5db199SXin Li def write_keyval_file(self, dictionary, type_tag=None): 316*9c5db199SXin Li os.path.isdir.expect_call("file").and_return(False) 317*9c5db199SXin Li return self.write_keyval("file", dictionary, type_tag=type_tag) 318*9c5db199SXin Li 319*9c5db199SXin Li 320*9c5db199SXin Li def test_accesses_files_directly(self): 321*9c5db199SXin Li os.path.isdir.expect_call("file").and_return(False) 322*9c5db199SXin Li result = self.write_keyval("file", {"a": "1"}) 323*9c5db199SXin Li self.assertEquals(result, "a=1\n") 324*9c5db199SXin Li 325*9c5db199SXin Li 326*9c5db199SXin Li def test_accesses_directories_through_keyval_file(self): 327*9c5db199SXin Li os.path.isdir.expect_call("dir").and_return(True) 328*9c5db199SXin Li result = self.write_keyval("dir", {"b": "2"}, "dir/keyval") 329*9c5db199SXin Li self.assertEquals(result, "b=2\n") 330*9c5db199SXin Li 331*9c5db199SXin Li 332*9c5db199SXin Li def test_numbers_are_stringified(self): 333*9c5db199SXin Li result = self.write_keyval_file({"c": 3}) 334*9c5db199SXin Li self.assertEquals(result, "c=3\n") 335*9c5db199SXin Li 336*9c5db199SXin Li 337*9c5db199SXin Li def test_type_tags_are_excluded_by_default(self): 338*9c5db199SXin Li result = self.write_keyval_file({"d": "a string"}) 339*9c5db199SXin Li self.assertEquals(result, "d=a string\n") 340*9c5db199SXin Li self.assertRaises(ValueError, self.write_keyval_file, 341*9c5db199SXin Li {"d{perf}": "a string"}) 342*9c5db199SXin Li 343*9c5db199SXin Li 344*9c5db199SXin Li def test_perf_tags_are_allowed(self): 345*9c5db199SXin Li result = self.write_keyval_file({"a{perf}": 1, "b{perf}": 2}, 346*9c5db199SXin Li type_tag="perf") 347*9c5db199SXin Li self.assertHasLines(result, ["a{perf}=1", "b{perf}=2"]) 348*9c5db199SXin Li self.assertRaises(ValueError, self.write_keyval_file, 349*9c5db199SXin Li {"a": 1, "b": 2}, type_tag="perf") 350*9c5db199SXin Li 351*9c5db199SXin Li 352*9c5db199SXin Li def test_non_alphanumeric_keynames_are_rejected(self): 353*9c5db199SXin Li self.assertRaises(ValueError, self.write_keyval_file, {"x$": 0}) 354*9c5db199SXin Li 355*9c5db199SXin Li 356*9c5db199SXin Li def test_underscores_are_allowed_in_key_names(self): 357*9c5db199SXin Li result = self.write_keyval_file({"a_b": "value"}) 358*9c5db199SXin Li self.assertEquals(result, "a_b=value\n") 359*9c5db199SXin Li 360*9c5db199SXin Li 361*9c5db199SXin Li def test_dashes_are_allowed_in_key_names(self): 362*9c5db199SXin Li result = self.write_keyval_file({"a-b": "value"}) 363*9c5db199SXin Li self.assertEquals(result, "a-b=value\n") 364*9c5db199SXin Li 365*9c5db199SXin Li 366*9c5db199SXin Liclass test_is_url(unittest.TestCase): 367*9c5db199SXin Li def test_accepts_http(self): 368*9c5db199SXin Li self.assertTrue(utils.is_url("http://example.com")) 369*9c5db199SXin Li 370*9c5db199SXin Li 371*9c5db199SXin Li def test_accepts_ftp(self): 372*9c5db199SXin Li self.assertTrue(utils.is_url("ftp://ftp.example.com")) 373*9c5db199SXin Li 374*9c5db199SXin Li 375*9c5db199SXin Li def test_rejects_local_path(self): 376*9c5db199SXin Li self.assertFalse(utils.is_url("/home/username/file")) 377*9c5db199SXin Li 378*9c5db199SXin Li 379*9c5db199SXin Li def test_rejects_local_filename(self): 380*9c5db199SXin Li self.assertFalse(utils.is_url("filename")) 381*9c5db199SXin Li 382*9c5db199SXin Li 383*9c5db199SXin Li def test_rejects_relative_local_path(self): 384*9c5db199SXin Li self.assertFalse(utils.is_url("somedir/somesubdir/file")) 385*9c5db199SXin Li 386*9c5db199SXin Li 387*9c5db199SXin Li def test_rejects_local_path_containing_url(self): 388*9c5db199SXin Li self.assertFalse(utils.is_url("somedir/http://path/file")) 389*9c5db199SXin Li 390*9c5db199SXin Li 391*9c5db199SXin Liclass test_urlopen(unittest.TestCase): 392*9c5db199SXin Li def setUp(self): 393*9c5db199SXin Li self.god = mock.mock_god(ut=self) 394*9c5db199SXin Li 395*9c5db199SXin Li 396*9c5db199SXin Li def tearDown(self): 397*9c5db199SXin Li self.god.unstub_all() 398*9c5db199SXin Li 399*9c5db199SXin Li 400*9c5db199SXin Li def stub_urlopen_with_timeout_comparison(self, test_func, expected_return, 401*9c5db199SXin Li *expected_args): 402*9c5db199SXin Li expected_args += (None,) * (2 - len(expected_args)) 403*9c5db199SXin Li def urlopen(url, data=None): 404*9c5db199SXin Li self.assertEquals(expected_args, (url,data)) 405*9c5db199SXin Li test_func(socket.getdefaulttimeout()) 406*9c5db199SXin Li return expected_return 407*9c5db199SXin Li self.god.stub_with(urllib.request, "urlopen", urlopen) 408*9c5db199SXin Li 409*9c5db199SXin Li 410*9c5db199SXin Li def stub_urlopen_with_timeout_check(self, expected_timeout, 411*9c5db199SXin Li expected_return, *expected_args): 412*9c5db199SXin Li def test_func(timeout): 413*9c5db199SXin Li self.assertEquals(timeout, expected_timeout) 414*9c5db199SXin Li self.stub_urlopen_with_timeout_comparison(test_func, expected_return, 415*9c5db199SXin Li *expected_args) 416*9c5db199SXin Li 417*9c5db199SXin Li 418*9c5db199SXin Li def test_timeout_set_during_call(self): 419*9c5db199SXin Li self.stub_urlopen_with_timeout_check(30, "retval", "url") 420*9c5db199SXin Li retval = utils.urlopen("url", timeout=30) 421*9c5db199SXin Li self.assertEquals(retval, "retval") 422*9c5db199SXin Li 423*9c5db199SXin Li 424*9c5db199SXin Li def test_timeout_reset_after_call(self): 425*9c5db199SXin Li old_timeout = socket.getdefaulttimeout() 426*9c5db199SXin Li self.stub_urlopen_with_timeout_check(30, None, "url") 427*9c5db199SXin Li try: 428*9c5db199SXin Li socket.setdefaulttimeout(1234) 429*9c5db199SXin Li utils.urlopen("url", timeout=30) 430*9c5db199SXin Li self.assertEquals(1234, socket.getdefaulttimeout()) 431*9c5db199SXin Li finally: 432*9c5db199SXin Li socket.setdefaulttimeout(old_timeout) 433*9c5db199SXin Li 434*9c5db199SXin Li 435*9c5db199SXin Li def test_timeout_set_by_default(self): 436*9c5db199SXin Li def test_func(timeout): 437*9c5db199SXin Li self.assertTrue(timeout is not None) 438*9c5db199SXin Li self.stub_urlopen_with_timeout_comparison(test_func, None, "url") 439*9c5db199SXin Li utils.urlopen("url") 440*9c5db199SXin Li 441*9c5db199SXin Li 442*9c5db199SXin Li def test_args_are_untouched(self): 443*9c5db199SXin Li self.stub_urlopen_with_timeout_check(30, None, "http://url", 444*9c5db199SXin Li "POST data") 445*9c5db199SXin Li utils.urlopen("http://url", timeout=30, data="POST data") 446*9c5db199SXin Li 447*9c5db199SXin Li 448*9c5db199SXin Liclass test_urlretrieve(unittest.TestCase): 449*9c5db199SXin Li def setUp(self): 450*9c5db199SXin Li self.god = mock.mock_god(ut=self) 451*9c5db199SXin Li 452*9c5db199SXin Li 453*9c5db199SXin Li def tearDown(self): 454*9c5db199SXin Li self.god.unstub_all() 455*9c5db199SXin Li 456*9c5db199SXin Li 457*9c5db199SXin Li def test_urlopen_passed_arguments(self): 458*9c5db199SXin Li self.god.stub_function(utils, "urlopen") 459*9c5db199SXin Li self.god.stub_function(utils.shutil, "copyfileobj") 460*9c5db199SXin Li self.god.stub_function(utils, "open") 461*9c5db199SXin Li 462*9c5db199SXin Li url = "url" 463*9c5db199SXin Li dest = "somefile" 464*9c5db199SXin Li data = object() 465*9c5db199SXin Li timeout = 10 466*9c5db199SXin Li 467*9c5db199SXin Li src_file = self.god.create_mock_class(io.IOBase, "file") 468*9c5db199SXin Li dest_file = self.god.create_mock_class(io.IOBase, "file") 469*9c5db199SXin Li 470*9c5db199SXin Li (utils.urlopen.expect_call(url, data=data, timeout=timeout) 471*9c5db199SXin Li .and_return(src_file)) 472*9c5db199SXin Li utils.open.expect_call(dest, "wb").and_return(dest_file) 473*9c5db199SXin Li utils.shutil.copyfileobj.expect_call(src_file, dest_file) 474*9c5db199SXin Li dest_file.close.expect_call() 475*9c5db199SXin Li src_file.close.expect_call() 476*9c5db199SXin Li 477*9c5db199SXin Li utils.urlretrieve(url, dest, data=data, timeout=timeout) 478*9c5db199SXin Li self.god.check_playback() 479*9c5db199SXin Li 480*9c5db199SXin Li 481*9c5db199SXin Liclass test_merge_trees(unittest.TestCase): 482*9c5db199SXin Li # a some path-handling helper functions 483*9c5db199SXin Li def src(self, *path_segments): 484*9c5db199SXin Li return os.path.join(self.src_tree.name, *path_segments) 485*9c5db199SXin Li 486*9c5db199SXin Li 487*9c5db199SXin Li def dest(self, *path_segments): 488*9c5db199SXin Li return os.path.join(self.dest_tree.name, *path_segments) 489*9c5db199SXin Li 490*9c5db199SXin Li 491*9c5db199SXin Li def paths(self, *path_segments): 492*9c5db199SXin Li return self.src(*path_segments), self.dest(*path_segments) 493*9c5db199SXin Li 494*9c5db199SXin Li 495*9c5db199SXin Li def assertFileEqual(self, *path_segments): 496*9c5db199SXin Li src, dest = self.paths(*path_segments) 497*9c5db199SXin Li self.assertEqual(True, os.path.isfile(src)) 498*9c5db199SXin Li self.assertEqual(True, os.path.isfile(dest)) 499*9c5db199SXin Li self.assertEqual(os.path.getsize(src), os.path.getsize(dest)) 500*9c5db199SXin Li self.assertEqual(open(src).read(), open(dest).read()) 501*9c5db199SXin Li 502*9c5db199SXin Li 503*9c5db199SXin Li def assertFileContents(self, contents, *path_segments): 504*9c5db199SXin Li dest = self.dest(*path_segments) 505*9c5db199SXin Li self.assertEqual(True, os.path.isfile(dest)) 506*9c5db199SXin Li self.assertEqual(os.path.getsize(dest), len(contents)) 507*9c5db199SXin Li self.assertEqual(contents, open(dest).read()) 508*9c5db199SXin Li 509*9c5db199SXin Li 510*9c5db199SXin Li def setUp(self): 511*9c5db199SXin Li self.src_tree = autotemp.tempdir(unique_id='utilsrc') 512*9c5db199SXin Li self.dest_tree = autotemp.tempdir(unique_id='utilsdest') 513*9c5db199SXin Li 514*9c5db199SXin Li # empty subdirs 515*9c5db199SXin Li os.mkdir(self.src("empty")) 516*9c5db199SXin Li os.mkdir(self.dest("empty")) 517*9c5db199SXin Li 518*9c5db199SXin Li 519*9c5db199SXin Li def tearDown(self): 520*9c5db199SXin Li self.src_tree.clean() 521*9c5db199SXin Li self.dest_tree.clean() 522*9c5db199SXin Li 523*9c5db199SXin Li 524*9c5db199SXin Li def test_both_dont_exist(self): 525*9c5db199SXin Li utils.merge_trees(*self.paths("empty")) 526*9c5db199SXin Li 527*9c5db199SXin Li 528*9c5db199SXin Li def test_file_only_at_src(self): 529*9c5db199SXin Li with open(self.src("src_only"), "w") as wf: 530*9c5db199SXin Li print("line 1", file=wf) 531*9c5db199SXin Li utils.merge_trees(*self.paths("src_only")) 532*9c5db199SXin Li self.assertFileEqual("src_only") 533*9c5db199SXin Li 534*9c5db199SXin Li 535*9c5db199SXin Li def test_file_only_at_dest(self): 536*9c5db199SXin Li with open(self.dest("dest_only"), "w") as wf: 537*9c5db199SXin Li print("line 1", file=wf) 538*9c5db199SXin Li utils.merge_trees(*self.paths("dest_only")) 539*9c5db199SXin Li self.assertEqual(False, os.path.exists(self.src("dest_only"))) 540*9c5db199SXin Li self.assertFileContents("line 1\n", "dest_only") 541*9c5db199SXin Li 542*9c5db199SXin Li 543*9c5db199SXin Li def test_file_at_both(self): 544*9c5db199SXin Li with open(self.dest("in_both"), "w") as wf1: 545*9c5db199SXin Li print("line 1", file=wf1) 546*9c5db199SXin Li with open(self.src("in_both"), "w") as wf2: 547*9c5db199SXin Li print("line 2", file=wf2) 548*9c5db199SXin Li utils.merge_trees(*self.paths("in_both")) 549*9c5db199SXin Li self.assertFileContents("line 1\nline 2\n", "in_both") 550*9c5db199SXin Li 551*9c5db199SXin Li 552*9c5db199SXin Li def test_directory_with_files_in_both(self): 553*9c5db199SXin Li with open(self.dest("in_both"), "w") as wf1: 554*9c5db199SXin Li print("line 1", file=wf1) 555*9c5db199SXin Li with open(self.src("in_both"), "w") as wf2: 556*9c5db199SXin Li print("line 3", file=wf2) 557*9c5db199SXin Li utils.merge_trees(*self.paths()) 558*9c5db199SXin Li self.assertFileContents("line 1\nline 3\n", "in_both") 559*9c5db199SXin Li 560*9c5db199SXin Li 561*9c5db199SXin Li def test_directory_with_mix_of_files(self): 562*9c5db199SXin Li with open(self.dest("in_dest"), "w") as wf1: 563*9c5db199SXin Li print("dest line", file=wf1) 564*9c5db199SXin Li with open(self.src("in_src"), "w") as wf2: 565*9c5db199SXin Li print("src line", file=wf2) 566*9c5db199SXin Li utils.merge_trees(*self.paths()) 567*9c5db199SXin Li self.assertFileContents("dest line\n", "in_dest") 568*9c5db199SXin Li self.assertFileContents("src line\n", "in_src") 569*9c5db199SXin Li 570*9c5db199SXin Li 571*9c5db199SXin Li def test_directory_with_subdirectories(self): 572*9c5db199SXin Li os.mkdir(self.src("src_subdir")) 573*9c5db199SXin Li with open(self.src("src_subdir", "subfile"), "w") as wf1: 574*9c5db199SXin Li print("subdir line", file=wf1) 575*9c5db199SXin Li os.mkdir(self.src("both_subdir")) 576*9c5db199SXin Li os.mkdir(self.dest("both_subdir")) 577*9c5db199SXin Li with open(self.src("both_subdir", "subfile"), "w") as wf2: 578*9c5db199SXin Li print("src line", file=wf2) 579*9c5db199SXin Li with open(self.dest("both_subdir", "subfile"), "w") as wf3: 580*9c5db199SXin Li print("dest line", file=wf3) 581*9c5db199SXin Li utils.merge_trees(*self.paths()) 582*9c5db199SXin Li self.assertFileContents("subdir line\n", "src_subdir", "subfile") 583*9c5db199SXin Li self.assertFileContents("dest line\nsrc line\n", "both_subdir", 584*9c5db199SXin Li "subfile") 585*9c5db199SXin Li 586*9c5db199SXin Li 587*9c5db199SXin Liclass test_get_relative_path(unittest.TestCase): 588*9c5db199SXin Li def test_not_absolute(self): 589*9c5db199SXin Li self.assertRaises(AssertionError, utils.get_relative_path, "a", "b") 590*9c5db199SXin Li 591*9c5db199SXin Li def test_same_dir(self): 592*9c5db199SXin Li self.assertEqual(utils.get_relative_path("/a/b/c", "/a/b"), "c") 593*9c5db199SXin Li 594*9c5db199SXin Li def test_forward_dir(self): 595*9c5db199SXin Li self.assertEqual(utils.get_relative_path("/a/b/c/d", "/a/b"), "c/d") 596*9c5db199SXin Li 597*9c5db199SXin Li def test_previous_dir(self): 598*9c5db199SXin Li self.assertEqual(utils.get_relative_path("/a/b", "/a/b/c/d"), "../..") 599*9c5db199SXin Li 600*9c5db199SXin Li def test_parallel_dir(self): 601*9c5db199SXin Li self.assertEqual(utils.get_relative_path("/a/c/d", "/a/b/c/d"), 602*9c5db199SXin Li "../../../c/d") 603*9c5db199SXin Li 604*9c5db199SXin Li 605*9c5db199SXin Liclass test_sh_escape(unittest.TestCase): 606*9c5db199SXin Li def _test_in_shell(self, text): 607*9c5db199SXin Li escaped_text = utils.sh_escape(text) 608*9c5db199SXin Li proc = subprocess.Popen('echo "%s"' % escaped_text, shell=True, 609*9c5db199SXin Li stdin=open(os.devnull, 'r'), 610*9c5db199SXin Li stdout=subprocess.PIPE, 611*9c5db199SXin Li stderr=open(os.devnull, 'w')) 612*9c5db199SXin Li stdout, _ = proc.communicate() 613*9c5db199SXin Li self.assertEqual(proc.returncode, 0) 614*9c5db199SXin Li self.assertEqual(stdout[:-1].decode(), text) 615*9c5db199SXin Li 616*9c5db199SXin Li 617*9c5db199SXin Li def test_normal_string(self): 618*9c5db199SXin Li self._test_in_shell('abcd') 619*9c5db199SXin Li 620*9c5db199SXin Li 621*9c5db199SXin Li def test_spaced_string(self): 622*9c5db199SXin Li self._test_in_shell('abcd efgh') 623*9c5db199SXin Li 624*9c5db199SXin Li 625*9c5db199SXin Li def test_dollar(self): 626*9c5db199SXin Li self._test_in_shell('$') 627*9c5db199SXin Li 628*9c5db199SXin Li 629*9c5db199SXin Li def test_single_quote(self): 630*9c5db199SXin Li self._test_in_shell('\'') 631*9c5db199SXin Li 632*9c5db199SXin Li 633*9c5db199SXin Li def test_single_quoted_string(self): 634*9c5db199SXin Li self._test_in_shell('\'efgh\'') 635*9c5db199SXin Li 636*9c5db199SXin Li 637*9c5db199SXin Li def test_string_with_single_quote(self): 638*9c5db199SXin Li self._test_in_shell("a'b") 639*9c5db199SXin Li 640*9c5db199SXin Li 641*9c5db199SXin Li def test_string_with_escaped_single_quote(self): 642*9c5db199SXin Li self._test_in_shell(r"a\'b") 643*9c5db199SXin Li 644*9c5db199SXin Li 645*9c5db199SXin Li def test_double_quote(self): 646*9c5db199SXin Li self._test_in_shell('"') 647*9c5db199SXin Li 648*9c5db199SXin Li 649*9c5db199SXin Li def test_double_quoted_string(self): 650*9c5db199SXin Li self._test_in_shell('"abcd"') 651*9c5db199SXin Li 652*9c5db199SXin Li 653*9c5db199SXin Li def test_backtick(self): 654*9c5db199SXin Li self._test_in_shell('`') 655*9c5db199SXin Li 656*9c5db199SXin Li 657*9c5db199SXin Li def test_backticked_string(self): 658*9c5db199SXin Li self._test_in_shell('`jklm`') 659*9c5db199SXin Li 660*9c5db199SXin Li 661*9c5db199SXin Li def test_backslash(self): 662*9c5db199SXin Li self._test_in_shell('\\') 663*9c5db199SXin Li 664*9c5db199SXin Li 665*9c5db199SXin Li def test_backslashed_special_characters(self): 666*9c5db199SXin Li self._test_in_shell('\\$') 667*9c5db199SXin Li self._test_in_shell('\\"') 668*9c5db199SXin Li self._test_in_shell('\\\'') 669*9c5db199SXin Li self._test_in_shell('\\`') 670*9c5db199SXin Li 671*9c5db199SXin Li 672*9c5db199SXin Li def test_backslash_codes(self): 673*9c5db199SXin Li self._test_in_shell('\\n') 674*9c5db199SXin Li self._test_in_shell('\\r') 675*9c5db199SXin Li self._test_in_shell('\\t') 676*9c5db199SXin Li self._test_in_shell('\\v') 677*9c5db199SXin Li self._test_in_shell('\\b') 678*9c5db199SXin Li self._test_in_shell('\\a') 679*9c5db199SXin Li self._test_in_shell('\\000') 680*9c5db199SXin Li 681*9c5db199SXin Li def test_real_newline(self): 682*9c5db199SXin Li self._test_in_shell('\n') 683*9c5db199SXin Li self._test_in_shell('\\\n') 684*9c5db199SXin Li 685*9c5db199SXin Li 686*9c5db199SXin Liclass test_sh_quote_word(test_sh_escape): 687*9c5db199SXin Li """Run tests on sh_quote_word. 688*9c5db199SXin Li 689*9c5db199SXin Li Inherit from test_sh_escape to get the same tests to run on both. 690*9c5db199SXin Li """ 691*9c5db199SXin Li 692*9c5db199SXin Li def _test_in_shell(self, text): 693*9c5db199SXin Li quoted_word = utils.sh_quote_word(text) 694*9c5db199SXin Li echoed_value = subprocess.check_output('echo %s' % quoted_word, 695*9c5db199SXin Li shell=True) 696*9c5db199SXin Li self.assertEqual(echoed_value.decode(), text + '\n') 697*9c5db199SXin Li 698*9c5db199SXin Li 699*9c5db199SXin Liclass test_nested_sh_quote_word(test_sh_quote_word): 700*9c5db199SXin Li """Run nested tests on sh_quote_word. 701*9c5db199SXin Li 702*9c5db199SXin Li Inherit from test_sh_quote_word to get the same tests to run on both. 703*9c5db199SXin Li """ 704*9c5db199SXin Li 705*9c5db199SXin Li def _test_in_shell(self, text): 706*9c5db199SXin Li command = 'echo ' + utils.sh_quote_word(text) 707*9c5db199SXin Li nested_command = 'echo ' + utils.sh_quote_word(command) 708*9c5db199SXin Li produced_command = subprocess.check_output(nested_command, shell=True) 709*9c5db199SXin Li echoed_value = subprocess.check_output(produced_command, shell=True) 710*9c5db199SXin Li self.assertEqual(echoed_value.decode(), text + '\n') 711*9c5db199SXin Li 712*9c5db199SXin Li 713*9c5db199SXin Liclass test_run(unittest.TestCase): 714*9c5db199SXin Li """ 715*9c5db199SXin Li Test the utils.run() function. 716*9c5db199SXin Li 717*9c5db199SXin Li Note: This test runs simple external commands to test the utils.run() 718*9c5db199SXin Li API without assuming implementation details. 719*9c5db199SXin Li """ 720*9c5db199SXin Li 721*9c5db199SXin Li # Log levels in ascending severity. 722*9c5db199SXin Li LOG_LEVELS = [logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR, 723*9c5db199SXin Li logging.CRITICAL] 724*9c5db199SXin Li 725*9c5db199SXin Li 726*9c5db199SXin Li def setUp(self): 727*9c5db199SXin Li self.god = mock.mock_god(ut=self) 728*9c5db199SXin Li self.god.stub_function(utils.logging, 'warning') 729*9c5db199SXin Li self.god.stub_function(utils.logging, 'debug') 730*9c5db199SXin Li 731*9c5db199SXin Li # Log level -> StringIO.StringIO. 732*9c5db199SXin Li self.logs = {} 733*9c5db199SXin Li for level in self.LOG_LEVELS: 734*9c5db199SXin Li self.logs[level] = six.StringIO() 735*9c5db199SXin Li 736*9c5db199SXin Li # Override logging_manager.LoggingFile to return buffers. 737*9c5db199SXin Li def logging_file(level=None, prefix=None): 738*9c5db199SXin Li return self.logs[level] 739*9c5db199SXin Li self.god.stub_with(utils.logging_manager, 'LoggingFile', logging_file) 740*9c5db199SXin Li 741*9c5db199SXin Li def tearDown(self): 742*9c5db199SXin Li self.god.unstub_all() 743*9c5db199SXin Li 744*9c5db199SXin Li 745*9c5db199SXin Li def __check_result(self, result, command, exit_status=0, stdout='', 746*9c5db199SXin Li stderr=''): 747*9c5db199SXin Li self.assertEquals(result.command, command) 748*9c5db199SXin Li self.assertEquals(result.exit_status, exit_status) 749*9c5db199SXin Li self.assertEquals(result.stdout, stdout) 750*9c5db199SXin Li self.assertEquals(result.stderr, stderr) 751*9c5db199SXin Li 752*9c5db199SXin Li 753*9c5db199SXin Li def __get_logs(self): 754*9c5db199SXin Li """Returns contents of log buffers at all levels. 755*9c5db199SXin Li 756*9c5db199SXin Li @return: 5-element list of strings corresponding to logged messages 757*9c5db199SXin Li at the levels in self.LOG_LEVELS. 758*9c5db199SXin Li """ 759*9c5db199SXin Li return [self.logs[v].getvalue() for v in self.LOG_LEVELS] 760*9c5db199SXin Li 761*9c5db199SXin Li 762*9c5db199SXin Li def test_default_simple(self): 763*9c5db199SXin Li cmd = 'echo "hello world"' 764*9c5db199SXin Li # expect some king of logging.debug() call but don't care about args 765*9c5db199SXin Li utils.logging.debug.expect_any_call() 766*9c5db199SXin Li self.__check_result(utils.run(cmd), cmd, stdout='hello world\n') 767*9c5db199SXin Li 768*9c5db199SXin Li 769*9c5db199SXin Li def test_default_failure(self): 770*9c5db199SXin Li cmd = 'exit 11' 771*9c5db199SXin Li try: 772*9c5db199SXin Li utils.run(cmd, verbose=False) 773*9c5db199SXin Li except utils.error.CmdError as err: 774*9c5db199SXin Li self.__check_result(err.result_obj, cmd, exit_status=11) 775*9c5db199SXin Li 776*9c5db199SXin Li 777*9c5db199SXin Li def test_ignore_status(self): 778*9c5db199SXin Li cmd = 'echo error >&2 && exit 11' 779*9c5db199SXin Li self.__check_result(utils.run(cmd, ignore_status=True, verbose=False), 780*9c5db199SXin Li cmd, exit_status=11, stderr='error\n') 781*9c5db199SXin Li 782*9c5db199SXin Li 783*9c5db199SXin Li def test_timeout(self): 784*9c5db199SXin Li # we expect a logging.warning() message, don't care about the contents 785*9c5db199SXin Li utils.logging.warning.expect_any_call() 786*9c5db199SXin Li try: 787*9c5db199SXin Li utils.run('echo -n output && sleep 10', timeout=1, verbose=False) 788*9c5db199SXin Li except utils.error.CmdError as err: 789*9c5db199SXin Li self.assertEquals(err.result_obj.stdout, 'output') 790*9c5db199SXin Li 791*9c5db199SXin Li 792*9c5db199SXin Li def test_stdout_stderr_tee(self): 793*9c5db199SXin Li cmd = 'echo output && echo error >&2' 794*9c5db199SXin Li stdout_tee = six.StringIO() 795*9c5db199SXin Li stderr_tee = six.StringIO() 796*9c5db199SXin Li 797*9c5db199SXin Li self.__check_result(utils.run( 798*9c5db199SXin Li cmd, stdout_tee=stdout_tee, stderr_tee=stderr_tee, 799*9c5db199SXin Li verbose=False), cmd, stdout='output\n', stderr='error\n') 800*9c5db199SXin Li self.assertEqual(stdout_tee.getvalue(), 'output\n') 801*9c5db199SXin Li self.assertEqual(stderr_tee.getvalue(), 'error\n') 802*9c5db199SXin Li 803*9c5db199SXin Li 804*9c5db199SXin Li def test_stdin_string(self): 805*9c5db199SXin Li cmd = 'cat' 806*9c5db199SXin Li self.__check_result(utils.run(cmd, verbose=False, stdin='hi!\n'), 807*9c5db199SXin Li cmd, stdout='hi!\n') 808*9c5db199SXin Li 809*9c5db199SXin Li 810*9c5db199SXin Li def test_stdout_tee_to_logs_info(self): 811*9c5db199SXin Li """Test logging stdout at the info level.""" 812*9c5db199SXin Li utils.run('echo output', stdout_tee=utils.TEE_TO_LOGS, 813*9c5db199SXin Li stdout_level=logging.INFO, verbose=False) 814*9c5db199SXin Li self.assertEqual(self.__get_logs(), ['', 'output\n', '', '', '']) 815*9c5db199SXin Li 816*9c5db199SXin Li 817*9c5db199SXin Li def test_stdout_tee_to_logs_warning(self): 818*9c5db199SXin Li """Test logging stdout at the warning level.""" 819*9c5db199SXin Li utils.run('echo output', stdout_tee=utils.TEE_TO_LOGS, 820*9c5db199SXin Li stdout_level=logging.WARNING, verbose=False) 821*9c5db199SXin Li self.assertEqual(self.__get_logs(), ['', '', 'output\n', '', '']) 822*9c5db199SXin Li 823*9c5db199SXin Li 824*9c5db199SXin Li def test_stdout_and_stderr_tee_to_logs(self): 825*9c5db199SXin Li """Test simultaneous stdout and stderr log levels.""" 826*9c5db199SXin Li utils.run('echo output && echo error >&2', stdout_tee=utils.TEE_TO_LOGS, 827*9c5db199SXin Li stderr_tee=utils.TEE_TO_LOGS, stdout_level=logging.INFO, 828*9c5db199SXin Li stderr_level=logging.ERROR, verbose=False) 829*9c5db199SXin Li self.assertEqual(self.__get_logs(), ['', 'output\n', '', 'error\n', '']) 830*9c5db199SXin Li 831*9c5db199SXin Li 832*9c5db199SXin Li def test_default_expected_stderr_log_level(self): 833*9c5db199SXin Li """Test default expected stderr log level. 834*9c5db199SXin Li 835*9c5db199SXin Li stderr should be logged at the same level as stdout when 836*9c5db199SXin Li stderr_is_expected is true and stderr_level isn't passed. 837*9c5db199SXin Li """ 838*9c5db199SXin Li utils.run('echo output && echo error >&2', stdout_tee=utils.TEE_TO_LOGS, 839*9c5db199SXin Li stderr_tee=utils.TEE_TO_LOGS, stdout_level=logging.INFO, 840*9c5db199SXin Li stderr_is_expected=True, verbose=False) 841*9c5db199SXin Li self.assertEqual(self.__get_logs(), ['', 'output\nerror\n', '', '', '']) 842*9c5db199SXin Li 843*9c5db199SXin Li 844*9c5db199SXin Li def test_safe_args(self): 845*9c5db199SXin Li # NOTE: The string in expected_quoted_cmd depends on the internal 846*9c5db199SXin Li # implementation of shell quoting which is used by utils.run(), 847*9c5db199SXin Li # in this case, sh_quote_word(). 848*9c5db199SXin Li expected_quoted_cmd = "echo 'hello \"world' again" 849*9c5db199SXin Li self.__check_result(utils.run( 850*9c5db199SXin Li 'echo', verbose=False, args=('hello "world', 'again')), 851*9c5db199SXin Li expected_quoted_cmd, stdout='hello "world again\n') 852*9c5db199SXin Li 853*9c5db199SXin Li 854*9c5db199SXin Li def test_safe_args_given_string(self): 855*9c5db199SXin Li self.assertRaises(TypeError, utils.run, 'echo', args='hello') 856*9c5db199SXin Li 857*9c5db199SXin Li 858*9c5db199SXin Li def test_wait_interrupt(self): 859*9c5db199SXin Li """Test that we actually select twice if the first one returns EINTR.""" 860*9c5db199SXin Li utils.logging.debug.expect_any_call() 861*9c5db199SXin Li 862*9c5db199SXin Li bg_job = utils.BgJob('echo "hello world"') 863*9c5db199SXin Li bg_job.result.exit_status = 0 864*9c5db199SXin Li self.god.stub_function(utils.select, 'select') 865*9c5db199SXin Li 866*9c5db199SXin Li utils.select.select.expect_any_call().and_raises( 867*9c5db199SXin Li select.error(errno.EINTR, 'Select interrupted')) 868*9c5db199SXin Li utils.logging.warning.expect_any_call() 869*9c5db199SXin Li 870*9c5db199SXin Li utils.select.select.expect_any_call().and_return( 871*9c5db199SXin Li ([bg_job.sp.stdout, bg_job.sp.stderr], [], None)) 872*9c5db199SXin Li utils.logging.warning.expect_any_call() 873*9c5db199SXin Li 874*9c5db199SXin Li self.assertFalse( 875*9c5db199SXin Li utils._wait_for_commands([bg_job], time.time(), None)) 876*9c5db199SXin Li 877*9c5db199SXin Li 878*9c5db199SXin Liclass test_compare_versions(unittest.TestCase): 879*9c5db199SXin Li def test_zerofill(self): 880*9c5db199SXin Li self.assertEqual(utils.compare_versions('1.7', '1.10'), -1) 881*9c5db199SXin Li self.assertEqual(utils.compare_versions('1.222', '1.3'), 1) 882*9c5db199SXin Li self.assertEqual(utils.compare_versions('1.03', '1.3'), 0) 883*9c5db199SXin Li 884*9c5db199SXin Li 885*9c5db199SXin Li def test_unequal_len(self): 886*9c5db199SXin Li self.assertEqual(utils.compare_versions('1.3', '1.3.4'), -1) 887*9c5db199SXin Li self.assertEqual(utils.compare_versions('1.3.1', '1.3'), 1) 888*9c5db199SXin Li 889*9c5db199SXin Li 890*9c5db199SXin Li def test_dash_delimited(self): 891*9c5db199SXin Li self.assertEqual(utils.compare_versions('1-2-3', '1-5-1'), -1) 892*9c5db199SXin Li self.assertEqual(utils.compare_versions('1-2-1', '1-1-1'), 1) 893*9c5db199SXin Li self.assertEqual(utils.compare_versions('1-2-4', '1-2-4'), 0) 894*9c5db199SXin Li 895*9c5db199SXin Li 896*9c5db199SXin Li def test_alphabets(self): 897*9c5db199SXin Li self.assertEqual(utils.compare_versions('m.l.b', 'n.b.a'), -1) 898*9c5db199SXin Li self.assertEqual(utils.compare_versions('n.b.a', 'm.l.b'), 1) 899*9c5db199SXin Li self.assertEqual(utils.compare_versions('abc.e', 'abc.e'), 0) 900*9c5db199SXin Li 901*9c5db199SXin Li 902*9c5db199SXin Li def test_mix_symbols(self): 903*9c5db199SXin Li self.assertEqual(utils.compare_versions('k-320.1', 'k-320.3'), -1) 904*9c5db199SXin Li self.assertEqual(utils.compare_versions('k-231.5', 'k-231.1'), 1) 905*9c5db199SXin Li self.assertEqual(utils.compare_versions('k-231.1', 'k-231.1'), 0) 906*9c5db199SXin Li 907*9c5db199SXin Li self.assertEqual(utils.compare_versions('k.320-1', 'k.320-3'), -1) 908*9c5db199SXin Li self.assertEqual(utils.compare_versions('k.231-5', 'k.231-1'), 1) 909*9c5db199SXin Li self.assertEqual(utils.compare_versions('k.231-1', 'k.231-1'), 0) 910*9c5db199SXin Li 911*9c5db199SXin Li 912*9c5db199SXin Liclass test_args_to_dict(unittest.TestCase): 913*9c5db199SXin Li def test_no_args(self): 914*9c5db199SXin Li result = utils.args_to_dict([]) 915*9c5db199SXin Li self.assertEqual({}, result) 916*9c5db199SXin Li 917*9c5db199SXin Li 918*9c5db199SXin Li def test_matches(self): 919*9c5db199SXin Li result = utils.args_to_dict(['aBc:DeF', 'SyS=DEf', 'XY_Z:', 920*9c5db199SXin Li 'F__o0O=', 'B8r:=:=', '_bAZ_=:=:']) 921*9c5db199SXin Li self.assertEqual(result, {'abc':'DeF', 'sys':'DEf', 'xy_z':'', 922*9c5db199SXin Li 'f__o0o':'', 'b8r':'=:=', '_baz_':':=:'}) 923*9c5db199SXin Li 924*9c5db199SXin Li 925*9c5db199SXin Li def test_unmatches(self): 926*9c5db199SXin Li # Temporarily shut warning messages from args_to_dict() when an argument 927*9c5db199SXin Li # doesn't match its pattern. 928*9c5db199SXin Li logger = logging.getLogger() 929*9c5db199SXin Li saved_level = logger.level 930*9c5db199SXin Li logger.setLevel(logging.ERROR) 931*9c5db199SXin Li 932*9c5db199SXin Li try: 933*9c5db199SXin Li result = utils.args_to_dict(['ab-c:DeF', '--SyS=DEf', 'a*=b', 'a*b', 934*9c5db199SXin Li ':VAL', '=VVV', 'WORD']) 935*9c5db199SXin Li self.assertEqual({}, result) 936*9c5db199SXin Li finally: 937*9c5db199SXin Li # Restore level. 938*9c5db199SXin Li logger.setLevel(saved_level) 939*9c5db199SXin Li 940*9c5db199SXin Li 941*9c5db199SXin Liclass test_get_random_port(unittest.TestCase): 942*9c5db199SXin Li def do_bind(self, port, socket_type, socket_proto): 943*9c5db199SXin Li s = socket.socket(socket.AF_INET, socket_type, socket_proto) 944*9c5db199SXin Li s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 945*9c5db199SXin Li s.bind(('', port)) 946*9c5db199SXin Li return s 947*9c5db199SXin Li 948*9c5db199SXin Li 949*9c5db199SXin Li def test_get_port(self): 950*9c5db199SXin Li for _ in range(100): 951*9c5db199SXin Li p = utils.get_unused_port() 952*9c5db199SXin Li s = self.do_bind(p, socket.SOCK_STREAM, socket.IPPROTO_TCP) 953*9c5db199SXin Li self.assert_(s.getsockname()) 954*9c5db199SXin Li s = self.do_bind(p, socket.SOCK_DGRAM, socket.IPPROTO_UDP) 955*9c5db199SXin Li self.assert_(s.getsockname()) 956*9c5db199SXin Li 957*9c5db199SXin Li 958*9c5db199SXin Lidef test_function(arg1, arg2, arg3, arg4=4, arg5=5, arg6=6): 959*9c5db199SXin Li """Test global function. 960*9c5db199SXin Li """ 961*9c5db199SXin Li 962*9c5db199SXin Li 963*9c5db199SXin Liclass TestClass(object): 964*9c5db199SXin Li """Test class. 965*9c5db199SXin Li """ 966*9c5db199SXin Li 967*9c5db199SXin Li def test_instance_function(self, arg1, arg2, arg3, arg4=4, arg5=5, arg6=6): 968*9c5db199SXin Li """Test instance function. 969*9c5db199SXin Li """ 970*9c5db199SXin Li 971*9c5db199SXin Li 972*9c5db199SXin Li @classmethod 973*9c5db199SXin Li def test_class_function(cls, arg1, arg2, arg3, arg4=4, arg5=5, arg6=6): 974*9c5db199SXin Li """Test class function. 975*9c5db199SXin Li """ 976*9c5db199SXin Li 977*9c5db199SXin Li 978*9c5db199SXin Li @staticmethod 979*9c5db199SXin Li def test_static_function(arg1, arg2, arg3, arg4=4, arg5=5, arg6=6): 980*9c5db199SXin Li """Test static function. 981*9c5db199SXin Li """ 982*9c5db199SXin Li 983*9c5db199SXin Li 984*9c5db199SXin Liclass GetFunctionArgUnittest(unittest.TestCase): 985*9c5db199SXin Li """Tests for method get_function_arg_value.""" 986*9c5db199SXin Li 987*9c5db199SXin Li def run_test(self, func, insert_arg): 988*9c5db199SXin Li """Run test. 989*9c5db199SXin Li 990*9c5db199SXin Li @param func: Function being called with given arguments. 991*9c5db199SXin Li @param insert_arg: Set to True to insert an object in the argument list. 992*9c5db199SXin Li This is to mock instance/class object. 993*9c5db199SXin Li """ 994*9c5db199SXin Li if insert_arg: 995*9c5db199SXin Li args = (None, 1, 2, 3) 996*9c5db199SXin Li else: 997*9c5db199SXin Li args = (1, 2, 3) 998*9c5db199SXin Li for i in range(1, 7): 999*9c5db199SXin Li self.assertEquals(utils.get_function_arg_value( 1000*9c5db199SXin Li func, 'arg%d'%i, args, {}), i) 1001*9c5db199SXin Li 1002*9c5db199SXin Li self.assertEquals(utils.get_function_arg_value( 1003*9c5db199SXin Li func, 'arg7', args, {'arg7': 7}), 7) 1004*9c5db199SXin Li self.assertRaises( 1005*9c5db199SXin Li KeyError, utils.get_function_arg_value, 1006*9c5db199SXin Li func, 'arg3', args[:-1], {}) 1007*9c5db199SXin Li 1008*9c5db199SXin Li 1009*9c5db199SXin Li def test_global_function(self): 1010*9c5db199SXin Li """Test global function. 1011*9c5db199SXin Li """ 1012*9c5db199SXin Li self.run_test(test_function, False) 1013*9c5db199SXin Li 1014*9c5db199SXin Li 1015*9c5db199SXin Li def test_instance_function(self): 1016*9c5db199SXin Li """Test instance function. 1017*9c5db199SXin Li """ 1018*9c5db199SXin Li self.run_test(TestClass().test_instance_function, True) 1019*9c5db199SXin Li 1020*9c5db199SXin Li 1021*9c5db199SXin Li def test_class_function(self): 1022*9c5db199SXin Li """Test class function. 1023*9c5db199SXin Li """ 1024*9c5db199SXin Li self.run_test(TestClass.test_class_function, True) 1025*9c5db199SXin Li 1026*9c5db199SXin Li 1027*9c5db199SXin Li def test_static_function(self): 1028*9c5db199SXin Li """Test static function. 1029*9c5db199SXin Li """ 1030*9c5db199SXin Li self.run_test(TestClass.test_static_function, False) 1031*9c5db199SXin Li 1032*9c5db199SXin Li 1033*9c5db199SXin Liclass IsInSameSubnetUnittest(unittest.TestCase): 1034*9c5db199SXin Li """Test is_in_same_subnet function.""" 1035*9c5db199SXin Li 1036*9c5db199SXin Li def test_is_in_same_subnet(self): 1037*9c5db199SXin Li """Test is_in_same_subnet function.""" 1038*9c5db199SXin Li self.assertTrue(utils.is_in_same_subnet('192.168.0.0', '192.168.1.2', 1039*9c5db199SXin Li 23)) 1040*9c5db199SXin Li self.assertFalse(utils.is_in_same_subnet('192.168.0.0', '192.168.1.2', 1041*9c5db199SXin Li 24)) 1042*9c5db199SXin Li self.assertTrue(utils.is_in_same_subnet('192.168.0.0', '192.168.0.255', 1043*9c5db199SXin Li 24)) 1044*9c5db199SXin Li self.assertFalse(utils.is_in_same_subnet('191.168.0.0', '192.168.0.0', 1045*9c5db199SXin Li 24)) 1046*9c5db199SXin Li 1047*9c5db199SXin Li 1048*9c5db199SXin Liclass GetWirelessSsidUnittest(unittest.TestCase): 1049*9c5db199SXin Li """Test get_wireless_ssid function.""" 1050*9c5db199SXin Li 1051*9c5db199SXin Li DEFAULT_SSID = 'default' 1052*9c5db199SXin Li SSID_1 = 'ssid_1' 1053*9c5db199SXin Li SSID_2 = 'ssid_2' 1054*9c5db199SXin Li SSID_3 = 'ssid_3' 1055*9c5db199SXin Li 1056*9c5db199SXin Li def test_get_wireless_ssid(self): 1057*9c5db199SXin Li """Test is_in_same_subnet function.""" 1058*9c5db199SXin Li god = mock.mock_god() 1059*9c5db199SXin Li god.stub_function_to_return(utils.CONFIG, 'get_config_value', 1060*9c5db199SXin Li self.DEFAULT_SSID) 1061*9c5db199SXin Li god.stub_function_to_return(utils.CONFIG, 'get_config_value_regex', 1062*9c5db199SXin Li {'wireless_ssid_1.2.3.4/24': self.SSID_1, 1063*9c5db199SXin Li 'wireless_ssid_4.3.2.1/16': self.SSID_2, 1064*9c5db199SXin Li 'wireless_ssid_4.3.2.111/32': self.SSID_3}) 1065*9c5db199SXin Li self.assertEqual(self.SSID_1, utils.get_wireless_ssid('1.2.3.100')) 1066*9c5db199SXin Li self.assertEqual(self.SSID_2, utils.get_wireless_ssid('4.3.2.100')) 1067*9c5db199SXin Li self.assertEqual(self.SSID_3, utils.get_wireless_ssid('4.3.2.111')) 1068*9c5db199SXin Li self.assertEqual(self.DEFAULT_SSID, 1069*9c5db199SXin Li utils.get_wireless_ssid('100.0.0.100')) 1070*9c5db199SXin Li 1071*9c5db199SXin Li 1072*9c5db199SXin Liclass LaunchControlBuildParseUnittest(unittest.TestCase): 1073*9c5db199SXin Li """Test various parsing functions related to Launch Control builds and 1074*9c5db199SXin Li devices. 1075*9c5db199SXin Li """ 1076*9c5db199SXin Li 1077*9c5db199SXin Li def test_parse_launch_control_target(self): 1078*9c5db199SXin Li """Test parse_launch_control_target function.""" 1079*9c5db199SXin Li target_tests = { 1080*9c5db199SXin Li ('shamu', 'userdebug'): 'shamu-userdebug', 1081*9c5db199SXin Li ('shamu', 'eng'): 'shamu-eng', 1082*9c5db199SXin Li ('shamu-board', 'eng'): 'shamu-board-eng', 1083*9c5db199SXin Li (None, None): 'bad_target', 1084*9c5db199SXin Li (None, None): 'target'} 1085*9c5db199SXin Li for result, target in target_tests.items(): 1086*9c5db199SXin Li self.assertEqual(result, utils.parse_launch_control_target(target)) 1087*9c5db199SXin Li 1088*9c5db199SXin Li 1089*9c5db199SXin Liclass GetOffloaderUriTest(unittest.TestCase): 1090*9c5db199SXin Li """Test get_offload_gsuri function.""" 1091*9c5db199SXin Li _IMAGE_STORAGE_SERVER = 'gs://test_image_bucket' 1092*9c5db199SXin Li 1093*9c5db199SXin Li def setUp(self): 1094*9c5db199SXin Li self.god = mock.mock_god() 1095*9c5db199SXin Li 1096*9c5db199SXin Li def tearDown(self): 1097*9c5db199SXin Li self.god.unstub_all() 1098*9c5db199SXin Li 1099*9c5db199SXin Li def test_get_default_lab_offload_gsuri(self): 1100*9c5db199SXin Li """Test default lab offload gsuri .""" 1101*9c5db199SXin Li self.god.mock_up(utils.CONFIG, 'CONFIG') 1102*9c5db199SXin Li self.god.stub_function_to_return(utils, 'is_moblab', False) 1103*9c5db199SXin Li self.assertEqual(utils.DEFAULT_OFFLOAD_GSURI, 1104*9c5db199SXin Li utils.get_offload_gsuri()) 1105*9c5db199SXin Li 1106*9c5db199SXin Li self.god.check_playback() 1107*9c5db199SXin Li 1108*9c5db199SXin Li def test_get_default_moblab_offload_gsuri(self): 1109*9c5db199SXin Li self.god.mock_up(utils.CONFIG, 'CONFIG') 1110*9c5db199SXin Li self.god.stub_function_to_return(utils, 'is_moblab', True) 1111*9c5db199SXin Li utils.CONFIG.get_config_value.expect_call( 1112*9c5db199SXin Li 'CROS', 'image_storage_server').and_return( 1113*9c5db199SXin Li self._IMAGE_STORAGE_SERVER) 1114*9c5db199SXin Li self.god.stub_function_to_return(utils, 1115*9c5db199SXin Li 'get_moblab_serial_number', 'test_serial_number') 1116*9c5db199SXin Li self.god.stub_function_to_return(utils, 'get_moblab_id', 'test_id') 1117*9c5db199SXin Li expected_gsuri = '%sresults/%s/%s/' % ( 1118*9c5db199SXin Li self._IMAGE_STORAGE_SERVER, 'test_serial_number', 'test_id') 1119*9c5db199SXin Li cached_gsuri = utils.DEFAULT_OFFLOAD_GSURI 1120*9c5db199SXin Li utils.DEFAULT_OFFLOAD_GSURI = None 1121*9c5db199SXin Li gsuri = utils.get_offload_gsuri() 1122*9c5db199SXin Li utils.DEFAULT_OFFLOAD_GSURI = cached_gsuri 1123*9c5db199SXin Li self.assertEqual(expected_gsuri, gsuri) 1124*9c5db199SXin Li 1125*9c5db199SXin Li self.god.check_playback() 1126*9c5db199SXin Li 1127*9c5db199SXin Li def test_get_moblab_offload_gsuri(self): 1128*9c5db199SXin Li """Test default lab offload gsuri .""" 1129*9c5db199SXin Li self.god.mock_up(utils.CONFIG, 'CONFIG') 1130*9c5db199SXin Li self.god.stub_function_to_return(utils, 'is_moblab', True) 1131*9c5db199SXin Li self.god.stub_function_to_return(utils, 1132*9c5db199SXin Li 'get_moblab_serial_number', 'test_serial_number') 1133*9c5db199SXin Li self.god.stub_function_to_return(utils, 'get_moblab_id', 'test_id') 1134*9c5db199SXin Li gsuri = '%s%s/%s/' % ( 1135*9c5db199SXin Li utils.DEFAULT_OFFLOAD_GSURI, 'test_serial_number', 'test_id') 1136*9c5db199SXin Li self.assertEqual(gsuri, utils.get_offload_gsuri()) 1137*9c5db199SXin Li 1138*9c5db199SXin Li self.god.check_playback() 1139*9c5db199SXin Li 1140*9c5db199SXin Li 1141*9c5db199SXin Li 1142*9c5db199SXin Liclass MockMetricsTest(unittest.TestCase): 1143*9c5db199SXin Li """Test metrics mock class can handle various metrics calls.""" 1144*9c5db199SXin Li 1145*9c5db199SXin Li def test_Counter(self): 1146*9c5db199SXin Li """Test the mock class can create an instance and call any method. 1147*9c5db199SXin Li """ 1148*9c5db199SXin Li c = metrics.Counter('counter') 1149*9c5db199SXin Li c.increment(fields={'key': 1}) 1150*9c5db199SXin Li 1151*9c5db199SXin Li 1152*9c5db199SXin Li def test_Context(self): 1153*9c5db199SXin Li """Test the mock class can handle context class. 1154*9c5db199SXin Li """ 1155*9c5db199SXin Li test_value = None 1156*9c5db199SXin Li with metrics.SecondsTimer('context') as t: 1157*9c5db199SXin Li test_value = 'called_in_context' 1158*9c5db199SXin Li t['random_key'] = 'pass' 1159*9c5db199SXin Li self.assertEqual('called_in_context', test_value) 1160*9c5db199SXin Li 1161*9c5db199SXin Li 1162*9c5db199SXin Li def test_decorator(self): 1163*9c5db199SXin Li """Test the mock class can handle decorator. 1164*9c5db199SXin Li """ 1165*9c5db199SXin Li class TestClass(object): 1166*9c5db199SXin Li 1167*9c5db199SXin Li def __init__(self): 1168*9c5db199SXin Li self.value = None 1169*9c5db199SXin Li 1170*9c5db199SXin Li test_value = TestClass() 1171*9c5db199SXin Li test_value.value = None 1172*9c5db199SXin Li @metrics.SecondsTimerDecorator('decorator') 1173*9c5db199SXin Li def test(arg): 1174*9c5db199SXin Li arg.value = 'called_in_decorator' 1175*9c5db199SXin Li 1176*9c5db199SXin Li test(test_value) 1177*9c5db199SXin Li self.assertEqual('called_in_decorator', test_value.value) 1178*9c5db199SXin Li 1179*9c5db199SXin Li 1180*9c5db199SXin Li def test_setitem(self): 1181*9c5db199SXin Li """Test the mock class can handle set item call. 1182*9c5db199SXin Li """ 1183*9c5db199SXin Li timer = metrics.SecondsTimer('name') 1184*9c5db199SXin Li timer['random_key'] = 'pass' 1185*9c5db199SXin Li 1186*9c5db199SXin Li 1187*9c5db199SXin Liclass test_background_sample(unittest.TestCase): 1188*9c5db199SXin Li """Test that the background sample can sample as desired. 1189*9c5db199SXin Li """ 1190*9c5db199SXin Li 1191*9c5db199SXin Li def test_can_sample(self): 1192*9c5db199SXin Li """Test that a simple sample will work with no other complications. 1193*9c5db199SXin Li """ 1194*9c5db199SXin Li should_be_sampled = 'name' 1195*9c5db199SXin Li 1196*9c5db199SXin Li def sample_function(): 1197*9c5db199SXin Li """Return value of variable stored in method.""" 1198*9c5db199SXin Li return should_be_sampled 1199*9c5db199SXin Li still_sampling = True 1200*9c5db199SXin Li 1201*9c5db199SXin Li t = utils.background_sample_until_condition( 1202*9c5db199SXin Li function=sample_function, 1203*9c5db199SXin Li condition=lambda: still_sampling, 1204*9c5db199SXin Li timeout=5, 1205*9c5db199SXin Li sleep_interval=0.1) 1206*9c5db199SXin Li result = t.finish() 1207*9c5db199SXin Li self.assertIn(should_be_sampled, result) 1208*9c5db199SXin Li 1209*9c5db199SXin Li 1210*9c5db199SXin Li def test_samples_multiple_values(self): 1211*9c5db199SXin Li """Test that a sample will work and actually samples at the necessary 1212*9c5db199SXin Li intervals, such that it will pick up changes. 1213*9c5db199SXin Li """ 1214*9c5db199SXin Li should_be_sampled = 'name' 1215*9c5db199SXin Li 1216*9c5db199SXin Li def sample_function(): 1217*9c5db199SXin Li """Return value of variable stored in method.""" 1218*9c5db199SXin Li return should_be_sampled 1219*9c5db199SXin Li still_sampling = True 1220*9c5db199SXin Li 1221*9c5db199SXin Li t = utils.background_sample_until_condition( 1222*9c5db199SXin Li function=sample_function, 1223*9c5db199SXin Li condition=lambda: still_sampling, 1224*9c5db199SXin Li timeout=5, 1225*9c5db199SXin Li sleep_interval=0.1) 1226*9c5db199SXin Li # Let it sample values some with the initial value. 1227*9c5db199SXin Li time.sleep(2.5) 1228*9c5db199SXin Li # It should also sample some with the new value. 1229*9c5db199SXin Li should_be_sampled = 'noname' 1230*9c5db199SXin Li result = t.finish() 1231*9c5db199SXin Li self.assertIn('name', result) 1232*9c5db199SXin Li self.assertIn('noname', result) 1233*9c5db199SXin Li 1234*9c5db199SXin Li 1235*9c5db199SXin Liclass FakeTime(object): 1236*9c5db199SXin Li """Provides time() and sleep() for faking time module. 1237*9c5db199SXin Li """ 1238*9c5db199SXin Li 1239*9c5db199SXin Li def __init__(self, start_time): 1240*9c5db199SXin Li self._time = start_time 1241*9c5db199SXin Li 1242*9c5db199SXin Li 1243*9c5db199SXin Li def time(self): 1244*9c5db199SXin Li return self._time 1245*9c5db199SXin Li 1246*9c5db199SXin Li 1247*9c5db199SXin Li def sleep(self, interval): 1248*9c5db199SXin Li self._time += interval 1249*9c5db199SXin Li 1250*9c5db199SXin Li 1251*9c5db199SXin Liclass TimeModuleMockTestCase(unittest.TestCase): 1252*9c5db199SXin Li """Mocks up utils.time with a FakeTime. 1253*9c5db199SXin Li 1254*9c5db199SXin Li It substitudes time.time() and time.sleep() with FakeTime.time() 1255*9c5db199SXin Li and FakeTime.sleep(), respectively. 1256*9c5db199SXin Li """ 1257*9c5db199SXin Li 1258*9c5db199SXin Li def setUp(self): 1259*9c5db199SXin Li self.fake_time_begin = 10 1260*9c5db199SXin Li self.fake_time = FakeTime(self.fake_time_begin) 1261*9c5db199SXin Li self.patcher = pymock.patch( 1262*9c5db199SXin Li 'autotest_lib.client.common_lib.utils.time') 1263*9c5db199SXin Li self.time_mock = self.patcher.start() 1264*9c5db199SXin Li self.addCleanup(self.patcher.stop) 1265*9c5db199SXin Li self.time_mock.time.side_effect = self.fake_time.time 1266*9c5db199SXin Li self.time_mock.sleep.side_effect = self.fake_time.sleep 1267*9c5db199SXin Li 1268*9c5db199SXin Li 1269*9c5db199SXin Lidef always_raise(): 1270*9c5db199SXin Li """A function that raises an exception.""" 1271*9c5db199SXin Li raise Exception('always raise') 1272*9c5db199SXin Li 1273*9c5db199SXin Li 1274*9c5db199SXin Lidef fail_n_times(count): 1275*9c5db199SXin Li """Creates a function that returns False for the first count-th calls. 1276*9c5db199SXin Li 1277*9c5db199SXin Li @return a function returns False for the first count-th calls and True 1278*9c5db199SXin Li afterwards. 1279*9c5db199SXin Li """ 1280*9c5db199SXin Li counter = itertools.count(count, -1) 1281*9c5db199SXin Li return lambda: next(counter) <= 0 1282*9c5db199SXin Li 1283*9c5db199SXin Li 1284*9c5db199SXin Liclass test_poll_for_condition(TimeModuleMockTestCase): 1285*9c5db199SXin Li """Test poll_for_condition. 1286*9c5db199SXin Li """ 1287*9c5db199SXin Li 1288*9c5db199SXin Li def test_ok(self): 1289*9c5db199SXin Li """Test polling condition that returns True. 1290*9c5db199SXin Li """ 1291*9c5db199SXin Li self.assertTrue(utils.poll_for_condition(lambda: True)) 1292*9c5db199SXin Li 1293*9c5db199SXin Li 1294*9c5db199SXin Li def test_ok_evaluated_as_true(self): 1295*9c5db199SXin Li """Test polling condition which's return value is evaluated as True. 1296*9c5db199SXin Li """ 1297*9c5db199SXin Li self.assertEqual(1, utils.poll_for_condition(lambda: 1)) 1298*9c5db199SXin Li 1299*9c5db199SXin Li self.assertEqual('something', 1300*9c5db199SXin Li utils.poll_for_condition(lambda: 'something')) 1301*9c5db199SXin Li 1302*9c5db199SXin Li 1303*9c5db199SXin Li def test_fail(self): 1304*9c5db199SXin Li """Test polling condition that returns False. 1305*9c5db199SXin Li 1306*9c5db199SXin Li Expect TimeoutError exception as neither customized exception nor 1307*9c5db199SXin Li exception raised from condition(). 1308*9c5db199SXin Li """ 1309*9c5db199SXin Li with self.assertRaises(utils.TimeoutError): 1310*9c5db199SXin Li utils.poll_for_condition(lambda: False, timeout=3, sleep_interval=1) 1311*9c5db199SXin Li self.assertEqual(3, self.time_mock.sleep.call_count) 1312*9c5db199SXin Li 1313*9c5db199SXin Li 1314*9c5db199SXin Li def test_fail_evaluated_as_false(self): 1315*9c5db199SXin Li """Test polling condition which's return value is evaluated as False. 1316*9c5db199SXin Li 1317*9c5db199SXin Li Expect TimeoutError exception as neither customized exception nor 1318*9c5db199SXin Li exception raised from condition(). 1319*9c5db199SXin Li """ 1320*9c5db199SXin Li with self.assertRaises(utils.TimeoutError): 1321*9c5db199SXin Li utils.poll_for_condition(lambda: 0, timeout=3, sleep_interval=1) 1322*9c5db199SXin Li self.assertEqual(3, self.time_mock.sleep.call_count) 1323*9c5db199SXin Li 1324*9c5db199SXin Li with self.assertRaises(utils.TimeoutError): 1325*9c5db199SXin Li utils.poll_for_condition(lambda: None, timeout=3, sleep_interval=1) 1326*9c5db199SXin Li 1327*9c5db199SXin Li 1328*9c5db199SXin Li def test_exception_arg(self): 1329*9c5db199SXin Li """Test polling condition always fails. 1330*9c5db199SXin Li 1331*9c5db199SXin Li Expect exception raised by 'exception' args. 1332*9c5db199SXin Li """ 1333*9c5db199SXin Li with self.assertRaisesRegexp(Exception, 'from args'): 1334*9c5db199SXin Li utils.poll_for_condition(lambda: False, 1335*9c5db199SXin Li exception=Exception('from args'), 1336*9c5db199SXin Li timeout=3, sleep_interval=1) 1337*9c5db199SXin Li self.assertEqual(3, self.time_mock.sleep.call_count) 1338*9c5db199SXin Li 1339*9c5db199SXin Li 1340*9c5db199SXin Li def test_exception_from_condition(self): 1341*9c5db199SXin Li """Test polling condition always fails. 1342*9c5db199SXin Li 1343*9c5db199SXin Li Expect exception raised by condition(). 1344*9c5db199SXin Li """ 1345*9c5db199SXin Li with self.assertRaisesRegexp(Exception, 'always raise'): 1346*9c5db199SXin Li utils.poll_for_condition(always_raise, 1347*9c5db199SXin Li exception=Exception('from args'), 1348*9c5db199SXin Li timeout=3, sleep_interval=1) 1349*9c5db199SXin Li # For poll_for_condition, if condition() raises exception, it raises 1350*9c5db199SXin Li # immidiately without retry. So sleep() should not be called. 1351*9c5db199SXin Li self.time_mock.sleep.assert_not_called() 1352*9c5db199SXin Li 1353*9c5db199SXin Li 1354*9c5db199SXin Li def test_ok_after_retry(self): 1355*9c5db199SXin Li """Test polling a condition which is success after retry twice. 1356*9c5db199SXin Li """ 1357*9c5db199SXin Li self.assertTrue(utils.poll_for_condition(fail_n_times(2), timeout=3, 1358*9c5db199SXin Li sleep_interval=1)) 1359*9c5db199SXin Li 1360*9c5db199SXin Li 1361*9c5db199SXin Li def test_cannot_wait(self): 1362*9c5db199SXin Li """Test polling a condition which fails till timeout. 1363*9c5db199SXin Li """ 1364*9c5db199SXin Li with self.assertRaisesRegexp( 1365*9c5db199SXin Li utils.TimeoutError, 1366*9c5db199SXin Li 'Timed out waiting for unnamed condition'): 1367*9c5db199SXin Li utils.poll_for_condition(fail_n_times(4), timeout=3, 1368*9c5db199SXin Li sleep_interval=1) 1369*9c5db199SXin Li self.assertEqual(3, self.time_mock.sleep.call_count) 1370*9c5db199SXin Li 1371*9c5db199SXin Li 1372*9c5db199SXin Liclass test_poll_for_condition_ex(TimeModuleMockTestCase): 1373*9c5db199SXin Li """Test poll_for_condition_ex. 1374*9c5db199SXin Li """ 1375*9c5db199SXin Li 1376*9c5db199SXin Li def test_ok(self): 1377*9c5db199SXin Li """Test polling condition that returns True. 1378*9c5db199SXin Li """ 1379*9c5db199SXin Li self.assertTrue(utils.poll_for_condition_ex(lambda: True)) 1380*9c5db199SXin Li 1381*9c5db199SXin Li 1382*9c5db199SXin Li def test_ok_evaluated_as_true(self): 1383*9c5db199SXin Li """Test polling condition which's return value is evaluated as True. 1384*9c5db199SXin Li """ 1385*9c5db199SXin Li self.assertEqual(1, utils.poll_for_condition_ex(lambda: 1)) 1386*9c5db199SXin Li 1387*9c5db199SXin Li self.assertEqual('something', 1388*9c5db199SXin Li utils.poll_for_condition_ex(lambda: 'something')) 1389*9c5db199SXin Li 1390*9c5db199SXin Li 1391*9c5db199SXin Li def test_fail(self): 1392*9c5db199SXin Li """Test polling condition that returns False. 1393*9c5db199SXin Li 1394*9c5db199SXin Li Expect TimeoutError raised. 1395*9c5db199SXin Li """ 1396*9c5db199SXin Li with self.assertRaisesRegexp( 1397*9c5db199SXin Li utils.TimeoutError, 1398*9c5db199SXin Li 'Timed out waiting for unamed condition'): 1399*9c5db199SXin Li utils.poll_for_condition_ex(lambda: False, timeout=3, 1400*9c5db199SXin Li sleep_interval=1) 1401*9c5db199SXin Li self.assertEqual(2, self.time_mock.sleep.call_count) 1402*9c5db199SXin Li 1403*9c5db199SXin Li 1404*9c5db199SXin Li def test_fail_evaluated_as_false(self): 1405*9c5db199SXin Li """Test polling condition which's return value is evaluated as False. 1406*9c5db199SXin Li 1407*9c5db199SXin Li Expect TimeoutError raised. 1408*9c5db199SXin Li """ 1409*9c5db199SXin Li with self.assertRaisesRegexp( 1410*9c5db199SXin Li utils.TimeoutError, 1411*9c5db199SXin Li 'Timed out waiting for unamed condition'): 1412*9c5db199SXin Li utils.poll_for_condition_ex(lambda: 0, timeout=3, 1413*9c5db199SXin Li sleep_interval=1) 1414*9c5db199SXin Li self.assertEqual(2, self.time_mock.sleep.call_count) 1415*9c5db199SXin Li 1416*9c5db199SXin Li with self.assertRaisesRegexp( 1417*9c5db199SXin Li utils.TimeoutError, 1418*9c5db199SXin Li 'Timed out waiting for unamed condition'): 1419*9c5db199SXin Li utils.poll_for_condition_ex(lambda: None, timeout=3, 1420*9c5db199SXin Li sleep_interval=1) 1421*9c5db199SXin Li 1422*9c5db199SXin Li 1423*9c5db199SXin Li def test_desc_arg(self): 1424*9c5db199SXin Li """Test polling condition always fails with desc. 1425*9c5db199SXin Li 1426*9c5db199SXin Li Expect TimeoutError with condition description embedded. 1427*9c5db199SXin Li """ 1428*9c5db199SXin Li with self.assertRaisesRegexp( 1429*9c5db199SXin Li utils.TimeoutError, 1430*9c5db199SXin Li 'Timed out waiting for always false condition'): 1431*9c5db199SXin Li utils.poll_for_condition_ex(lambda: False, 1432*9c5db199SXin Li desc='always false condition', 1433*9c5db199SXin Li timeout=3, sleep_interval=1) 1434*9c5db199SXin Li self.assertEqual(2, self.time_mock.sleep.call_count) 1435*9c5db199SXin Li 1436*9c5db199SXin Li 1437*9c5db199SXin Li def test_exception(self): 1438*9c5db199SXin Li """Test polling condition that raises. 1439*9c5db199SXin Li 1440*9c5db199SXin Li Expect TimeoutError with condition raised exception embedded. 1441*9c5db199SXin Li """ 1442*9c5db199SXin Li with self.assertRaisesRegexp( 1443*9c5db199SXin Li utils.TimeoutError, 1444*9c5db199SXin Li "Reason: Exception\('always raise',\)"): 1445*9c5db199SXin Li utils.poll_for_condition_ex(always_raise, timeout=3, 1446*9c5db199SXin Li sleep_interval=1) 1447*9c5db199SXin Li self.assertEqual(2, self.time_mock.sleep.call_count) 1448*9c5db199SXin Li 1449*9c5db199SXin Li 1450*9c5db199SXin Li def test_ok_after_retry(self): 1451*9c5db199SXin Li """Test polling a condition which is success after retry twice. 1452*9c5db199SXin Li """ 1453*9c5db199SXin Li self.assertTrue(utils.poll_for_condition_ex(fail_n_times(2), timeout=3, 1454*9c5db199SXin Li sleep_interval=1)) 1455*9c5db199SXin Li 1456*9c5db199SXin Li 1457*9c5db199SXin Li def test_cannot_wait(self): 1458*9c5db199SXin Li """Test polling a condition which fails till timeout. 1459*9c5db199SXin Li """ 1460*9c5db199SXin Li with self.assertRaisesRegexp( 1461*9c5db199SXin Li utils.TimeoutError, 1462*9c5db199SXin Li 'condition evaluted as false'): 1463*9c5db199SXin Li utils.poll_for_condition_ex(fail_n_times(3), timeout=3, 1464*9c5db199SXin Li sleep_interval=1) 1465*9c5db199SXin Li self.assertEqual(2, self.time_mock.sleep.call_count) 1466*9c5db199SXin Li 1467*9c5db199SXin Li 1468*9c5db199SXin Liclass test_timer(TimeModuleMockTestCase): 1469*9c5db199SXin Li """Test Timer. 1470*9c5db199SXin Li """ 1471*9c5db199SXin Li 1472*9c5db199SXin Li def test_zero_timeout(self): 1473*9c5db199SXin Li """Test Timer with zero timeout. 1474*9c5db199SXin Li 1475*9c5db199SXin Li Only the first timer.sleep(0) is True. 1476*9c5db199SXin Li """ 1477*9c5db199SXin Li timer = utils.Timer(0) 1478*9c5db199SXin Li self.assertTrue(timer.sleep(0)) 1479*9c5db199SXin Li self.assertFalse(timer.sleep(0)) 1480*9c5db199SXin Li self.time_mock.sleep.assert_not_called() 1481*9c5db199SXin Li 1482*9c5db199SXin Li 1483*9c5db199SXin Li def test_sleep(self): 1484*9c5db199SXin Li """Test Timer.sleep() 1485*9c5db199SXin Li """ 1486*9c5db199SXin Li timeout = 3 1487*9c5db199SXin Li sleep_interval = 2 1488*9c5db199SXin Li timer = utils.Timer(timeout) 1489*9c5db199SXin Li 1490*9c5db199SXin Li # Kicks off timer. 1491*9c5db199SXin Li self.assertTrue(timer.sleep(sleep_interval)) 1492*9c5db199SXin Li self.assertEqual(self.fake_time_begin + timeout, timer.deadline) 1493*9c5db199SXin Li self.assertTrue(timer.sleep(sleep_interval)) 1494*9c5db199SXin Li # now: 12. 12 + 2 > 13, unable to sleep 1495*9c5db199SXin Li self.assertFalse(timer.sleep(sleep_interval)) 1496*9c5db199SXin Li 1497*9c5db199SXin Li self.time_mock.sleep.assert_has_calls([pymock.call(sleep_interval)]) 1498*9c5db199SXin Li 1499*9c5db199SXin Li 1500*9c5db199SXin Liclass test_timeout_error(unittest.TestCase): 1501*9c5db199SXin Li """Test TimeoutError. 1502*9c5db199SXin Li 1503*9c5db199SXin Li Test TimeoutError with three invocations format. 1504*9c5db199SXin Li """ 1505*9c5db199SXin Li 1506*9c5db199SXin Li def test_no_args(self): 1507*9c5db199SXin Li """Create TimeoutError without arguments. 1508*9c5db199SXin Li """ 1509*9c5db199SXin Li e = utils.TimeoutError() 1510*9c5db199SXin Li self.assertEqual('', str(e)) 1511*9c5db199SXin Li self.assertEqual('TimeoutError()', repr(e)) 1512*9c5db199SXin Li 1513*9c5db199SXin Li 1514*9c5db199SXin Li def test_with_message(self): 1515*9c5db199SXin Li """Create TimeoutError with text message. 1516*9c5db199SXin Li """ 1517*9c5db199SXin Li e = utils.TimeoutError(message='Waiting for condition') 1518*9c5db199SXin Li self.assertEqual('Waiting for condition', str(e)) 1519*9c5db199SXin Li self.assertEqual("TimeoutError('Waiting for condition',)", repr(e)) 1520*9c5db199SXin Li 1521*9c5db199SXin Li # Positional message argument for backward compatibility. 1522*9c5db199SXin Li e = utils.TimeoutError('Waiting for condition') 1523*9c5db199SXin Li self.assertEqual('Waiting for condition', str(e)) 1524*9c5db199SXin Li self.assertEqual("TimeoutError('Waiting for condition',)", repr(e)) 1525*9c5db199SXin Li 1526*9c5db199SXin Li 1527*9c5db199SXin Li 1528*9c5db199SXin Li def test_with_reason(self): 1529*9c5db199SXin Li """Create TimeoutError with reason only. 1530*9c5db199SXin Li """ 1531*9c5db199SXin Li e = utils.TimeoutError(reason='illegal input') 1532*9c5db199SXin Li self.assertEqual("Reason: 'illegal input'", str(e)) 1533*9c5db199SXin Li self.assertEqual("TimeoutError(\"Reason: 'illegal input'\",)", repr(e)) 1534*9c5db199SXin Li self.assertEqual('illegal input', e.reason) 1535*9c5db199SXin Li 1536*9c5db199SXin Li 1537*9c5db199SXin Li def test_with_message_reason(self): 1538*9c5db199SXin Li """Create TimeoutError with text message and reason. 1539*9c5db199SXin Li """ 1540*9c5db199SXin Li e = utils.TimeoutError(message='Waiting for condition', 1541*9c5db199SXin Li reason='illegal input') 1542*9c5db199SXin Li self.assertEqual("Waiting for condition. Reason: 'illegal input'", 1543*9c5db199SXin Li str(e)) 1544*9c5db199SXin Li self.assertEqual('illegal input', e.reason) 1545*9c5db199SXin Li 1546*9c5db199SXin Li # Positional message argument for backward compatibility. 1547*9c5db199SXin Li e = utils.TimeoutError('Waiting for condition', reason='illegal input') 1548*9c5db199SXin Li self.assertEqual("Waiting for condition. Reason: 'illegal input'", 1549*9c5db199SXin Li str(e)) 1550*9c5db199SXin Li self.assertEqual('illegal input', e.reason) 1551*9c5db199SXin Li 1552*9c5db199SXin Li 1553*9c5db199SXin Li def test_with_message_reason_object(self): 1554*9c5db199SXin Li """Create TimeoutError with text message and reason as exception object. 1555*9c5db199SXin Li """ 1556*9c5db199SXin Li e = utils.TimeoutError(message='Waiting for condition', 1557*9c5db199SXin Li reason=Exception('illegal input')) 1558*9c5db199SXin Li self.assertEqual( 1559*9c5db199SXin Li "Waiting for condition. Reason: Exception('illegal input',)", 1560*9c5db199SXin Li str(e)) 1561*9c5db199SXin Li self.assertIsInstance(e.reason, Exception) 1562*9c5db199SXin Li self.assertEqual('illegal input', str(e.reason)) 1563*9c5db199SXin Li 1564*9c5db199SXin Li # Positional message argument for backward compatibility. 1565*9c5db199SXin Li e = utils.TimeoutError('Waiting for condition', 1566*9c5db199SXin Li reason=Exception('illegal input')) 1567*9c5db199SXin Li self.assertEqual( 1568*9c5db199SXin Li "Waiting for condition. Reason: Exception('illegal input',)", 1569*9c5db199SXin Li str(e)) 1570*9c5db199SXin Li self.assertIsInstance(e.reason, Exception) 1571*9c5db199SXin Li self.assertEqual('illegal input', str(e.reason)) 1572*9c5db199SXin Li 1573*9c5db199SXin Li 1574*9c5db199SXin Li 1575*9c5db199SXin Liif __name__ == "__main__": 1576*9c5db199SXin Li unittest.main() 1577