mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
143 lines
4.4 KiB
Python
143 lines
4.4 KiB
Python
# Copyright 2015 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""Adds unittest-esque functionality to Legion."""
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
import unittest
|
|
|
|
#pylint: disable=relative-import
|
|
import common_lib
|
|
import task_controller
|
|
import task_registration_server
|
|
|
|
BANNER_WIDTH = 80
|
|
|
|
|
|
class TestCase(unittest.TestCase):
|
|
"""Test case class with added Legion support."""
|
|
|
|
_registration_server = None
|
|
_initialized = False
|
|
|
|
@classmethod
|
|
def __new__(cls, *args, **kwargs):
|
|
"""Initialize the class and return a new instance."""
|
|
cls._InitializeClass()
|
|
return super(TestCase, cls).__new__(*args, **kwargs)
|
|
|
|
def __init__(self, test_name='runTest'):
|
|
super(TestCase, self).__init__(test_name)
|
|
method = getattr(self, test_name, None)
|
|
if method:
|
|
# Install the _RunTest method
|
|
self._TestMethod = method
|
|
setattr(self, test_name, self._RunTest)
|
|
self._output_dir = None
|
|
|
|
@property
|
|
def output_dir(self):
|
|
if not self._output_dir:
|
|
self._output_dir = self.rpc.GetOutputDir()
|
|
return self._output_dir
|
|
|
|
def _RunTest(self):
|
|
"""Runs the test method and provides banner info and error reporting."""
|
|
self._LogInfoBanner(self._testMethodName, self.shortDescription())
|
|
try:
|
|
return self._TestMethod()
|
|
except:
|
|
exc_info = sys.exc_info()
|
|
logging.error('', exc_info=exc_info)
|
|
raise exc_info[0], exc_info[1], exc_info[2]
|
|
|
|
@classmethod
|
|
def _InitializeClass(cls):
|
|
"""Handles class level initialization.
|
|
|
|
There are 2 types of setup/teardown methods that always need to be run:
|
|
1) Framework level setup/teardown
|
|
2) Test case level setup/teardown
|
|
|
|
This method installs handlers in place of setUpClass and tearDownClass that
|
|
will ensure both types of setup/teardown methods are called correctly.
|
|
"""
|
|
if cls._initialized:
|
|
return
|
|
cls._OriginalSetUpClassMethod = cls.setUpClass
|
|
cls.setUpClass = cls._HandleSetUpClass
|
|
cls._OriginalTearDownClassMethod = cls.tearDownClass
|
|
cls.tearDownClass = cls._HandleTearDownClass
|
|
cls._initialized = True
|
|
|
|
@classmethod
|
|
def _LogInfoBanner(cls, method_name, method_doc=None):
|
|
"""Formats and logs test case information."""
|
|
logging.info('*' * BANNER_WIDTH)
|
|
logging.info(method_name.center(BANNER_WIDTH))
|
|
if method_doc:
|
|
for line in method_doc.split('\n'):
|
|
logging.info(line.center(BANNER_WIDTH))
|
|
logging.info('*' * BANNER_WIDTH)
|
|
|
|
@classmethod
|
|
def CreateTask(cls, *args, **kwargs):
|
|
"""Convenience method to create a new task."""
|
|
task = task_controller.TaskController(*args, **kwargs)
|
|
cls._registration_server.RegisterTaskCallback(
|
|
task.otp, task.OnConnect)
|
|
return task
|
|
|
|
@classmethod
|
|
def _SetUpFramework(cls):
|
|
"""Perform the framework-specific setup operations."""
|
|
cls._registration_server = (
|
|
task_registration_server.TaskRegistrationServer())
|
|
cls._registration_server.Start()
|
|
|
|
@classmethod
|
|
def _TearDownFramework(cls):
|
|
"""Perform the framework-specific teardown operations."""
|
|
if cls._registration_server:
|
|
cls._registration_server.Shutdown()
|
|
task_controller.TaskController.ReleaseAllTasks()
|
|
|
|
@classmethod
|
|
def _HandleSetUpClass(cls):
|
|
"""Performs common class-level setup operations.
|
|
|
|
This method performs test-wide setup such as starting the registration
|
|
server and then calls the original setUpClass method."""
|
|
try:
|
|
common_lib.InitLogging()
|
|
cls._LogInfoBanner('setUpClass', 'Performs class level setup.')
|
|
cls._SetUpFramework()
|
|
cls._OriginalSetUpClassMethod()
|
|
except:
|
|
# Make sure we tear down in case of any exceptions
|
|
cls._HandleTearDownClass(setup_failed=True)
|
|
exc_info = sys.exc_info()
|
|
logging.error('', exc_info=exc_info)
|
|
raise exc_info[0], exc_info[1], exc_info[2]
|
|
|
|
@classmethod
|
|
def _HandleTearDownClass(cls, setup_failed=False):
|
|
"""Performs common class-level tear down operations.
|
|
|
|
This method calls the original tearDownClass then performs test-wide
|
|
tear down such as stopping the registration server.
|
|
"""
|
|
cls._LogInfoBanner('tearDownClass', 'Performs class level tear down.')
|
|
try:
|
|
if not setup_failed:
|
|
cls._OriginalTearDownClassMethod()
|
|
finally:
|
|
cls._TearDownFramework()
|
|
|
|
|
|
def main():
|
|
unittest.main(verbosity=0, argv=sys.argv[:1])
|