# Copyright 2020-2026 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/>.

# Helper functions to make it easier to write debuginfod tests.

# tclint-disable redefined-builtin

# Return true if the debuginfod tests should be run, otherwise, return
# false.
proc allow_debuginfod_tests {} {
    if {[is_remote host]} {
	return false
    }

    if { [which debuginfod] == 0 } {
	return false
    }

    if { [which curl] == 0 } {
	untested "cannot find curl"
	return false
    }

    # Skip testing if gdb was not configured with debuginfod.
    #
    # If GDB is built with ASan, it warns that some signal handlers
    # (installed by ASan) exist on startup.  That makes TCL's exec throw an
    # error.  This is dealt with by the --quiet in INTERNAL_GDBFLAGS.
    if { [string first "with-debuginfod" \
	      [exec $::GDB {*}$::INTERNAL_GDBFLAGS \
		   --configuration]] == -1 } {
	return false
    }

    return true
}

# Create two directories within the current output directory.  One directory
# will be used by GDB as the client cache to hold downloaded debug
# information, and the other directory will be used by the debuginfod server
# as its cache of the parsed debug files that will be served to GDB.
#
# Call this proc with the names to two variables, these variables will be
# set in the parent scope with the paths to the two directories.
#
# This proc allocates the names for the directories, but doesn't create
# them.  In fact, if the directories already exist, this proc will delete
# them, this ensures that any existing contents are also deleted.
proc prepare_for_debuginfod { cache_var db_var } {
    upvar $cache_var cache
    upvar $db_var db

    set cache [standard_output_file ".client_cache"]
    set db [standard_output_file ".debuginfod.db"]

    # Delete any preexisting test files.
    file delete -force $cache
    file delete -force $db
}

# Run BODY with the three environment variables required to control
# debuginfod set.  The timeout is set based on the usual timeouts used by
# GDB within dejagnu (see get_largest_timeout), the debuginfod cache is set
# to CACHE (this is where downloaded debug data is placed), and the
# debuginfod urls environment variable is set to be the empty string.
#
# Within BODY you should start a debuginfod server and set the environment
# variable DEBUGINFOD_URLS as appropriate (see start_debuginfod for details).
#
# The reason that this proc doesn't automatically start debuginfod, is that
# in some test cases we want to initially test with debuginfod not running
# and/or disabled.
proc with_debuginfod_env { cache body } {
    set envlist \
	[list \
	     env(DEBUGINFOD_URLS) \
	     env(DEBUGINFOD_TIMEOUT) \
	     env(DEBUGINFOD_CACHE_PATH)]

    save_vars $envlist {
	setenv DEBUGINFOD_TIMEOUT [get_largest_timeout]
	setenv DEBUGINFOD_CACHE_PATH $cache
	setenv DEBUGINFOD_URLS ""

	uplevel 1 $body
    }
}

# Start a debuginfod server.  DB is the directory to use for the server's
# database cache, while DEBUGDIR is a directory containing all the debug
# information that the server should server.
#
# This proc will try to find an available port to start the server on, will
# start the server, and check that the server has started correctly.
#
# If the server starts correctly, then this proc will return the url that
# should be used to communicate with the server.  If the server can't be
# started, then an error will be printed, and an empty string returned.
#
# If the server is successfully started then the global variable
# debuginfod_spawn_id will be set with the spawn_id of the debuginfod
# process.
proc start_debuginfod { db debugdir } {
    global debuginfod_spawn_id spawn_id

    # Find an unused port.
    set port 7999
    set found false
    while { ! $found } {
	incr port
	if { $port == 65536 } {
	    perror "no available ports"
	    return ""
	}

	if { [info exists spawn_id] } {
	    set old_spawn_id $spawn_id
	}

	spawn debuginfod -vvvv -d $db -p $port -F $debugdir
	set debuginfod_spawn_id $spawn_id

	if { [info exists old_spawn_id] } {
	    set spawn_id $old_spawn_id
	    unset old_spawn_id
	}

	expect {
	    -i $debuginfod_spawn_id
	    "started http server on IPv4 IPv6 port=$port" { set found true }
	    "started http server on IPv4 port=$port" { set found true }
	    "started http server on IPv6 port=$port" {}
	    "failed to bind to port" {}
	    timeout {
		stop_debuginfod
		perror "find port timeout"
		return ""
	    }
	}
	if { ! $found } {
	    stop_debuginfod
	}
    }

    set url "http://127.0.0.1:$port"

    set metrics [list "ready 1" \
		     "thread_work_total{role=\"traverse\"} 1" \
		     "thread_work_pending{role=\"scan\"} 0" \
		     "thread_busy{role=\"scan\"} 0"]

    # Check server metrics to confirm init has completed.
    foreach m $metrics {
	set timelim 20
	while { $timelim != 0 } {
	    sleep 0.5
	    catch {exec curl -s $url/metrics} got

	    if { [regexp $m $got] } {
		break
	    }

	    incr timelim -1
	}

	if { $timelim == 0 } {
	    stop_debuginfod
	    perror "server init timeout"
	    return ""
	}
    }

    return $url
}

# Drain output from debuginfod.

proc drain_debuginfod {} {
    verbose -log "drain debuginfod output --- start"
    expect {
	-i $::debuginfod_spawn_id ".*" {
	}
    }
    verbose -log "drain debuginfod output --- end"
}

# If the global debuginfod_spawn_id exists, then kill that process and unset
# the debuginfod_spawn_id global.  This can be used to shutdown the
# debuginfod server.
proc stop_debuginfod { } {
    global debuginfod_spawn_id

    if {[info exists debuginfod_spawn_id]} {
	kill_wait_spawned_process $debuginfod_spawn_id
	unset debuginfod_spawn_id
    }
}
