# Copyright 2017-2021 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/>.

# Common routines for testing multi-target features.

load_lib gdbserver-support.exp

standard_testfile multi-target.c

# Keep a list of (inferior ID, spawn ID).
set server_spawn_ids [list]

proc connect_target_extended_remote {binfile num} {
    set res [gdbserver_start "--multi" ""]
    global server_spawn_ids server_spawn_id
    lappend server_spawn_ids $num $server_spawn_id
    set gdbserver_gdbport [lindex $res 1]
    return [gdb_target_cmd "extended-remote" $gdbserver_gdbport]
}

# Add and start inferior number NUM.  Returns true on success, false
# otherwise.
proc add_inferior {num target binfile {gcorefile ""}} {
    # Start another inferior.
    gdb_test "add-inferior -no-connection" "Added inferior $num" \
	"add empty inferior $num"
    gdb_test "inferior $num" "Switching to inferior $num.*" \
	"switch to inferior $num"
    gdb_test "file ${binfile}" ".*" "load file in inferior $num"
    gdb_test_no_output "set remote exec-file ${binfile}" \
	"set remote-exec file in inferior $num"

    if {$target == "core"} {
	gdb_test "core $gcorefile" "Core was generated by.*" \
	    "core [file tail $gcorefile], inf $num"
	return 1
    }

    if {$target == "extended-remote"} {
	if {[connect_target_extended_remote $binfile $num]} {
	    return 0
	}
    }
    if ![runto "all_started"] then {
	return 0
    }
    delete_breakpoints

    return 1
}

proc prepare_core {} {
    global gcorefile gcore_created
    global binfile

    clean_restart ${binfile}

    if ![runto all_started] then {
	return -1
    }

    global testfile
    set gcorefile [standard_output_file $testfile.gcore]
    set gcore_created [gdb_gcore_cmd $gcorefile "save a core file"]
}

proc next_live_inferior {inf} {
    incr inf
    if {$inf == 3} {
	# 3 is a core.
	return 4
    }
    if {$inf > 5} {
	# 6 is a core.
	return 1
    }

    return $inf
}

# Clean up the server_spawn_ids.
proc cleanup_gdbservers { } {
    global server_spawn_id
    global server_spawn_ids
    foreach { inferior_id spawn_id } $server_spawn_ids {
	set server_spawn_id $spawn_id
	gdb_test "inferior $inferior_id"
	gdbserver_exit 0
    }
    set server_spawn_ids [list]
}

# Return true on success, false otherwise.

proc setup {non-stop} {
    global gcorefile gcore_created
    global binfile

    cleanup_gdbservers

    save_vars { ::GDBFLAGS } {
	# Make GDB read files from the local file system, not through the
	# remote targets, to speed things up.
	set ::GDBFLAGS "${::GDBFLAGS} -ex \"set sysroot\""
	clean_restart ${binfile}
    }

    # multi-target depends on target running in non-stop mode.  Force
    # it on for remote targets, until this is the default.
    gdb_test_no_output "maint set target-non-stop on"

    gdb_test_no_output "set non-stop ${non-stop}"

    if ![runto all_started] then {
	return 0
    }

    delete_breakpoints

    # inferior 1 -> native
    # inferior 2 -> extended-remote
    # inferior 3 -> core
    # inferior 4 -> native
    # inferior 5 -> extended-remote
    # inferior 6 -> core
    if {![add_inferior 2 "extended-remote" $binfile]} {
	return 0
    }
    if {![add_inferior 3 "core" $binfile $gcorefile]} {
	return 0
    }
    if {![add_inferior 4 "native" $binfile]} {
	return 0
    }
    if {![add_inferior 5 "extended-remote" $binfile]} {
	return 0
    }
    if {![add_inferior 6 "core" $binfile $gcorefile]} {
	return 0
    }

    # For debugging.
    gdb_test "info threads" ".*"

    # Make "continue" resume all inferiors.
    if {${non-stop} == "off"} {
	gdb_test_no_output "set schedule-multiple on"
    }

    return 1
}

proc multi_target_prepare {} {
    global binfile srcfile

    if { [skip_gdbserver_tests] } {
	return 0
    }

    # The plain remote target can't do multiple inferiors.
    if {[target_info gdb_protocol] != ""} {
	return 0
    }

    if { [prepare_for_testing "failed to prepare" ${binfile} "${srcfile}" \
	      {debug pthreads}] } {
	return 0
    }

    # Make a core file with two threads upfront.  Several tests load
    # the same core file.
    prepare_core

    return 1
}

proc multi_target_cleanup {} {
    cleanup_gdbservers
}
