blob: 63e731b06b840252a579e00c20b6ee6432ea23d6 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit tests for server/cros/dynamic_suite/dynamic_suite.py."""
import logging
import mox
import os
import signal
import unittest
from autotest_lib.client.common_lib import base_job, error
from autotest_lib.client.common_lib.cros import dev_server
from autotest_lib.server.cros.dynamic_suite import dynamic_suite
from autotest_lib.server.cros.dynamic_suite import host_lock_manager
class DynamicSuiteTest(mox.MoxTestBase):
"""Unit tests for dynamic_suite module methods.
@var _DARGS: default args to vet.
"""
_DEVSERVER_HOST = 'http://devserver1'
_BUILD = 'build'
def setUp(self):
super(DynamicSuiteTest, self).setUp()
self._DARGS = {'name': 'name',
'build': self._BUILD,
'board': 'board',
'job': self.mox.CreateMock(base_job.base_job),
'num': 1,
'pool': 'pool',
'skip_reimage': True,
'check_hosts': False,
'add_experimental': False}
def testVetRequiredReimageAndRunArgs(self):
"""Should verify only that required args are present and correct."""
self._MockDevserverResolve()
self.mox.ReplayAll()
spec = dynamic_suite.SuiteSpec(**self._DARGS)
self.assertEquals(spec.build, self._DARGS['build'])
self.assertEquals(spec.board, 'board:' + self._DARGS['board'])
self.assertEquals(spec.name, self._DARGS['name'])
self.assertEquals(spec.job, self._DARGS['job'])
self.assertEquals(spec.devserver.url(), self._DEVSERVER_HOST)
def testVetReimageAndRunBuildArgFail(self):
"""Should fail verification because |build| arg is bad."""
self._DARGS['build'] = None
self.assertRaises(error.SuiteArgumentException,
dynamic_suite.SuiteSpec,
**self._DARGS)
def testVetReimageAndRunBoardArgFail(self):
"""Should fail verification because |board| arg is bad."""
self._DARGS['board'] = None
self.assertRaises(error.SuiteArgumentException,
dynamic_suite.SuiteSpec,
**self._DARGS)
def testVetReimageAndRunNameArgFail(self):
"""Should fail verification because |name| arg is bad."""
self._DARGS['name'] = None
self.assertRaises(error.SuiteArgumentException,
dynamic_suite.SuiteSpec,
**self._DARGS)
def testVetReimageAndRunJobArgFail(self):
"""Should fail verification because |job| arg is bad."""
self._DARGS['job'] = None
self.assertRaises(error.SuiteArgumentException,
dynamic_suite.SuiteSpec,
**self._DARGS)
def _MockDevserverResolve(self):
"""
Helper method used with spec creation as the devserver host will need
to be resolved.
"""
self.mox.StubOutWithMock(dev_server.ImageServer, 'resolve')
dev_server.ImageServer.resolve(self._BUILD).AndReturn(
dev_server.ImageServer(self._DEVSERVER_HOST))
def testOverrideOptionalReimageAndRunArgs(self):
"""Should verify that optional args can be overridden."""
self._MockDevserverResolve()
self.mox.ReplayAll()
spec = dynamic_suite.SuiteSpec(**self._DARGS)
self.assertEquals(spec.pool, 'pool:' + self._DARGS['pool'])
self.assertEquals(spec.num, self._DARGS['num'])
self.assertEquals(spec.check_hosts, self._DARGS['check_hosts'])
self.assertEquals(spec.skip_reimage, self._DARGS['skip_reimage'])
self.assertEquals(spec.add_experimental,
self._DARGS['add_experimental'])
self.assertEquals(spec.devserver.url(), self._DEVSERVER_HOST)
def testDefaultOptionalReimageAndRunArgs(self):
"""Should verify that optional args get defaults."""
del(self._DARGS['pool'])
del(self._DARGS['skip_reimage'])
del(self._DARGS['check_hosts'])
del(self._DARGS['add_experimental'])
del(self._DARGS['num'])
self._MockDevserverResolve()
self.mox.ReplayAll()
spec = dynamic_suite.SuiteSpec(**self._DARGS)
self.assertEquals(spec.pool, None)
self.assertEquals(spec.num, None)
self.assertEquals(spec.check_hosts, True)
self.assertEquals(spec.skip_reimage, False)
self.assertEquals(spec.add_experimental, True)
self.assertEquals(spec.devserver.url(), self._DEVSERVER_HOST)
def testReimageWithBadDependencies(self):
"""Should raise if the build has bad dependency info."""
ds = self.mox.CreateMock(dev_server.ImageServer)
ds.get_dependencies_file(self._DARGS['build']).AndReturn('busted')
self.mox.StubOutWithMock(dev_server.ImageServer, 'resolve')
dev_server.ImageServer.resolve(self._BUILD).AndReturn(ds)
self.mox.ReplayAll()
self.assertRaises(error.MalformedDependenciesException,
dynamic_suite.reimage_and_run, **self._DARGS)
def testReimageAndSIGTERM(self):
"""Should reimage_and_run that causes a SIGTERM and fails cleanly."""
def suicide(_dontcare):
os.kill(os.getpid(), signal.SIGTERM)
# Mox doesn't play well with SIGTERM, but it does play well with
# with exceptions, so here we're using an exception to simulate
# execution being interrupted by a signal.
class UnhandledSIGTERM(Exception):
pass
def handler(signal_number, frame):
raise UnhandledSIGTERM()
signal.signal(signal.SIGTERM, handler)
spec = self.mox.CreateMock(dynamic_suite.SuiteSpec)
spec.skip_reimage = True
spec.build = ''
spec.devserver = self.mox.CreateMock(dev_server.ImageServer)
spec.devserver.finish_download(spec.build).WithSideEffects(suicide)
manager = self.mox.CreateMock(host_lock_manager.HostLockManager)
# This unlock occurrs in the signal handler, autoserv would be
# terminated at this point
manager.unlock()
# However, since we're throwing an exception, we "gracefully" exit the
# context manager, so this unlock comes from the |__exit__| call.
manager.unlock()
self.mox.ReplayAll()
self.assertRaises(UnhandledSIGTERM,
dynamic_suite._perform_reimage_and_run,
spec, None, None, None, manager)