blob: 6fd96b848504adf14d6dd44bedcf4d29a4095c23 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Patrick Williams92b42cb2022-09-03 06:53:57 -05002# Copyright OpenEmbedded Contributors
3#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: MIT
5#
6
Brad Bishopd7bf8c12018-02-25 22:55:05 -05007from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd
9from oeqa.utils import CommandError
Brad Bishopd7bf8c12018-02-25 22:55:05 -050010
11import subprocess
12import threading
13import time
14import signal
15
16class MemLogger(object):
17 def __init__(self):
18 self.info_msgs = []
19 self.error_msgs = []
20
21 def info(self, msg):
22 self.info_msgs.append(msg)
23
24 def error(self, msg):
25 self.error_msgs.append(msg)
26
27class RunCmdTests(OESelftestTestCase):
28 """ Basic tests for runCmd() utility function """
29
30 # The delta is intentionally smaller than the timeout, to detect cases where
31 # we incorrectly apply the timeout more than once.
Andrew Geissler5f350902021-07-23 13:09:54 -040032 TIMEOUT = 10
33 DELTA = 8
Brad Bishopd7bf8c12018-02-25 22:55:05 -050034
Brad Bishopd7bf8c12018-02-25 22:55:05 -050035 def test_result_okay(self):
36 result = runCmd("true")
37 self.assertEqual(result.status, 0)
38
Brad Bishopd7bf8c12018-02-25 22:55:05 -050039 def test_result_false(self):
40 result = runCmd("false", ignore_status=True)
41 self.assertEqual(result.status, 1)
42
Brad Bishopd7bf8c12018-02-25 22:55:05 -050043 def test_shell(self):
44 # A shell is used for all string commands.
45 result = runCmd("false; true", ignore_status=True)
46 self.assertEqual(result.status, 0)
47
Brad Bishopd7bf8c12018-02-25 22:55:05 -050048 def test_no_shell(self):
49 self.assertRaises(FileNotFoundError,
50 runCmd, "false; true", shell=False)
51
Brad Bishopd7bf8c12018-02-25 22:55:05 -050052 def test_list_not_found(self):
53 self.assertRaises(FileNotFoundError,
54 runCmd, ["false; true"])
55
Brad Bishopd7bf8c12018-02-25 22:55:05 -050056 def test_list_okay(self):
57 result = runCmd(["true"])
58 self.assertEqual(result.status, 0)
59
Brad Bishopd7bf8c12018-02-25 22:55:05 -050060 def test_result_assertion(self):
61 self.assertRaisesRegexp(AssertionError, "Command 'echo .* false' returned non-zero exit status 1:\nfoobar",
62 runCmd, "echo foobar >&2; false", shell=True)
63
Brad Bishopd7bf8c12018-02-25 22:55:05 -050064 def test_result_exception(self):
65 self.assertRaisesRegexp(CommandError, "Command 'echo .* false' returned non-zero exit status 1 with output: foobar",
66 runCmd, "echo foobar >&2; false", shell=True, assert_error=False)
67
Brad Bishopd7bf8c12018-02-25 22:55:05 -050068 def test_output(self):
Andrew Geissler4c19ea12020-10-27 13:52:24 -050069 result = runCmd("echo stdout; echo stderr >&2", shell=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050070 self.assertEqual("stdout\nstderr", result.output)
71 self.assertEqual("", result.error)
72
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 def test_output_split(self):
Andrew Geissler4c19ea12020-10-27 13:52:24 -050074 result = runCmd("echo stdout; echo stderr >&2", shell=True, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050075 self.assertEqual("stdout", result.output)
76 self.assertEqual("stderr", result.error)
77
Brad Bishopd7bf8c12018-02-25 22:55:05 -050078 def test_timeout(self):
79 numthreads = threading.active_count()
80 start = time.time()
81 # Killing a hanging process only works when not using a shell?!
Andrew Geissler4c19ea12020-10-27 13:52:24 -050082 result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050083 self.assertEqual(result.status, -signal.SIGTERM)
84 end = time.time()
85 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -050086 self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
Brad Bishopd7bf8c12018-02-25 22:55:05 -050087
Brad Bishopd7bf8c12018-02-25 22:55:05 -050088 def test_timeout_split(self):
89 numthreads = threading.active_count()
90 start = time.time()
91 # Killing a hanging process only works when not using a shell?!
Andrew Geissler4c19ea12020-10-27 13:52:24 -050092 result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050093 self.assertEqual(result.status, -signal.SIGTERM)
94 end = time.time()
95 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -050096 self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
Brad Bishopd7bf8c12018-02-25 22:55:05 -050097
Brad Bishopd7bf8c12018-02-25 22:55:05 -050098 def test_stdin(self):
99 numthreads = threading.active_count()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500100 result = runCmd("cat", data=b"hello world", timeout=self.TIMEOUT, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500101 self.assertEqual("hello world", result.output)
Andrew Geisslerd25ed322020-06-27 00:28:28 -0500102 self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
103 self.assertEqual(numthreads, 1)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500104
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500105 def test_stdin_timeout(self):
106 numthreads = threading.active_count()
107 start = time.time()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500108 result = runCmd(['sleep', '60'], data=b"hello world", timeout=self.TIMEOUT, ignore_status=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500109 self.assertEqual(result.status, -signal.SIGTERM)
110 end = time.time()
111 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -0500112 self.assertEqual(numthreads, threading.active_count(), msg="Thread counts were not equal before (%s) and after (%s), active threads: %s" % (numthreads, threading.active_count(), threading.enumerate()))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500113
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500114 def test_log(self):
115 log = MemLogger()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500116 result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500117 self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout", "stderr"], log.info_msgs)
118 self.assertEqual([], log.error_msgs)
119
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500120 def test_log_split(self):
121 log = MemLogger()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500122 result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500123 self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout"], log.info_msgs)
124 self.assertEqual(["stderr"], log.error_msgs)