16fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone#!/usr/bin/python 26fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone# 3ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 46fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone# Use of this source code is governed by a BSD-style license that can be 56fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone# found in the LICENSE file. 66fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone 7b493555db2d43e79d96e793cae9d1ffb822dd6c1Chris Masone"""Unit tests for server/cros/dynamic_suite/dynamic_suite.py.""" 86fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone 96fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masoneimport mox 107a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Millerimport os 117a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Millerimport signal 1236cfd831af781eed114337efa5b90c103a49b502Dan Shiimport unittest 136fed646ae4c833b537ea24b6161b81e0f50c0e32Chris Masone 1444e4d6ce5a7c38451c25d35b307b35338606091fChris Masonefrom autotest_lib.client.common_lib import base_job, error 1524b3a027291ff030bb74482818106fa91bcc911dChris Sosafrom autotest_lib.client.common_lib.cros import dev_server 1636cfd831af781eed114337efa5b90c103a49b502Dan Shifrom autotest_lib.server.cros import provision 17b493555db2d43e79d96e793cae9d1ffb822dd6c1Chris Masonefrom autotest_lib.server.cros.dynamic_suite import dynamic_suite 1836cfd831af781eed114337efa5b90c103a49b502Dan Shifrom autotest_lib.server.cros.dynamic_suite.suite import Suite 19f63576d7e89fd933475c1dc123c60aa9c2cee1c0Chris Masone 20f63576d7e89fd933475c1dc123c60aa9c2cee1c0Chris Masone 21ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masoneclass DynamicSuiteTest(mox.MoxTestBase): 22ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Unit tests for dynamic_suite module methods. 23ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 24ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone @var _DARGS: default args to vet. 25ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """ 26ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 27accb5ceaac066025592808247bfa9c97966bba97Chris Sosa _DEVSERVER_HOST = 'http://devserver1' 280723bf5ed7ff506e15fea180547cb6a8ae9102ebDan Shi _BUILDS = {provision.CROS_VERSION_PREFIX: 'build_1', 290723bf5ed7ff506e15fea180547cb6a8ae9102ebDan Shi provision.FW_RW_VERSION_PREFIX:'fwrw_build_1'} 30ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 31ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def setUp(self): 32accb5ceaac066025592808247bfa9c97966bba97Chris Sosa 33ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone super(DynamicSuiteTest, self).setUp() 34ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone self._DARGS = {'name': 'name', 3536cfd831af781eed114337efa5b90c103a49b502Dan Shi 'builds': self._BUILDS, 36ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 'board': 'board', 37ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 'job': self.mox.CreateMock(base_job.base_job), 38ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 'num': 1, 39ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 'pool': 'pool', 4062579122694934d942a4844a615bc034bc2e8aa1Chris Masone 'check_hosts': False, 4141048e3859e1ca5c0fb0d84da1aab3b3079de27bAviv Keshet 'add_experimental': False, 425965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi 'suite_dependencies': ['test_dep'], 435965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi 'devserver_url': self._DEVSERVER_HOST} 44ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 45ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 46accb5ceaac066025592808247bfa9c97966bba97Chris Sosa 47ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testVetRequiredReimageAndRunArgs(self): 48ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should verify only that required args are present and correct.""" 496dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone spec = dynamic_suite.SuiteSpec(**self._DARGS) 5036cfd831af781eed114337efa5b90c103a49b502Dan Shi self.assertEquals(spec.builds, self._DARGS['builds']) 516dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.board, 'board:' + self._DARGS['board']) 526dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.name, self._DARGS['name']) 536dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.job, self._DARGS['job']) 54ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 55ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 56ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testVetReimageAndRunBuildArgFail(self): 5736cfd831af781eed114337efa5b90c103a49b502Dan Shi """Should fail verification if both |builds| and |build| are not set. 5836cfd831af781eed114337efa5b90c103a49b502Dan Shi """ 59ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone self._DARGS['build'] = None 6036cfd831af781eed114337efa5b90c103a49b502Dan Shi self._DARGS['builds'] = None 6136cfd831af781eed114337efa5b90c103a49b502Dan Shi self.assertRaises(error.SuiteArgumentException, 6236cfd831af781eed114337efa5b90c103a49b502Dan Shi dynamic_suite.SuiteSpec, 6336cfd831af781eed114337efa5b90c103a49b502Dan Shi **self._DARGS) 6436cfd831af781eed114337efa5b90c103a49b502Dan Shi self._DARGS['build'] = 'build1' 6536cfd831af781eed114337efa5b90c103a49b502Dan Shi self._DARGS['builds'] = {'cros-version': 'build2', 6636cfd831af781eed114337efa5b90c103a49b502Dan Shi 'firmware-version': 'build3'} 67f8b5306840870a8ebec3a5dc4b77c0bd79a69c5bChris Masone self.assertRaises(error.SuiteArgumentException, 686dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone dynamic_suite.SuiteSpec, 69ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone **self._DARGS) 70ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 71ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 72ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testVetReimageAndRunBoardArgFail(self): 73ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should fail verification because |board| arg is bad.""" 74ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone self._DARGS['board'] = None 75f8b5306840870a8ebec3a5dc4b77c0bd79a69c5bChris Masone self.assertRaises(error.SuiteArgumentException, 766dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone dynamic_suite.SuiteSpec, 77ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone **self._DARGS) 78ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 79ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 80ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testVetReimageAndRunNameArgFail(self): 81ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should fail verification because |name| arg is bad.""" 82ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone self._DARGS['name'] = None 83f8b5306840870a8ebec3a5dc4b77c0bd79a69c5bChris Masone self.assertRaises(error.SuiteArgumentException, 846dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone dynamic_suite.SuiteSpec, 85ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone **self._DARGS) 86ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 87ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 88ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testVetReimageAndRunJobArgFail(self): 89ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should fail verification because |job| arg is bad.""" 90ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone self._DARGS['job'] = None 91f8b5306840870a8ebec3a5dc4b77c0bd79a69c5bChris Masone self.assertRaises(error.SuiteArgumentException, 926dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone dynamic_suite.SuiteSpec, 93ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone **self._DARGS) 94ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 95ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 96ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testOverrideOptionalReimageAndRunArgs(self): 97ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should verify that optional args can be overridden.""" 986dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone spec = dynamic_suite.SuiteSpec(**self._DARGS) 996dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.pool, 'pool:' + self._DARGS['pool']) 1006dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.num, self._DARGS['num']) 1016dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.check_hosts, self._DARGS['check_hosts']) 1026dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.add_experimental, 1036dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self._DARGS['add_experimental']) 10441048e3859e1ca5c0fb0d84da1aab3b3079de27bAviv Keshet self.assertEquals(spec.suite_dependencies, 10541048e3859e1ca5c0fb0d84da1aab3b3079de27bAviv Keshet self._DARGS['suite_dependencies']) 106ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 107ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 108ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone def testDefaultOptionalReimageAndRunArgs(self): 109ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone """Should verify that optional args get defaults.""" 110ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone del(self._DARGS['pool']) 11162579122694934d942a4844a615bc034bc2e8aa1Chris Masone del(self._DARGS['check_hosts']) 112ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone del(self._DARGS['add_experimental']) 113ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone del(self._DARGS['num']) 11441048e3859e1ca5c0fb0d84da1aab3b3079de27bAviv Keshet del(self._DARGS['suite_dependencies']) 1156dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone 1166dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone spec = dynamic_suite.SuiteSpec(**self._DARGS) 1176dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.pool, None) 1186dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.num, None) 1196dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.check_hosts, True) 1206dff243bdcb9d52b0d07e92c33f42cfa40263945Chris Masone self.assertEquals(spec.add_experimental, True) 12147a0367b883f3429efac994047f2c921a983fd96Alex Miller self.assertEquals(spec.suite_dependencies, []) 122ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 123ab3e7331e3f45521fef3ef2b736a82f9d5aad854Chris Masone 1247a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller def testReimageAndSIGTERM(self): 1257a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller """Should reimage_and_run that causes a SIGTERM and fails cleanly.""" 1269a1987acc36506ceba0397ce64aeca1b39eb5b39Alex Miller def suicide(*_): 1275965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi """Send SIGTERM to current process to exit. 1285965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi 1295965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi @param _: Ignored. 1305965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi """ 1317a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller os.kill(os.getpid(), signal.SIGTERM) 1327a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller 1338dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller # Mox doesn't play well with SIGTERM, but it does play well with 1348dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller # with exceptions, so here we're using an exception to simulate 1358dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller # execution being interrupted by a signal. 1367a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller class UnhandledSIGTERM(Exception): 1375965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi """Exception to be raised when SIGTERM is received.""" 1387a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller pass 1397a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller 1408dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller def handler(signal_number, frame): 1415965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi """Handler for receiving a signal. 1425965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi 1435965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi @param signal_number: signal number. 1445965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi @param frame: stack frame object. 1455965c09acfcba7253f9bd4a3851f3b7fec429e2eDan Shi """ 1468dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller raise UnhandledSIGTERM() 1478dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller 1488dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller signal.signal(signal.SIGTERM, handler) 149accb5ceaac066025592808247bfa9c97966bba97Chris Sosa spec = self.mox.CreateMock(dynamic_suite.SuiteSpec) 15036cfd831af781eed114337efa5b90c103a49b502Dan Shi spec.builds = self._BUILDS 15136cfd831af781eed114337efa5b90c103a49b502Dan Shi spec.test_source_build = Suite.get_test_source_build(self._BUILDS) 152accb5ceaac066025592808247bfa9c97966bba97Chris Sosa spec.devserver = self.mox.CreateMock(dev_server.ImageServer) 1539a1987acc36506ceba0397ce64aeca1b39eb5b39Alex Miller spec.devserver.stage_artifacts( 15436cfd831af781eed114337efa5b90c103a49b502Dan Shi spec.builds[provision.CROS_VERSION_PREFIX], 15536cfd831af781eed114337efa5b90c103a49b502Dan Shi ['control_files', 'test_suites']).WithSideEffects(suicide) 1565ace6f2e17f808efbee863a7d7dbe1bc52527a19Simran Basi spec.run_prod_code = False 1578dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller 1587a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller self.mox.ReplayAll() 1597a2160a31f5ca4ce41faac94aeb3c3ffc389021eAlex Miller 1608dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller self.assertRaises(UnhandledSIGTERM, 1618dca4641f3b98181843b752e2b51b99c52541a0aAlex Miller dynamic_suite._perform_reimage_and_run, 1623a69adcf4b2c35fb9775c8de8091dc8d30196512Alex Miller spec, None, None, None) 16336cfd831af781eed114337efa5b90c103a49b502Dan Shi 16436cfd831af781eed114337efa5b90c103a49b502Dan Shi 16536cfd831af781eed114337efa5b90c103a49b502Dan Shiif __name__ == '__main__': 16636cfd831af781eed114337efa5b90c103a49b502Dan Shi unittest.main() 167