| 12
 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
 
 | # Copyright 2016 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 that -exec-run works as expected.  Exercises various testing
# axes:
#
# - MI running on main UI vs separate UI.
#
# - inferior tty set to main tty vs separate tty.
#
# - forking the child failing and sending output to the right inferior
#   terminal, vs the child not failing to start.
load_lib mi-support.exp
set MIFLAGS "-i=mi"
# The purpose of this testcase is to test the -exec-run command. If we
# cannot use it, then there is no point in running this testcase.
if [target_info exists use_gdb_stub] {
     untested "cannot use -exec-run command"
     return -1
}
standard_testfile mi-start.c
if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
     untested "could not build mi-exec-run"
     return -1
}
# The test proper.  INFTTY_MODE determines whether "set inferior-tty"
# is in effect.  MI_MODE determines whether MI is run on the main UI,
# or as a separate UI.  FORCE_FAIL is true when we want -exec-run to
# fail and cause inferior output be sent to the inferior tty.
proc test {inftty_mode mi_mode force_fail} {
    global srcdir subdir binfile srcfile
    global gdb_spawn_id gdb_main_spawn_id mi_spawn_id inferior_spawn_id
    global decimal
    mi_gdb_exit
    set start_ops {}
    if {$inftty_mode == "separate"} {
	lappend start_ops "separate-inferior-tty"
    }
    if {$mi_mode == "separate"} {
	lappend start_ops "separate-mi-tty"
    }
    if [eval mi_gdb_start $start_ops] {
	return
    }
    if {$force_fail} {
	# Disable the shell so that its the first exec that fails,
	# instead of the shell starting and then failing with some
	# unspecified output.
	mi_gdb_test "-gdb-set startup-with-shell off" ".*"
	set bin $binfile.nox
    } else {
	set bin $binfile
    }
    mi_delete_breakpoints
    mi_gdb_reinitialize_dir $srcdir/$subdir
    mi_gdb_reinitialize_dir $srcdir/$subdir
    mi_gdb_load ${bin}
    # Useful for debugging:
    verbose -log "Channels:"
    verbose -log " inferior_spawn_id=$inferior_spawn_id"
    verbose -log " gdb_spawn_id=$gdb_spawn_id"
    verbose -log " gdb_main_spawn_id=$gdb_main_spawn_id"
    verbose -log " mi_spawn_id=$mi_spawn_id"
    if {$force_fail} {
	set saw_perm_error 0
	set saw_mi_error 0
	set test "run failure detected"
	send_gdb "-exec-run --start\n"
	while {1} {
	    gdb_expect {
		-i "$inferior_spawn_id"
		-re ".*Cannot exec.*Permission denied" {
		    set saw_perm_error 1
		    verbose -log "saw mi error"
		}
		-i "$gdb_spawn_id"
		-re "\\^error,msg=\"During startup program exited with code 127" {
		    set saw_mi_error 1
		    verbose -log "saw mi error"
		}
		timeout {
		    fail "$test (timeout)"
		    break
		}
		-i "$gdb_main_spawn_id"
		eof {
		    fail "$test (eof)"
		    break
		}
	    }
	    if {$saw_perm_error && $saw_mi_error} {
		pass $test
		break
	    }
	}
    } else {
	mi_run_cmd "--start"
	mi_expect_stop "breakpoint-hit" "main" "" ".*$srcfile" "$decimal" \
	    { "" "disp=\"del\"" } "breakpoint hit reported on mi"
	if {$mi_mode == "separate"} {
	    # Check that the breakpoint hit is reported on the main
	    # UI/CLI.  Note no prompt is expected.
	    switch_gdb_spawn_id $gdb_main_spawn_id
	    set test "breakpoint hit reported on console"
	    gdb_test_multiple "" $test {
		-re "Temporary breakpoint .*, main \\(\\) at .*$srcfile:$decimal.*return 0;" {
		    pass $test
		}
	    }
	    # Switch back to the MI UI.
	    global mi_spawn_id
	    switch_gdb_spawn_id $mi_spawn_id
	}
    }
}
# Create a not-executable copy of the program, in order to exercise
# vfork->exec failing.
gdb_remote_download host $binfile $binfile.nox
remote_spawn target "chmod \"a-x\" $binfile.nox"
foreach_with_prefix inferior-tty {"main" "separate"} {
    foreach_with_prefix mi {"main" "separate"} {
	foreach_with_prefix force-fail {0 1} {
	    test ${inferior-tty} ${mi} ${force-fail}
	}
    }
}
 |