2022-06-21 18:49:25 +02:00
|
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
#
|
|
|
|
|
# Copyright © 2022 Emmanuel Fleury <emmanuel.fleury@gmail.com>
|
|
|
|
|
#
|
|
|
|
|
# This library is free software; you can redistribute it and/or
|
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This library is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
# License along with this library; if not, write to the Free Software
|
|
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
|
# MA 02110-1301 USA
|
|
|
|
|
|
|
|
|
|
""" Integration tests for g_assert() functions. """
|
|
|
|
|
|
|
|
|
|
import collections
|
|
|
|
|
import os
|
|
|
|
|
import shutil
|
|
|
|
|
import subprocess
|
|
|
|
|
import tempfile
|
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
|
|
import taptestrunner
|
|
|
|
|
|
|
|
|
|
Result = collections.namedtuple("Result", ("info", "out", "err"))
|
|
|
|
|
|
|
|
|
|
GDB_SCRIPT = """
|
|
|
|
|
# Work around https://sourceware.org/bugzilla/show_bug.cgi?id=22501
|
|
|
|
|
set confirm off
|
|
|
|
|
set print elements 0
|
|
|
|
|
set auto-load safe-path /
|
|
|
|
|
run
|
|
|
|
|
print *((char**) &__glib_assert_msg)
|
|
|
|
|
quit
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestAssertMessage(unittest.TestCase):
|
|
|
|
|
"""Integration test for throwing message on g_assert().
|
|
|
|
|
|
|
|
|
|
This can be run when installed or uninstalled. When uninstalled,
|
|
|
|
|
it requires G_TEST_BUILDDIR and G_TEST_SRCDIR to be set.
|
|
|
|
|
|
|
|
|
|
The idea with this test harness is to test if g_assert() prints
|
|
|
|
|
an error message when called, and that it saves this error
|
|
|
|
|
message in a global variable accessible to gdb, so that developers
|
|
|
|
|
and automated tools can more easily debug assertion failures.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.__gdb = shutil.which("gdb")
|
|
|
|
|
self.timeout_seconds = 10 # seconds per test
|
|
|
|
|
|
2022-10-14 14:04:18 +04:00
|
|
|
|
ext = ""
|
|
|
|
|
if os.name == "nt":
|
|
|
|
|
ext = ".exe"
|
2022-06-21 18:49:25 +02:00
|
|
|
|
if "G_TEST_BUILDDIR" in os.environ:
|
|
|
|
|
self.__assert_msg_test = os.path.join(
|
2022-10-14 14:04:18 +04:00
|
|
|
|
os.environ["G_TEST_BUILDDIR"], "assert-msg-test" + ext
|
2022-06-21 18:49:25 +02:00
|
|
|
|
)
|
|
|
|
|
else:
|
2022-07-24 16:33:12 +01:00
|
|
|
|
self.__assert_msg_test = os.path.join(
|
2022-10-14 14:04:18 +04:00
|
|
|
|
os.path.dirname(__file__), "assert-msg-test" + ext
|
2022-07-24 16:33:12 +01:00
|
|
|
|
)
|
2022-06-21 18:49:25 +02:00
|
|
|
|
print("assert-msg-test:", self.__assert_msg_test)
|
|
|
|
|
|
|
|
|
|
def runAssertMessage(self, *args):
|
|
|
|
|
argv = [self.__assert_msg_test]
|
|
|
|
|
argv.extend(args)
|
|
|
|
|
print("Running:", argv)
|
|
|
|
|
|
|
|
|
|
env = os.environ.copy()
|
|
|
|
|
env["LC_ALL"] = "C.UTF-8"
|
|
|
|
|
print("Environment:", env)
|
|
|
|
|
|
|
|
|
|
# We want to ensure consistent line endings...
|
|
|
|
|
info = subprocess.run(
|
|
|
|
|
argv,
|
|
|
|
|
timeout=self.timeout_seconds,
|
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
|
env=env,
|
|
|
|
|
universal_newlines=True,
|
|
|
|
|
)
|
|
|
|
|
out = info.stdout.strip()
|
|
|
|
|
err = info.stderr.strip()
|
|
|
|
|
|
|
|
|
|
result = Result(info, out, err)
|
|
|
|
|
|
|
|
|
|
print("Output:", result.out)
|
2022-06-29 14:41:07 +01:00
|
|
|
|
print("Error:", result.err)
|
2022-06-21 18:49:25 +02:00
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def runGdbAssertMessage(self, *args):
|
|
|
|
|
if self.__gdb is None:
|
|
|
|
|
return Result(None, "", "")
|
|
|
|
|
|
2022-12-12 10:52:41 +04:00
|
|
|
|
argv = ["gdb", "-n", "--batch"]
|
2022-06-21 18:49:25 +02:00
|
|
|
|
argv.extend(args)
|
|
|
|
|
print("Running:", argv)
|
|
|
|
|
|
|
|
|
|
env = os.environ.copy()
|
|
|
|
|
env["LC_ALL"] = "C.UTF-8"
|
|
|
|
|
print("Environment:", env)
|
|
|
|
|
|
|
|
|
|
# We want to ensure consistent line endings...
|
|
|
|
|
info = subprocess.run(
|
|
|
|
|
argv,
|
|
|
|
|
timeout=self.timeout_seconds,
|
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
|
stderr=subprocess.PIPE,
|
|
|
|
|
env=env,
|
|
|
|
|
universal_newlines=True,
|
|
|
|
|
)
|
|
|
|
|
out = info.stdout.strip()
|
|
|
|
|
err = info.stderr.strip()
|
|
|
|
|
|
|
|
|
|
result = Result(info, out, err)
|
|
|
|
|
|
|
|
|
|
print("Output:", result.out)
|
2022-06-29 14:41:07 +01:00
|
|
|
|
print("Error:", result.err)
|
|
|
|
|
print(result.info)
|
2022-06-21 18:49:25 +02:00
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def test_gassert(self):
|
|
|
|
|
"""Test running g_assert() and fail the program."""
|
|
|
|
|
result = self.runAssertMessage()
|
|
|
|
|
|
2022-10-14 14:04:18 +04:00
|
|
|
|
if os.name == "nt":
|
|
|
|
|
self.assertEqual(result.info.returncode, 3)
|
|
|
|
|
else:
|
|
|
|
|
self.assertEqual(result.info.returncode, -6)
|
2022-06-21 18:49:25 +02:00
|
|
|
|
self.assertIn("assertion failed: (42 < 0)", result.out)
|
|
|
|
|
|
|
|
|
|
def test_gdb_gassert(self):
|
|
|
|
|
"""Test running g_assert() within gdb and fail the program."""
|
|
|
|
|
if self.__gdb is None:
|
|
|
|
|
self.skipTest("GDB is not installed, skipping this test!")
|
|
|
|
|
|
|
|
|
|
with tempfile.NamedTemporaryFile(
|
2022-10-14 15:05:25 +04:00
|
|
|
|
prefix="assert-msg-test-", suffix=".gdb", mode="w", delete=False
|
2022-06-21 18:49:25 +02:00
|
|
|
|
) as tmp:
|
2022-10-14 15:05:25 +04:00
|
|
|
|
try:
|
|
|
|
|
tmp.write(GDB_SCRIPT)
|
|
|
|
|
tmp.close()
|
2022-10-19 12:28:08 +01:00
|
|
|
|
result = self.runGdbAssertMessage(
|
|
|
|
|
"-x", tmp.name, self.__assert_msg_test
|
|
|
|
|
)
|
2022-10-14 15:05:25 +04:00
|
|
|
|
finally:
|
|
|
|
|
os.unlink(tmp.name)
|
2022-06-29 14:41:07 +01:00
|
|
|
|
|
|
|
|
|
# Some CI environments disable ptrace (as they’re running in a
|
|
|
|
|
# container). If so, skip the test as there’s nothing we can do.
|
2023-03-02 00:13:22 -05:00
|
|
|
|
if result.info.returncode != 0 and (
|
|
|
|
|
"ptrace: Operation not permitted" in result.err
|
|
|
|
|
or "warning: opening /proc/PID/mem file for lwp" in result.err
|
2022-06-29 14:41:07 +01:00
|
|
|
|
):
|
|
|
|
|
self.skipTest("GDB is not functional due to ptrace being disabled")
|
|
|
|
|
|
2022-06-21 18:49:25 +02:00
|
|
|
|
self.assertEqual(result.info.returncode, 0)
|
|
|
|
|
self.assertIn("$1 = 0x", result.out)
|
|
|
|
|
self.assertIn("assertion failed: (42 < 0)", result.out)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|