###############################################################################
#
# debug.eagle --
#
# Extensible Adaptable Generalized Logic Engine (Eagle)
#
# Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: $
#
###############################################################################

source [file join [file normalize [file dirname [info script]]] prologue.eagle]

###############################################################################

runTest {test debug-1.1 {non-interactive loop entry} -setup {
  set interp [object invoke Interpreter GetActive]
  set interactive [object invoke $interp Interactive]

  object invoke $interp Interactive false

  proc foo {} { global x; set x 1; incr x; testDebugBreak; return $x }
} -body {
  foo
} -cleanup {
  if {[llength [info procs foo]] == 1} then {rename foo ""}

  object invoke $interp Interactive $interactive

  unset -nocomplain x interactive interp
} -constraints {eagle compile.DEBUGGER scriptDebugger} -returnCodes 1 -result \
{cannot break into interactive loop}}

###############################################################################

runTest {test debug-1.2 {debug halt} -body {
  debug halt
} -constraints {eagle} -noHalt true -returnCodes 1 \
-result {halted}}

###############################################################################

runTest {test debug-1.3 {custom shell argument callback} -setup {
  unset -nocomplain results
  set i [interp create -debug]

  if {[haveConstraint quiet]} then {
    object invoke Eagle._Tests.Default TestSetQuiet $i true
  }
} -body {
  set result null
  set code [object invoke Eagle._Tests.Default TestShellMainCore $i \
      [set args [object create StringList -one -postInitialize foo]] \
      true true result]

  lappend results $code [object invoke $result ToString]

  set result null
  set code [object invoke Eagle._Tests.Default TestShellMainCore $i \
      [set args [object create StringList -one -postInitialize "set x {}" \
      -two]] true true result]

  lappend results $code [object invoke $result ToString]

  set result null
  set code [object invoke Eagle._Tests.Default TestShellMainCore $i \
      [set args [object create StringList -one -two test1 -three]] \
      true true result]

  lappend results $code [object invoke $result ToString]

  set result null
  set code [object invoke Eagle._Tests.Default TestShellMainCore $i \
      [set args [object create StringList -one -two test2 -foo]] \
      true true result]

  lappend results $code [object invoke $result ToString]

  set result null
  set code [object invoke Eagle._Tests.Default TestShellMainCore $i \
      [set args [object create StringList -postInitialize \
      "debug icommand exit; set x 1"]] true true result]

  lappend results $code [object invoke $result ToString]

  set results
} -cleanup {
  catch {interp delete $i}
  unset -nocomplain results args result code i
} -constraints {eagle compile.TEST Eagle._Tests.Default.TestShellMainCore\
Eagle._Tests.Default.TestSetQuiet} -result {Failure\
{invalid command name "foo"} Failure {wrong # args: should be "-two <value>"|}\
Failure {argument one OK|argument two "test1" OK|argument three ERROR|} Failure\
{argument one OK|argument two "test2" OK|invalid test argument "foo"|} Success\
1}}

###############################################################################

runTest {test debug-1.4 {debug text writer} -setup {
  set savedDebugTextWriter \
    [object invoke Interpreter.GetActive DebugTextWriter]

  if {[string length $savedDebugTextWriter] == 0} then {
    set savedDebugTextWriter null; # NOTE: Must be object.
  }

  object import System.IO; # StreamWriter
} -body {
  set fileName [file join [getTemporaryPath] [file tail \
      [info nameofexecutable]][getTestLogId].complaint.[pid].log]

  set textWriter [object create StreamWriter $fileName]
  object invoke Interpreter.GetActive DebugTextWriter $textWriter

  object invoke -flags +NonPublic Eagle._Components.Private.DebugOps \
      Complain "" Error "test of something bad happening."

  string trim [readSharedFile $fileName]
} -cleanup {
  unset -nocomplain textWriter
  catch {file delete $fileName}
  unset -nocomplain fileName

  catch {object invoke Interpreter.GetActive DebugTextWriter \
      $savedDebugTextWriter}

  unset -nocomplain savedDebugTextWriter

  object unimport -importpattern System.IO
} -constraints [fixConstraints {eagle !quiet}] -match regexp -result \
{^-?\d+ \(\d+\): Error: test of something bad happening\.$}}

###############################################################################

runTest {test debug-1.5 {refresh cached host after argument} -setup {
  set i [interp create]
} -body {
  set script {
    #
    # NOTE: Dispose and reset the host for the created interpreter.
    #
    object invoke Interpreter.GetActive.Host Dispose
    object invoke Interpreter.GetActive Host null

    #
    # NOTE: Raise some other error, so that needs to be report
    #       something via the host.
    #
    error "fake post-initialize error"
  }

  set result null
  set code [object invoke Interpreter ShellMainCore $i null null null \
      null null null [set args [object create StringList -postInitialize \
      $script]] true true result]

  #
  # NOTE: The result should contain the fake error message, not an
  #       ObjectDisposedException error message (which would mean
  #       that the host was not refreshed after processing the
  #       post-initialize argument).
  #
  list $code [expr {[string length $result] > 0 ? \
      [object invoke $result ToString] : ""}]
} -cleanup {
  catch {interp delete $i}
  unset -nocomplain code result args script i
} -constraints {eagle} -result {Failure {fake post-initialize error}}}

###############################################################################

runTest {test debug-1.6 {debug shell sub-command w/reconfigure} -setup {
  set i [interp create -debug]
} -body {
  interp eval $i [list set fileName [file join $test_data_path settings.xml]]
  interp eval $i {
    debug shell -loop true -- -reconfigure $fileName --postInitialize \
        "debug icommand exit"
  }
} -cleanup {
  catch {interp delete $i}

  unset -nocomplain i
} -constraints \
{eagle compile.DEBUGGER compile.XML compile.SERIALIZATION file_settings.xml} \
-returnCodes 1 -result {interpreter is unusable (it may have been disposed)}}

###############################################################################

runTest {test debug-1.7 {debug shell sub-command w/reconfigure} -setup {
  set i [interp create -debug]
} -body {
  interp eval $i [list set fileName [file join $test_data_path settings.xml]]
  interp eval $i {
    debug shell -loop true -- -reconfigure $fileName --postInitialize \
        "debug icommand exit"; list true
  }
} -cleanup {
  catch {interp delete $i}

  unset -nocomplain i
} -constraints \
{eagle compile.DEBUGGER compile.XML compile.SERIALIZATION file_settings.xml} \
-returnCodes 1 -result {interpreter is unusable (it may have been disposed)}}

###############################################################################

runTest {test debug-1.8 {per-thread TraceInfo object w/watchpoint} -setup {
  set i [interp create -debug]
  interp alias $i setp {} set
  interp eval $i {
    object invoke Interpreter.GetActive Interactive true
  }
} -body {
  set x 0; catch {interp eval $i {
    set x 123
    debug watch x =BreakOnSet
    after 200 {debug icommand #go}
    after 400 {set x 456}
    after 600 {setp x $x; set forever 1}
    vwait forever
  }}; set x
} -cleanup {
  catch {interp delete $i}

  unset -nocomplain i x
} -constraints {eagle compile.DEBUGGER interactiveCommand.go} -result {456}}

###############################################################################

runTest {test debug-1.9 {per-thread TraceInfo object w/watchpoint} -setup {
  set i [interp create -debug]
  interp alias $i setp {} set
  interp eval $i {
    object invoke Interpreter.GetActive Interactive true
  }
} -body {
  set x 0; catch {interp eval $i {
    set x 123
    debug watch x =BreakOnSet
    after 200 {debug icommand {#done Error failed}}
    after 400 {set x 456}
    after 600 {setp x $x; set forever 1}
    vwait forever
  }}; set x
} -cleanup {
  catch {interp delete $i}

  unset -nocomplain i x
} -constraints {eagle compile.DEBUGGER interactiveCommand.done} -result {123}}

###############################################################################

source [file join [file normalize [file dirname [info script]]] epilogue.eagle]
