xref: /aosp_15_r20/build/make/ci/ci_test_lib.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker# Copyright 2024, The Android Open Source Project
2*9e94795aSAndroid Build Coastguard Worker#
3*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*9e94795aSAndroid Build Coastguard Worker#
7*9e94795aSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*9e94795aSAndroid Build Coastguard Worker#
9*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*9e94795aSAndroid Build Coastguard Worker# limitations under the License.
14*9e94795aSAndroid Build Coastguard Worker
15*9e94795aSAndroid Build Coastguard Worker"""Testing utilities for tests in the CI package."""
16*9e94795aSAndroid Build Coastguard Worker
17*9e94795aSAndroid Build Coastguard Workerimport logging
18*9e94795aSAndroid Build Coastguard Workerimport os
19*9e94795aSAndroid Build Coastguard Workerimport unittest
20*9e94795aSAndroid Build Coastguard Workerimport subprocess
21*9e94795aSAndroid Build Coastguard Workerimport pathlib
22*9e94795aSAndroid Build Coastguard Workerimport shutil
23*9e94795aSAndroid Build Coastguard Workerimport tempfile
24*9e94795aSAndroid Build Coastguard Worker
25*9e94795aSAndroid Build Coastguard Worker
26*9e94795aSAndroid Build Coastguard Worker# Export the TestCase class to reduce the number of imports tests have to list.
27*9e94795aSAndroid Build Coastguard WorkerTestCase = unittest.TestCase
28*9e94795aSAndroid Build Coastguard Worker
29*9e94795aSAndroid Build Coastguard Worker
30*9e94795aSAndroid Build Coastguard Workerdef process_alive(pid):
31*9e94795aSAndroid Build Coastguard Worker  """Check For the existence of a pid."""
32*9e94795aSAndroid Build Coastguard Worker
33*9e94795aSAndroid Build Coastguard Worker  try:
34*9e94795aSAndroid Build Coastguard Worker    os.kill(pid, 0)
35*9e94795aSAndroid Build Coastguard Worker  except OSError:
36*9e94795aSAndroid Build Coastguard Worker    return False
37*9e94795aSAndroid Build Coastguard Worker
38*9e94795aSAndroid Build Coastguard Worker  return True
39*9e94795aSAndroid Build Coastguard Worker
40*9e94795aSAndroid Build Coastguard Worker
41*9e94795aSAndroid Build Coastguard Workerclass TemporaryProcessSession:
42*9e94795aSAndroid Build Coastguard Worker
43*9e94795aSAndroid Build Coastguard Worker  def __init__(self, test_case: TestCase):
44*9e94795aSAndroid Build Coastguard Worker    self._created_processes = []
45*9e94795aSAndroid Build Coastguard Worker    test_case.addCleanup(self.cleanup)
46*9e94795aSAndroid Build Coastguard Worker
47*9e94795aSAndroid Build Coastguard Worker  def create(self, args, kwargs):
48*9e94795aSAndroid Build Coastguard Worker    p = subprocess.Popen(*args, **kwargs, start_new_session=True)
49*9e94795aSAndroid Build Coastguard Worker    self._created_processes.append(p)
50*9e94795aSAndroid Build Coastguard Worker    return p
51*9e94795aSAndroid Build Coastguard Worker
52*9e94795aSAndroid Build Coastguard Worker  def cleanup(self):
53*9e94795aSAndroid Build Coastguard Worker    for p in self._created_processes:
54*9e94795aSAndroid Build Coastguard Worker      if not process_alive(p.pid):
55*9e94795aSAndroid Build Coastguard Worker        return
56*9e94795aSAndroid Build Coastguard Worker      os.killpg(os.getpgid(p.pid), signal.SIGKILL)
57*9e94795aSAndroid Build Coastguard Worker
58*9e94795aSAndroid Build Coastguard Worker
59*9e94795aSAndroid Build Coastguard Workerclass TestTemporaryDirectory:
60*9e94795aSAndroid Build Coastguard Worker
61*9e94795aSAndroid Build Coastguard Worker  def __init__(self, delete: bool, ):
62*9e94795aSAndroid Build Coastguard Worker    self._delete = delete
63*9e94795aSAndroid Build Coastguard Worker
64*9e94795aSAndroid Build Coastguard Worker  @classmethod
65*9e94795aSAndroid Build Coastguard Worker  def create(cls, test_case: TestCase, delete: bool = True):
66*9e94795aSAndroid Build Coastguard Worker    temp_dir = TestTemporaryDirectory(delete)
67*9e94795aSAndroid Build Coastguard Worker    temp_dir._dir = pathlib.Path(tempfile.mkdtemp())
68*9e94795aSAndroid Build Coastguard Worker    test_case.addCleanup(temp_dir.cleanup)
69*9e94795aSAndroid Build Coastguard Worker    return temp_dir._dir
70*9e94795aSAndroid Build Coastguard Worker
71*9e94795aSAndroid Build Coastguard Worker  def get_dir(self):
72*9e94795aSAndroid Build Coastguard Worker    return self._dir
73*9e94795aSAndroid Build Coastguard Worker
74*9e94795aSAndroid Build Coastguard Worker  def cleanup(self):
75*9e94795aSAndroid Build Coastguard Worker    if not self._delete:
76*9e94795aSAndroid Build Coastguard Worker      return
77*9e94795aSAndroid Build Coastguard Worker    shutil.rmtree(self._dir, ignore_errors=True)
78*9e94795aSAndroid Build Coastguard Worker
79*9e94795aSAndroid Build Coastguard Worker
80*9e94795aSAndroid Build Coastguard Workerdef main():
81*9e94795aSAndroid Build Coastguard Worker
82*9e94795aSAndroid Build Coastguard Worker  # Disable logging since it breaks the TF Python test output parser.
83*9e94795aSAndroid Build Coastguard Worker  # TODO(hzalek): Use TF's `test-output-file` option to re-enable logging.
84*9e94795aSAndroid Build Coastguard Worker  logging.getLogger().disabled = True
85*9e94795aSAndroid Build Coastguard Worker
86*9e94795aSAndroid Build Coastguard Worker  unittest.main()
87