xref: /aosp_15_r20/external/cronet/testing/test_env_unittest.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6777b538SAndroid Build Coastguard Worker# Copyright 2019 The Chromium Authors
3*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
5*6777b538SAndroid Build Coastguard Worker
6*6777b538SAndroid Build Coastguard Worker"""Unit tests for test_env.py functionality.
7*6777b538SAndroid Build Coastguard Worker
8*6777b538SAndroid Build Coastguard WorkerEach unit test is launches python process that uses test_env.py
9*6777b538SAndroid Build Coastguard Workerto launch another python process. Then signal handling and
10*6777b538SAndroid Build Coastguard Workerpropagation is tested. This similates how Swarming uses test_env.py.
11*6777b538SAndroid Build Coastguard Worker"""
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Workerimport os
14*6777b538SAndroid Build Coastguard Workerimport signal
15*6777b538SAndroid Build Coastguard Workerimport subprocess
16*6777b538SAndroid Build Coastguard Workerimport sys
17*6777b538SAndroid Build Coastguard Workerimport time
18*6777b538SAndroid Build Coastguard Workerimport unittest
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard WorkerHERE = os.path.dirname(os.path.abspath(__file__))
21*6777b538SAndroid Build Coastguard WorkerTEST_SCRIPT = os.path.join(HERE, 'test_env_user_script.py')
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Workerdef launch_process_windows(args):
25*6777b538SAndroid Build Coastguard Worker  # The `universal_newlines` option is equivalent to `text` in Python 3.
26*6777b538SAndroid Build Coastguard Worker  return subprocess.Popen(
27*6777b538SAndroid Build Coastguard Worker      [sys.executable, TEST_SCRIPT] + args,
28*6777b538SAndroid Build Coastguard Worker      stdout=subprocess.PIPE,
29*6777b538SAndroid Build Coastguard Worker      stderr=subprocess.STDOUT,
30*6777b538SAndroid Build Coastguard Worker      env=os.environ.copy(),
31*6777b538SAndroid Build Coastguard Worker      creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
32*6777b538SAndroid Build Coastguard Worker      universal_newlines=True)
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Workerdef launch_process_nonwindows(args):
36*6777b538SAndroid Build Coastguard Worker  # The `universal_newlines` option is equivalent to `text` in Python 3.
37*6777b538SAndroid Build Coastguard Worker  return subprocess.Popen(
38*6777b538SAndroid Build Coastguard Worker      [sys.executable, TEST_SCRIPT] + args,
39*6777b538SAndroid Build Coastguard Worker      stdout=subprocess.PIPE,
40*6777b538SAndroid Build Coastguard Worker      stderr=subprocess.STDOUT,
41*6777b538SAndroid Build Coastguard Worker      env=os.environ.copy(),
42*6777b538SAndroid Build Coastguard Worker      universal_newlines=True)
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker
45*6777b538SAndroid Build Coastguard Worker# pylint: disable=inconsistent-return-statements
46*6777b538SAndroid Build Coastguard Workerdef read_subprocess_message(proc, starts_with):
47*6777b538SAndroid Build Coastguard Worker  """Finds the value after first line prefix condition."""
48*6777b538SAndroid Build Coastguard Worker  for line in proc.stdout:
49*6777b538SAndroid Build Coastguard Worker    if line.startswith(starts_with):
50*6777b538SAndroid Build Coastguard Worker      return line.rstrip().replace(starts_with, '')
51*6777b538SAndroid Build Coastguard Worker# pylint: enable=inconsistent-return-statements
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Workerdef send_and_wait(proc, sig, sleep_time=0.6):
55*6777b538SAndroid Build Coastguard Worker  """Sends a signal to subprocess."""
56*6777b538SAndroid Build Coastguard Worker  time.sleep(sleep_time)  # gives process time to launch.
57*6777b538SAndroid Build Coastguard Worker  os.kill(proc.pid, sig)
58*6777b538SAndroid Build Coastguard Worker  proc.wait()
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Workerclass SignalingWindowsTest(unittest.TestCase):
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker  def setUp(self):
64*6777b538SAndroid Build Coastguard Worker    super().setUp()
65*6777b538SAndroid Build Coastguard Worker    if sys.platform != 'win32':
66*6777b538SAndroid Build Coastguard Worker      self.skipTest('test only runs on Windows')
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker  def test_send_ctrl_break_event(self):
69*6777b538SAndroid Build Coastguard Worker    proc = launch_process_windows([])
70*6777b538SAndroid Build Coastguard Worker    send_and_wait(proc, signal.CTRL_BREAK_EVENT) # pylint: disable=no-member
71*6777b538SAndroid Build Coastguard Worker    sig = read_subprocess_message(proc, 'Signal :')
72*6777b538SAndroid Build Coastguard Worker    # This test is flaky because it relies on the child process starting quickly
73*6777b538SAndroid Build Coastguard Worker    # "enough", which it fails to do sometimes. This is tracked by
74*6777b538SAndroid Build Coastguard Worker    # https://crbug.com/1335123 and it is hoped that increasing the timeout will
75*6777b538SAndroid Build Coastguard Worker    # reduce the flakiness.
76*6777b538SAndroid Build Coastguard Worker    self.assertEqual(sig, str(int(signal.SIGBREAK))) # pylint: disable=no-member
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Workerclass SignalingNonWindowsTest(unittest.TestCase):
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker  def setUp(self):
82*6777b538SAndroid Build Coastguard Worker    super().setUp()
83*6777b538SAndroid Build Coastguard Worker    if sys.platform == 'win32':
84*6777b538SAndroid Build Coastguard Worker      self.skipTest('test does not run on Windows')
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker  def test_send_sigterm(self):
87*6777b538SAndroid Build Coastguard Worker    proc = launch_process_nonwindows([])
88*6777b538SAndroid Build Coastguard Worker    send_and_wait(proc, signal.SIGTERM)
89*6777b538SAndroid Build Coastguard Worker    sig = read_subprocess_message(proc, 'Signal :')
90*6777b538SAndroid Build Coastguard Worker    self.assertEqual(sig, str(int(signal.SIGTERM)))
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker  def test_send_sigint(self):
93*6777b538SAndroid Build Coastguard Worker    proc = launch_process_nonwindows([])
94*6777b538SAndroid Build Coastguard Worker    send_and_wait(proc, signal.SIGINT)
95*6777b538SAndroid Build Coastguard Worker    sig = read_subprocess_message(proc, 'Signal :')
96*6777b538SAndroid Build Coastguard Worker    self.assertEqual(sig, str(int(signal.SIGINT)))
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
100*6777b538SAndroid Build Coastguard Worker  unittest.main()
101