source [file dirname [info script]]/testing.tcl

needs cmd xtrace

# Simply accumulate the callback args in the list ::lines
proc xtracetest {args} {
	lappend ::lines $args
}

proc xtracesummary {lines} {
	# Omit the last line that will always be xtrace {}
	# Remove file and line
	lmap line [lrange $lines 0 end-1] {
		lassign $line type file line result cmd arglist
		list $type ($result) $cmd $arglist
	}
}

proc xtracetestproc {a} {
	append a " world"
	return $a
}

test xtrace-1.1 {xtrace usage} -body {
	xtrace
} -returnCodes error -result {wrong # args: should be "xtrace callback"}

test xtrace-1.2 {xtrace non-proc} -body {
	set lines {}
	xtrace xtracetest
	set x 3
	xtrace {}
	xtracesummary $lines
} -result {{cmd () set {x 3}}}

# This will produce 4 calls to the trace callback
# 1. xtracetestproc hello (cmd)
# 2. xtracetestproc hello (proc - when executing the proc body)
# 3. append a " hello"
# 4. return "hello world" (previous command result will be "hello world")
test xtrace-1.3 {xtrace proc} -body {
	set lines {}
	xtrace xtracetest
	xtracetestproc hello
	xtrace {}
	xtracesummary $lines
} -result {{cmd () xtracetestproc hello} {proc () xtracetestproc hello} {cmd () append {a { world}}} {cmd {(hello world)} return {{hello world}}}}

test xtrace-1.4 {xtrace line numbers} -body {
	set lines {}
	xtrace xtracetest
	set x abc
	xtrace {}
	# Now the first callback should happen at the correct line number
	lassign [lindex $lines 0] - tracefile traceline
	lassign [info source $x] file line
	if {"$tracefile:$traceline" eq "$file:$line"} {
		function ok
	}
} -result {ok}

testreport
