Add HW 2
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
SCRIPT_DIR = pathlib.Path(__file__).parent.resolve()
|
||||
SUITE_TIMEOUT_S = 120
|
||||
|
||||
|
||||
class PassedCounter:
|
||||
def __init__(self):
|
||||
self.passed = 0
|
||||
|
||||
def pytest_report_teststatus(self, report, config):
|
||||
if report.when == 'call' and report.passed:
|
||||
self.passed += 1
|
||||
|
||||
|
||||
def suite_score(passed, expected, maximum, exit_code=pytest.ExitCode.OK):
|
||||
return maximum if exit_code == pytest.ExitCode.OK and passed == expected else 0
|
||||
|
||||
|
||||
def run_suite(filename, expected, maximum):
|
||||
# Each component has its own deadline so a timeout cannot discard other scores.
|
||||
process = subprocess.Popen(
|
||||
[sys.executable, '-u', str(pathlib.Path(__file__).resolve()),
|
||||
'--suite', str(SCRIPT_DIR / filename), str(expected)],
|
||||
start_new_session=os.name == 'posix',
|
||||
)
|
||||
try:
|
||||
exit_code = process.wait(timeout=SUITE_TIMEOUT_S)
|
||||
except subprocess.TimeoutExpired:
|
||||
if os.name == 'posix':
|
||||
# Include grpcurl and other subprocesses started by this test suite.
|
||||
try:
|
||||
os.killpg(process.pid, signal.SIGKILL)
|
||||
except ProcessLookupError:
|
||||
pass # The suite may have exited just after wait() timed out.
|
||||
else:
|
||||
process.kill()
|
||||
process.wait()
|
||||
print(f'{filename} exceeded {SUITE_TIMEOUT_S} seconds; component score is zero.', flush=True)
|
||||
return 0
|
||||
return maximum if exit_code == 0 else 0
|
||||
|
||||
|
||||
def suite_exit_code(filename, expected):
|
||||
counter = PassedCounter()
|
||||
exit_code = pytest.main(['-vs', filename], plugins=[counter])
|
||||
return 0 if suite_score(counter.passed, expected, 1, exit_code) else 1
|
||||
|
||||
|
||||
def component_enabled(environment_name):
|
||||
return os.environ.get(environment_name, '1') == '1'
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--component',
|
||||
choices=('all', 'proto', 'server', 'client'),
|
||||
default='all',
|
||||
)
|
||||
parser.add_argument('--suite', nargs=2, metavar=('FILE', 'EXPECTED'), help=argparse.SUPPRESS)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
if args.suite is not None:
|
||||
return suite_exit_code(args.suite[0], int(args.suite[1]))
|
||||
component = args.component
|
||||
score = 0
|
||||
|
||||
if component in ('all', 'proto'):
|
||||
proto_score = run_suite('test_proto.py', expected=1, maximum=2)
|
||||
score += proto_score
|
||||
print(f'Proto: {proto_score}/2')
|
||||
print()
|
||||
|
||||
if component in ('all', 'server'):
|
||||
if component_enabled('MESSENGER_SERVER_TESTS_ENABLED'):
|
||||
server_score = run_suite('test_server.py', expected=4, maximum=4)
|
||||
else:
|
||||
server_score = 0
|
||||
print('Server tests were not run because the server image did not build.')
|
||||
score += server_score
|
||||
print(f'Server: {server_score}/4')
|
||||
print()
|
||||
|
||||
if component in ('all', 'client'):
|
||||
if component_enabled('MESSENGER_CLIENT_TESTS_ENABLED'):
|
||||
client_score = run_suite('test_client.py', expected=3, maximum=4)
|
||||
else:
|
||||
client_score = 0
|
||||
print('Client tests were not run because the client image did not build.')
|
||||
score += client_score
|
||||
print(f'Client: {client_score}/4')
|
||||
|
||||
print(f'\nSCORE: {score}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user