blob: e9612389feccd720165facd1c23cbdc5b091e9fb [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: MIT
3#
4
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005from oeqa.selftest.case import OESelftestTestCase
6from oeqa.utils.commands import runCmd
7from oeqa.utils import CommandError
Brad Bishopd7bf8c12018-02-25 22:55:05 -05008
9import subprocess
10import threading
11import time
12import signal
13
14class MemLogger(object):
15 def __init__(self):
16 self.info_msgs = []
17 self.error_msgs = []
18
19 def info(self, msg):
20 self.info_msgs.append(msg)
21
22 def error(self, msg):
23 self.error_msgs.append(msg)
24
25class RunCmdTests(OESelftestTestCase):
26 """ Basic tests for runCmd() utility function """
27
28 # The delta is intentionally smaller than the timeout, to detect cases where
29 # we incorrectly apply the timeout more than once.
Andrew Geissler5f350902021-07-23 13:09:54 -040030 TIMEOUT = 10
31 DELTA = 8
Brad Bishopd7bf8c12018-02-25 22:55:05 -050032
Brad Bishopd7bf8c12018-02-25 22:55:05 -050033 def test_result_okay(self):
34 result = runCmd("true")
35 self.assertEqual(result.status, 0)
36
Brad Bishopd7bf8c12018-02-25 22:55:05 -050037 def test_result_false(self):
38 result = runCmd("false", ignore_status=True)
39 self.assertEqual(result.status, 1)
40
Brad Bishopd7bf8c12018-02-25 22:55:05 -050041 def test_shell(self):
42 # A shell is used for all string commands.
43 result = runCmd("false; true", ignore_status=True)
44 self.assertEqual(result.status, 0)
45
Brad Bishopd7bf8c12018-02-25 22:55:05 -050046 def test_no_shell(self):
47 self.assertRaises(FileNotFoundError,
48 runCmd, "false; true", shell=False)
49
Brad Bishopd7bf8c12018-02-25 22:55:05 -050050 def test_list_not_found(self):
51 self.assertRaises(FileNotFoundError,
52 runCmd, ["false; true"])
53
Brad Bishopd7bf8c12018-02-25 22:55:05 -050054 def test_list_okay(self):
55 result = runCmd(["true"])
56 self.assertEqual(result.status, 0)
57
Brad Bishopd7bf8c12018-02-25 22:55:05 -050058 def test_result_assertion(self):
59 self.assertRaisesRegexp(AssertionError, "Command 'echo .* false' returned non-zero exit status 1:\nfoobar",
60 runCmd, "echo foobar >&2; false", shell=True)
61
Brad Bishopd7bf8c12018-02-25 22:55:05 -050062 def test_result_exception(self):
63 self.assertRaisesRegexp(CommandError, "Command 'echo .* false' returned non-zero exit status 1 with output: foobar",
64 runCmd, "echo foobar >&2; false", shell=True, assert_error=False)
65
Brad Bishopd7bf8c12018-02-25 22:55:05 -050066 def test_output(self):
Andrew Geissler4c19ea12020-10-27 13:52:24 -050067 result = runCmd("echo stdout; echo stderr >&2", shell=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050068 self.assertEqual("stdout\nstderr", result.output)
69 self.assertEqual("", result.error)
70
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071 def test_output_split(self):
Andrew Geissler4c19ea12020-10-27 13:52:24 -050072 result = runCmd("echo stdout; echo stderr >&2", shell=True, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050073 self.assertEqual("stdout", result.output)
74 self.assertEqual("stderr", result.error)
75
Brad Bishopd7bf8c12018-02-25 22:55:05 -050076 def test_timeout(self):
77 numthreads = threading.active_count()
78 start = time.time()
79 # Killing a hanging process only works when not using a shell?!
Andrew Geissler4c19ea12020-10-27 13:52:24 -050080 result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050081 self.assertEqual(result.status, -signal.SIGTERM)
82 end = time.time()
83 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -050084 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 -050085
Brad Bishopd7bf8c12018-02-25 22:55:05 -050086 def test_timeout_split(self):
87 numthreads = threading.active_count()
88 start = time.time()
89 # Killing a hanging process only works when not using a shell?!
Andrew Geissler4c19ea12020-10-27 13:52:24 -050090 result = runCmd(['sleep', '60'], timeout=self.TIMEOUT, ignore_status=True, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050091 self.assertEqual(result.status, -signal.SIGTERM)
92 end = time.time()
93 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -050094 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 -050095
Brad Bishopd7bf8c12018-02-25 22:55:05 -050096 def test_stdin(self):
97 numthreads = threading.active_count()
Andrew Geissler4c19ea12020-10-27 13:52:24 -050098 result = runCmd("cat", data=b"hello world", timeout=self.TIMEOUT, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050099 self.assertEqual("hello world", result.output)
Andrew Geisslerd25ed322020-06-27 00:28:28 -0500100 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()))
101 self.assertEqual(numthreads, 1)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500102
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500103 def test_stdin_timeout(self):
104 numthreads = threading.active_count()
105 start = time.time()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500106 result = runCmd(['sleep', '60'], data=b"hello world", timeout=self.TIMEOUT, ignore_status=True, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500107 self.assertEqual(result.status, -signal.SIGTERM)
108 end = time.time()
109 self.assertLess(end - start, self.TIMEOUT + self.DELTA)
Andrew Geisslerd25ed322020-06-27 00:28:28 -0500110 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 -0500111
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500112 def test_log(self):
113 log = MemLogger()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500114 result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500115 self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout", "stderr"], log.info_msgs)
116 self.assertEqual([], log.error_msgs)
117
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500118 def test_log_split(self):
119 log = MemLogger()
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500120 result = runCmd("echo stdout; echo stderr >&2", shell=True, output_log=log, stderr=subprocess.PIPE, sync=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500121 self.assertEqual(["Running: echo stdout; echo stderr >&2", "stdout"], log.info_msgs)
122 self.assertEqual(["stderr"], log.error_msgs)