aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.python/py-source-styling.exp
blob: 8eed56b3b8007784e4a6055cf7b9f3a8957291f5 (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# Copyright (C) 2022-2024 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Test related to source code highlighting and Python.  Includes a
# test for using the Pygments module as a fall back to GNU source
# highlight.
#
# This script also includes tests for handling a non-uft-8 character
# with both Pygments highlighting, and with gdb.execute (when using
# the list command).

require allow_python_tests

load_lib gdb-python.exp

standard_testfile

if { [build_executable "failed to build" ${testfile} ${srcfile}] == -1 } {
    return
}

set line_number [gdb_get_line_number "List this line."]

# Helper proc.  Run CMD, which should produce a source listing, and
# check if the source code is styled or not.  EXPECT_STYLED indicates
# if we expect the source listing to be styled or not.
proc check_source_listing_styling { cmd expect_styled { testname "" } } {
    if { $testname eq "" } {
	set testname $cmd
    }

    set seen_style_escape false
    gdb_test_multiple $cmd $testname {
	-re -wrap "Python Exception.*" {
	    fail $gdb_test_name
	    return
	}
	-re "\033" {
	    set seen_style_escape true
	    exp_continue
	}
	-re "$::gdb_prompt $" {
	    gdb_assert { $seen_style_escape == $expect_styled } \
		$gdb_test_name
	}
    }
}

# Check that the Python pygments module can be used for source
# highlighting when GNU source highlight is not available (or is
# disabled, as is done in this test).
proc test_pygments_styling {} {
    clean_restart $::binfile

    # Remote host boards disable styling via GDB's command line.  Turn
    # it back on now.
    if {[is_remote host]} {
	gdb_test "set style enabled on"
    }

    if { ![gdb_py_module_available "pygments"] } {
	unsupported "pygments module not available"
	return
    }

    if ![runto_main] {
	return
    }

    gdb_test_no_output "maint set gnu-source-highlight enabled off"

    gdb_test "maint flush source-cache" "Source cache flushed\\."

    check_source_listing_styling "list $::line_number" true
}

# Use gdb.execute to list source code containing non-utf-8 character.
# Check that initially GDB fails to convert the source code to a
# string, then set the correct host encoding, and try again.  This
# time the conversion should succeed.
proc test_gdb_execute_non_utf8_source {} {
    clean_restart $::binfile

    # The default host charset is utf-8, the source code contains a
    # non-utf-8 character, so this will fail.
    gdb_test \
	"python source = gdb.execute('list $::line_number', True, True)" \
	[multi_line \
	     "Python Exception <class 'UnicodeDecodeError'>: 'ascii' codec can't decode byte 0xc0 in position 250: ordinal not in range\\(128\\)" \
	     "Error occurred in Python: 'ascii' codec can't decode byte 0xc0 in position 250: ordinal not in range\\(128\\)"] \
	"gdb.execute fails to convert result to string"

    # Set the correct host charset, and try the conversion again.
    gdb_test_no_output "set host-charset ISO-8859-1"
    gdb_test_no_output \
	"python source = gdb.execute('list $::line_number', True, True)" \
	"gdb.execute does convert result to string"

    # Check that we captured something that looks like the expected source.
    gdb_test "python print(source)" ".*List this line.*"
}

# Use gdb.execute() to list source code.  Alternate between asking for
# styled, and unstyled source code.  In some cases we ask for the
# output to be returned via a string, and in other cases we ask for
# the output to be sent straight to stdout.
proc_with_prefix test_source_cache_style_tracking {} {
    clean_restart $::binfile

    # Remote host boards disable styling via GDB's command line.  Turn
    # it back on now.
    if {[is_remote host]} {
	gdb_test "set style enabled on"
    }

    gdb_test_no_output "set host-charset ISO-8859-1"

    # Commands which return styled, and non-styled source code mixed
    # together.  This ensures that the source cache will need to keep
    # discarding the entry with the wrong styling mode.  All of these
    # gdb.execute calls send their output via a string.
    check_source_listing_styling \
	"python print(gdb.execute('list $::line_number', to_string=True), end='')" \
	false
    check_source_listing_styling \
	"python print(gdb.execute('list $::line_number', to_string=True, styling=True), end='')" \
	true
    foreach from_tty { True False } {
	check_source_listing_styling \
	    "python print(gdb.execute('list $::line_number', $from_tty, True), end='')" \
	    false
	check_source_listing_styling \
	    "python print(gdb.execute('list $::line_number', $from_tty, True, True), end='')" \
	    true
	check_source_listing_styling \
	    "python print(gdb.execute('list $::line_number', $from_tty, True, False), end='')" \
	    false
    }

    # The same again, but this time the output is sent directly to
    # stdout.
    check_source_listing_styling \
	"python gdb.execute('list $::line_number')" \
	true
    check_source_listing_styling \
	"python gdb.execute('list $::line_number', to_string=False, styling=False)" \
	false
    check_source_listing_styling \
	"python gdb.execute('list $::line_number', to_string=False, styling=True)" \
	true
    foreach from_tty { True False } {
	check_source_listing_styling \
	    "python gdb.execute('list $::line_number', $from_tty, False, False)" \
	    false
	check_source_listing_styling \
	    "python gdb.execute('list $::line_number', $from_tty, False, True)" \
	    true
	check_source_listing_styling \
	    "python gdb.execute('list $::line_number', $from_tty, False)" \
	    true
    }
}

# We need an ANSI-capable terminal to get the output, additionally we
# need to set LC_ALL so GDB knows the terminal is UTF-8 capable,
# otherwise we'll get a UnicodeEncodeError trying to encode the
# output.
with_ansi_styling_terminal {
    test_pygments_styling
    test_gdb_execute_non_utf8_source
    test_source_cache_style_tracking
}