mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-25 21:46:14 +01:00
19a8df9d8b
Similar to commit 6e44151bf7
, skip the test if gdb is unable to read
/proc/PID/mem, which gdb does as a fallback if ptrace is unavailable.
This allows the test to skip when run under Gentoo's sandbox.
174 lines
5.5 KiB
Python
Executable File
174 lines
5.5 KiB
Python
Executable File
#!/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
|
||
|
||
ext = ""
|
||
if os.name == "nt":
|
||
ext = ".exe"
|
||
if "G_TEST_BUILDDIR" in os.environ:
|
||
self.__assert_msg_test = os.path.join(
|
||
os.environ["G_TEST_BUILDDIR"], "assert-msg-test" + ext
|
||
)
|
||
else:
|
||
self.__assert_msg_test = os.path.join(
|
||
os.path.dirname(__file__), "assert-msg-test" + ext
|
||
)
|
||
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)
|
||
print("Error:", result.err)
|
||
return result
|
||
|
||
def runGdbAssertMessage(self, *args):
|
||
if self.__gdb is None:
|
||
return Result(None, "", "")
|
||
|
||
argv = ["gdb", "-n", "--batch"]
|
||
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)
|
||
print("Error:", result.err)
|
||
print(result.info)
|
||
return result
|
||
|
||
def test_gassert(self):
|
||
"""Test running g_assert() and fail the program."""
|
||
result = self.runAssertMessage()
|
||
|
||
if os.name == "nt":
|
||
self.assertEqual(result.info.returncode, 3)
|
||
else:
|
||
self.assertEqual(result.info.returncode, -6)
|
||
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(
|
||
prefix="assert-msg-test-", suffix=".gdb", mode="w", delete=False
|
||
) as tmp:
|
||
try:
|
||
tmp.write(GDB_SCRIPT)
|
||
tmp.close()
|
||
result = self.runGdbAssertMessage(
|
||
"-x", tmp.name, self.__assert_msg_test
|
||
)
|
||
finally:
|
||
os.unlink(tmp.name)
|
||
|
||
# Some CI environments disable ptrace (as they’re running in a
|
||
# container). If so, skip the test as there’s nothing we can do.
|
||
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
|
||
):
|
||
self.skipTest("GDB is not functional due to ptrace being disabled")
|
||
|
||
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())
|