File: __init__.py

package info (click to toggle)
drgn 0.0.33-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,892 kB
  • sloc: python: 59,081; ansic: 51,400; awk: 423; makefile: 339; sh: 113
file content (95 lines) | stat: -rw-r--r-- 2,789 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Copyright (c) Meta Platforms, Inc. and affiliates.
# SPDX-License-Identifier: LGPL-2.1-or-later

import contextlib
import io
import os
import sys
import types

import drgn
from drgn.commands.crash import CRASH_COMMAND_NAMESPACE
from tests.linux_kernel import LinuxKernelTestCase


class CrashCommandTestCase(LinuxKernelTestCase):
    @contextlib.contextmanager
    def with_default_prog(self):
        try:
            old_default_prog = drgn.get_default_prog()
        except drgn.NoDefaultProgramError:
            old_default_prog = None
        try:
            drgn.set_default_prog(self.prog)
            yield
        finally:
            drgn.set_default_prog(old_default_prog)

    # Run a crash command and capture its stdout and stderr.
    def run_crash_command(self, command):
        with contextlib.redirect_stdout(
            io.StringIO()
        ) as stdout, contextlib.redirect_stderr(io.StringIO()) as stderr:
            CRASH_COMMAND_NAMESPACE.run(self.prog, command)
        return types.SimpleNamespace(stdout=stdout.getvalue(), stderr=stderr.getvalue())

    # Run a crash command with --drgn. Capture its stdout and check that it
    # doesn't write anything to stderr.
    #
    # mode must be "capture", "compile", or "exec".
    #
    # If mode is "compile" or "exec", check that it outputs valid, non-empty
    # Python code.
    #
    # If mode is "exec", also execute the code and capture any globals it sets.
    def run_crash_command_drgn_option(self, command, mode="exec"):
        assert mode in {"capture", "compile", "exec"}

        ret = self.run_crash_command(command + " --drgn")

        self.assertFalse(ret.stderr)

        if os.getenv("DRGN_TEST_LOG_CRASH_DRGN"):
            sys.stderr.write(
                f"""
{'=' * 88}
%crash {command} --drgn
{'-' * 88}
{ret.stdout}\
{'=' * 88}
"""
            )
            sys.stderr.flush()

        if mode == "compile" or mode == "exec":
            self.assertTrue(ret.stdout)
            ret.code = compile(ret.stdout, command + " --drgn", "exec")

        if mode == "exec":
            ret.globals = {"prog": self.prog}
            with self.with_default_prog():
                exec(ret.stdout, ret.globals)

        return ret

    # Run a crash command with and without --drgn. mode is passed to
    # run_crash_command_drgn_option().
    def check_crash_command(self, command, mode="exec"):
        drgn_option = self.run_crash_command_drgn_option(command, mode)

        ret = self.run_crash_command(command)

        if os.getenv("DRGN_TEST_LOG_CRASH_OUTPUT"):
            sys.stderr.write(
                f"""
{'=' * 88}
%crash {command}
{'-' * 88}
{ret.stdout}\
{'=' * 88}
"""
            )
            sys.stderr.flush()

        ret.drgn_option = drgn_option
        return ret