###############################################################################
#
# namespace-inscope.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 namespace-99.1 {namespace eval/inscope with info level} -body {
  list [namespace eval :: {info level}] [namespace inscope :: {info level}]
} -constraints {namespaces} -result {1 1}}

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

runTest {test namespace-99.2 {namespace inscope without proc} -body {
  namespace inscope :: { return [list [info level] [info level [info level]]] }
} -constraints {namespaces tcl85Feature} -result {1 {namespace\
inscope :: { return [list [info level] [info level [info level]]] }}}}

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

runTest {test namespace-99.3 {namespace inscope with proc} -setup {
  proc {foo bar} { args } {return [info level [info level]]}
} -body {
  list [namespace inscope :: {{foo bar}} "this is the test." \
      {where is the test?} \\ \{ \}] [namespace inscope :: {{foo bar}}]
} -cleanup {
  rename {foo bar} ""
} -result \
{{{foo bar} {this is the test.} {where is the test?} \\ \{ \}} {{foo bar}}}}

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

runTest {test namespace-99.4 {namespace qualifiers} -body {
  list [namespace qualifiers ""] \
      [namespace qualifiers ::] \
      [namespace qualifiers foo] \
      [namespace qualifiers foo::] \
      [namespace qualifiers foo::bar] \
      [namespace qualifiers ::foo::bar] \
      [namespace qualifiers foo::bar::splog] \
      [namespace qualifiers ::foo::bar::splog]
} -result {{} {} {} foo foo ::foo foo::bar ::foo::bar}}

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

runTest {test namespace-99.5 {namespace tail} -body {
  list [namespace tail ""] \
      [namespace tail ::] \
      [namespace tail foo] \
      [namespace tail foo::] \
      [namespace tail foo::bar] \
      [namespace tail ::foo::bar] \
      [namespace tail foo::bar::splog] \
      [namespace tail ::foo::bar::splog]
} -result {{} {} foo {} bar bar splog splog}}

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

runTest {test namespace-99.6.1 {namespace which errors} -setup {
  unset -nocomplain msg
} -body {
  list [catch {namespace which} msg] $msg \
      [catch {namespace which -doesNotExist} msg] $msg \
      [catch {namespace which -doesNotExist set} msg] $msg \
      [catch {namespace which -command -variable ""} msg] $msg \
      [catch {namespace which doesNotExist doesNotExist} msg] $msg
} -cleanup {
  unset -nocomplain msg
} -constraints {tcl tcl84} -result \
{1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}}

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

runTest {test namespace-99.6.2 {namespace which errors} -setup {
  unset -nocomplain msg
} -body {
  list [catch {namespace which} msg] $msg \
      [catch {namespace which -doesNotExist} msg] $msg \
      [catch {namespace which -doesNotExist set} msg] $msg \
      [catch {namespace which -command -variable ""} msg] $msg \
      [catch {namespace which doesNotExist doesNotExist} msg] $msg
} -cleanup {
  unset -nocomplain msg
} -constraints {tcl85OrHigher} -result \
{1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
0 {} 1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}}

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

runTest {test namespace-99.7.3 {namespace which errors} -setup {
  unset -nocomplain msg
} -body {
  list [catch {namespace which} msg] $msg \
      [catch {namespace which -doesNotExist} msg] $msg \
      [catch {namespace which -doesNotExist set} msg] $msg \
      [catch {namespace which -command -variable ""} msg] $msg \
      [catch {namespace which doesNotExist doesNotExist} msg] $msg
} -cleanup {
  unset -nocomplain msg
} -constraints {eagle} -result \
{1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
0 {} 1 {bad option "-doesNotExist": must be --, -command, or -variable}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}\
1 {wrong # args: should be "namespace which ?-command? ?-variable? name"}}}

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

runTest {test namespace-99.7 {namespace which -command} -body {
  list [namespace which -command ""] \
      [namespace which -command ::] \
      [namespace which -command set] \
      [namespace which -command ::set] \
      [namespace which -command doesNotExist] \
      [namespace which -command ::doesNotExist] \
      [namespace which -command doesNotExist::doesNotExist] \
      [namespace which -command ::doesNotExist::doesNotExist]
} -result {{} {} ::set ::set {} {} {} {}}}

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

runTest {test namespace-99.8 {namespace which -variable} -setup {
  unset -nocomplain ""; # NOTE: Make sure any empty string variable is gone.
} -body {
  list [namespace which -variable ""] \
      [namespace which -variable ::] \
      [namespace which -variable tcl_platform] \
      [namespace which -variable ::tcl_platform] \
      [namespace which -variable doesNotExist] \
      [namespace which -variable ::doesNotExist] \
      [namespace which -variable doesNotExist::doesNotExist] \
      [namespace which -variable ::doesNotExist::doesNotExist]
} -result {{} {} ::tcl_platform ::tcl_platform {} {} {} {}}}

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

runTest {test namespace-99.9 {current proc namespace} -setup {
  namespace eval ::foo {
    proc bar {} {
      return [namespace current]
    }
  }
} -body {
  ::foo::bar
} -cleanup {
  catch {namespace delete ::foo}
} -constraints {namespaces} -result {::foo}}

###############################################################################
#
# NOTE: The following tests verify the behavior of both native Tcl and Eagle
#       in how the "creative writing problem" is dealt with.
#
#       To summarize: the creative reading/writing problem involves using a
#       variable while inside a [namespace eval] or similar construct that
#       does not exist within that namespace, which causes it to "fallback"
#       to reading or writing a global variable that just so happens to have
#       the same name.
#
#       All recent versions of native Tcl implement this behavior.  The Tcl
#       wiki page "http://wiki.tcl.tk/1030" (Dangers of creative writing)
#       has more information and commentary on this issue.
#
#       In Eagle, a global variable cannot be used from within a namespace
#       context without help from the global command or global "::" prefix.
#       When trying to understand these behavioral differences, it can be
#       useful to think of this behavior as being similar to how a script
#       procedure makes use of global variables.
#
###############################################################################

runTest {test namespace-100.1.1 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.1.1 {
    set x
  }
} -cleanup {
  catch {namespace delete namespace-100.1.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {1}}

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

runTest {test namespace-100.1.2 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.1.2 {
    set x
  }
} -cleanup {
  catch {namespace delete namespace-100.1.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -returnCodes 1 -result \
{can't read "x": no such variable}}

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

runTest {test namespace-100.2.1 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.2.1 {
    global x; set x
  }
} -cleanup {
  catch {namespace delete namespace-100.2.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {1}}

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

runTest {test namespace-100.2.2 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.2.2 {
    global x; set x
  }
} -cleanup {
  catch {namespace delete namespace-100.2.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {1}}

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

runTest {test namespace-100.3.1 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.3.1 {
    set ::x
  }
} -cleanup {
  catch {namespace delete namespace-100.3.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {1}}

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

runTest {test namespace-100.3.2 {creative reading existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.3.2 {
    set ::x
  }
} -cleanup {
  catch {namespace delete namespace-100.3.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {1}}

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

runTest {test namespace-100.4.1 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.4.1 {
    set x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.4.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -returnCodes 1 -result \
{can't read "x": no such variable}}

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

runTest {test namespace-100.4.2 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.4.2 {
    set x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.4.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -returnCodes 1 -result \
{can't read "x": no such variable}}

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

runTest {test namespace-100.5.1 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.5.1 {
    global x; set x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.5.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -returnCodes 1 -result \
{can't read "x": no such variable}}

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

runTest {test namespace-100.5.2 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.5.2 {
    global x; set x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.5.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {1}}

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

runTest {test namespace-100.6.1 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.6.1 {
    set ::x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.6.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {1}}

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

runTest {test namespace-100.6.2 {creative writing non-existing global} -setup {
  unset -nocomplain x
} -body {
  namespace eval namespace-100.6.2 {
    set ::x 1
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.6.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {1}}

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

runTest {test namespace-100.7.1 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.7.1 {
    set x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.7.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {2}}

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

runTest {test namespace-100.7.2 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.7.2 {
    set x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.7.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {1}}

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

runTest {test namespace-100.8.1 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.8.1 {
    global x; set x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.8.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {2}}

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

runTest {test namespace-100.8.2 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.8.2 {
    global x; set x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.8.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {2}}

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

runTest {test namespace-100.9.1 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.9.1 {
    set ::x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.9.1}

  unset -nocomplain x
} -constraints {tcl namespaces} -result {2}}

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

runTest {test namespace-100.9.2 {creative writing existing global} -setup {
  unset -nocomplain x
} -body {
  set x 1
  namespace eval namespace-100.9.2 {
    set ::x 2
  }
  set x
} -cleanup {
  catch {namespace delete namespace-100.9.2}

  unset -nocomplain x
} -constraints {eagle namespaces} -result {2}}

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

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