# Copyright (C) 2016-2025 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/>.

# Regression test for PR gdb/18360.  Test that "interrupt -a" while
# some thread is stepping over a breakpoint behaves as expected.

standard_testfile

if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
	 {debug pthreads}] == -1} {
    return -1
}

if {![runto_main]} {
    return -1
}

# Read the number of threads out of the inferior.
set NUM_THREADS [get_integer_valueof "num_threads" -1]

# Account for the main thread.
incr NUM_THREADS

# Run command and wait for the prompt, without end anchor.

proc gdb_test_no_anchor {cmd} {
    global gdb_prompt

    gdb_test_multiple $cmd $cmd {
	-re "$gdb_prompt " {
	    pass $cmd
	}
	-re "infrun:" {
	    exp_continue
	}
    }
}

# Enable/disable debugging.

proc enable_debug {enable} {

    # Comment out to debug problems with the test.
    return

    gdb_test_no_anchor "set debug infrun $enable"
    gdb_test_no_anchor "set debug displaced $enable"
}

# If RESULT is not zero, make the caller return RESULT.

proc return_if_nonzero { result } {
    if {$result != 0} {
	return -code return $result
    }
}

# Do one iteration of "c -a& -> interrupt -a".  Return zero on success,
# and non-zero if some test fails.

proc test_one_iteration {} {
    global gdb_prompt
    global NUM_THREADS
    global decimal
    global tdlabel_re

    set saw_continuing 0
    set test "continue -a &"
    return_if_nonzero [gdb_test_multiple $test $test {
	-re "Continuing.\r\n" {
	    set saw_continuing 1
	    exp_continue
	}
	-re "$gdb_prompt " {
	    if {![gdb_assert $saw_continuing $test]} {
		return 1
	    }
	}
	-re "infrun:" {
	    exp_continue
	}
    }]

    set running_count 0
    set test "all threads are running"
    return_if_nonzero [gdb_test_multiple "info threads" $test {
	-re "Thread \[^\r\n\]* \\(running\\)" {
	    incr running_count
	    exp_continue
	}
	-re "$gdb_prompt " {
	    if {![gdb_assert {$running_count == $NUM_THREADS} $test]} {
		return 1
	    }
	}
	-re "infrun:" {
	    exp_continue
	}
    }]

    set test "interrupt -a"
    return_if_nonzero [gdb_test_multiple $test $test {
	-re "$gdb_prompt " {
	    pass $test
	}
	-re "infrun:" {
	    exp_continue
	}
    }]

    set stopped_count 0
    set test "wait for stops"
    # Don't return on failure here, in order to let "info threads" put
    # useful info in gdb.log.
    gdb_test_multiple "" $test {
	-re "Thread $decimal \[^\r\n\]*stopped" {
	    incr stopped_count
	    if {$stopped_count != $NUM_THREADS} {
		exp_continue
	    }
	}
	-re "$gdb_prompt " {
	    gdb_assert {$stopped_count == $NUM_THREADS} $test
	}
	-re "infrun:" {
	    exp_continue
	}
    }

    # Check if all threads are seen as stopped with "info
    # threads".  It's a bit redundant with the test above, but
    # it's useful to have this in the gdb.log if the above ever
    # happens to fail.
    set running_count 0
    set test "all threads are stopped"
    return_if_nonzero [gdb_test_multiple "info threads" $test {
	-re "${tdlabel_re} \[^\r\n\]* \\(running\\)" {
	    incr running_count
	    exp_continue
	}
	-re "$gdb_prompt " {
	    if {![gdb_assert {$running_count == 0} $test]} {
		return 1
	    }
	}
    }]

    return 0
}

# The test driver proper.  If DISPLACED is "on", turn on displaced
# stepping.  If "off", turn it off.

proc testdriver {displaced} {
    global binfile
    global GDBFLAGS

    save_vars { GDBFLAGS } {
	append GDBFLAGS " -ex \"set non-stop on\""
	clean_restart $::testfile
    }

    gdb_test_no_output "set displaced-stepping $displaced"

    if {![runto all_started]} {
	return
    }
    set break_line [gdb_get_line_number "set breakpoint here"]

    gdb_test "break $break_line if always_zero" "Breakpoint .*" "set breakpoint"

    enable_debug 1

    for {set iter 0} {$iter < 20} {incr iter} {
	with_test_prefix "iter=$iter" {
	    # Return early if some test fails, to avoid cascading
	    # timeouts if something goes wrong.
	    if {[test_one_iteration] != 0} {
		return
	    }
	}
    }
}

foreach_with_prefix displaced-stepping {"on" "off"} {
    if { ${displaced-stepping} != "off" && ![support_displaced_stepping] } {
	continue
    }

    testdriver ${displaced-stepping}
}
