package prefer latest

package require nx::test

set ::tcl86 [package vsatisfies [package req Tcl] 8.6-]

nx::test case nsf-method-get-variants {

  #
  # Create a simple class
  #
  nx::Class create Person {
    :property name
    :public method foo {x:integer} {return foo-$x}
    :public method "string match" {pattern string} {return string-match-$string}
    :create p1
  }

  #
  # A plain method
  #
  set ::handle [p1 info lookup method foo]

  ? {nsf::cmd::info args $::handle} x
  ? {nsf::cmd::info body $::handle} {return foo-$x}
  ? {nsf::cmd::info definition $::handle} {::Person public method foo x:integer {return foo-$x}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ::nsf::classes::Person::foo
  ? {nsf::cmd::info definitionhandle $::handle} ::nsf::classes::Person::foo
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} x:integer
  ? {nsf::cmd::info syntax $::handle} "/x/"
  ? {nsf::cmd::info type $::handle} scripted
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # An ensemble method
  #
  set ::handle [p1 info lookup method "string match"]

  ? {nsf::cmd::info args $::handle} "pattern string"
  ? {nsf::cmd::info body $::handle} {return string-match-$string}
  ? {nsf::cmd::info definition $::handle} {::Person public method {string match} {pattern string} {return string-match-$string}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} "::nsf::classes::Person::string match"
  ? {nsf::cmd::info definitionhandle $::handle} "::Person::slot::__string::match"
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "pattern string"
  ? {nsf::cmd::info syntax $::handle} "/pattern/ /string/"
  ? {nsf::cmd::info type $::handle} scripted
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  # alternative string reps for pattern list
  foreach char {\t \n \r \f \v} {
    ? [list p1 info lookup method "string${char}match"] [join [list {*}$::handle] $char]
  }

  #
  # An C-defined method inherited from nx::Object
  #
  set ::handle [p1 info lookup method configure]

  ? {nsf::cmd::info args $::handle} args
  ? {nsf::cmd::info body $::handle} ""
  ? {nsf::cmd::info definition $::handle} "::nx::Object public alias configure ::nsf::methods::object::configure"
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ::nsf::classes::nx::Object::configure
  ? {nsf::cmd::info definitionhandle $::handle} ::nsf::classes::nx::Object::configure
  ? {nsf::cmd::info origin $::handle} ::nsf::methods::object::configure
  ? {nsf::cmd::info parameter $::handle} args:virtualobjectargs
  ? {nsf::cmd::info syntax $::handle} "?/arg .../?"
  ? {nsf::cmd::info type $::handle} alias
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # An undefined method
  #
  set ::handle [p1 info lookup method exists]

  ? {nsf::cmd::info args $::handle} ""
  ? {nsf::cmd::info body $::handle} ""
  ? {nsf::cmd::info definition $::handle} ""
  ? {nsf::cmd::info exists $::handle} 0
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} ""
  ? {nsf::cmd::info syntax $::handle} ""
  ? {nsf::cmd::info type $::handle} ""
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # Define 2 nsf::procs: one, which requires the nsf argument parser,
  # and one, which does not.
  #
  nsf::proc ::foo {{-x 1} y:optional} {return $x-$y}
  nsf::proc ::bar {a b} {return $a-$b}

  #
  # An nsf::proc requiring nsf argument parser
  #
  set ::handle ::foo

  ? {nsf::cmd::info args $::handle} "x y"
  ? {nsf::cmd::info body $::handle} {return $x-$y}
  ? {nsf::cmd::info definition $::handle} {::nsf::proc ::foo {{-x 1} y:optional} {return $x-$y}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "{-x 1} y:optional"
  ? {nsf::cmd::info syntax $::handle} {?-x /value/? ?/y/?}
  ? {nsf::cmd::info type $::handle} "nsfproc"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # define a nsf::proc with "-debug" and "-deprecated"
  #
  nsf::proc -deprecated -debug ::baz {{-x 1} y:optional} {return $x-$y}

  ? {nsf::cmd::info definition ::baz} {::nsf::proc -debug -deprecated ::baz {{-x 1} y:optional} {return $x-$y}}

  #
  # A simple Tcl proc
  #
  set ::handle ::bar

  ? {nsf::cmd::info args $::handle} "a b"
  ? {nsf::cmd::info body $::handle} {return $a-$b}
  ? {nsf::cmd::info definition $::handle} {::proc ::bar {a b} {return $a-$b}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "a b"
  ? {nsf::cmd::info syntax $::handle} {/a/ /b/}
  ? {nsf::cmd::info type $::handle} "proc"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""
  ? {nsf::method::property ::nx::Object $handle debug 1} 1
  ? {bar a b} "a-b"

  #
  # redefine "bar" with debug flag
  #
  nsf::proc -debug bar {a b} {return $a-$b}
  set ::handle ::bar

  ? {nsf::cmd::info args $::handle} "a b"
  ? {nsf::cmd::info body $::handle} {return $a-$b}
  ? {nsf::cmd::info definition $::handle} {::nsf::proc -debug ::bar {a b} {return $a-$b}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "a b"
  ? {nsf::cmd::info syntax $::handle} {/a/ /b/}
  ? {nsf::cmd::info type $::handle} "nsfproc"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""
  ? {nsf::method::property ::nx::Object $handle debug 1} 1
  ? {bar a b} "a-b"

  #
  # redefine "foo" with "-returns" checker.
  #
  nsf::proc ::foo {{-x 1} y:optional} -returns integer {return $y}

  set ::handle ::foo

  ? {nsf::cmd::info args $::handle} "x y"
  ? {nsf::cmd::info body $::handle} {return $y}
  ? {nsf::cmd::info definition $::handle} {::nsf::proc ::foo {{-x 1} y:optional} -returns integer {return $y}}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "{-x 1} y:optional"
  ? {nsf::cmd::info syntax $::handle} {?-x /value/? ?/y/?}
  ? {nsf::cmd::info type $::handle} "nsfproc"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} "integer"

  #
  # A Tcl cmd implemented in C
  #
  set ::handle ::set

  ? {nsf::cmd::info args $::handle} "could not obtain parameter definition for method 'set'"
  ? {nsf::cmd::info body $::handle} {}
  ? {nsf::cmd::info definition $::handle} {}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "could not obtain parameter definition for method 'set'"
  ? {nsf::cmd::info syntax $::handle} "could not obtain parameter definition for method 'set'"
  ? {nsf::cmd::info type $::handle} "cmd"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # A Tcl cmd implemented in C with the nsf infrastructure (with parameter definitions)
  #
  set ::handle ::nsf::cmd::info

  ? {nsf::cmd::info args $::handle} "subcmd -context methodName pattern"
  ? {nsf::cmd::info body $::handle} {}
  ? {nsf::cmd::info definition $::handle} {}
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} "subcmd -context:object methodName pattern:optional"
  ? {nsf::cmd::info syntax $::handle} "args|body|definition|exists|registrationhandle|definitionhandle|origin|parameter|syntax|type|precondition|postcondition|submethods|returns|disassemble ?-context /object/? /methodName/ ?/pattern/?"
  ? {nsf::cmd::info type $::handle} "cmd"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # A plain NX object
  #
  set ::handle [nx::Object new]

  ? {nsf::cmd::info args $::handle} ""
  ? {nsf::cmd::info body $::handle} ""
  ? {nsf::cmd::info definition $::handle} ""
  ? {nsf::cmd::info exists $::handle} 0
  ? {nsf::cmd::info registrationhandle $::handle} ""
  ? {nsf::cmd::info definitionhandle $::handle} ""
  ? {nsf::cmd::info origin $::handle} ""
  ? {nsf::cmd::info parameter $::handle} ""
  ? {nsf::cmd::info syntax $::handle} ""
  ? {nsf::cmd::info type $::handle} "cmd"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} ""
  ? {nsf::cmd::info returns $::handle} ""

  #
  # A method handle for an ensemble
  #
  set ::handle [nx::Object info method registrationhandle "info"]

  ? {nsf::cmd::info args $::handle} ""
  ? {nsf::cmd::info body $::handle} ""
  ? {nsf::cmd::info definition $::handle} "::nx::Object public alias info ::nx::Object::slot::__info"
  ? {nsf::cmd::info exists $::handle} 1
  ? {nsf::cmd::info registrationhandle $::handle} $::handle
  ? {nsf::cmd::info definitionhandle $::handle} $::handle
  ? {nsf::cmd::info origin $::handle} "::nx::Object::slot::__info"
  ? {nsf::cmd::info parameter $::handle} ""
  ? {nsf::cmd::info syntax $::handle} ""
  ? {nsf::cmd::info type $::handle} "alias"
  ? {nsf::cmd::info precondition $::handle} ""
  ? {nsf::cmd::info postcondition $::handle} ""
  ? {nsf::cmd::info submethods $::handle} [nx::Object info method submethods info]
  ? {nsf::cmd::info returns $::handle} ""

}

nx::test case nsf-method-property {
  ? {::nsf::object::exists ::TestMe} 0
  ? {::nsf::method::property ::TestMe missing call-protected true} \
      {expected object but got "::TestMe" for parameter "object"}
  ? {::nsf::method::forward::property ::TestMe missing verbose true} \
      {expected object but got "::TestMe" for parameter "object"}

  nx::Class create ::TestMe

  ? {::nsf::method::property ::TestMe -per-object missing call-protected true} \
      {cannot lookup object method 'missing' for ::TestMe}
  ? {::nsf::method::property ::TestMe missing call-protected true} \
      {cannot lookup method 'missing' for ::TestMe}
  ? {::nsf::method::forward::property ::TestMe -per-object missing verbose true} \
      {cannot lookup object method 'missing' for ::TestMe}
  ? {::nsf::method::forward::property ::TestMe missing verbose true} \
      {cannot lookup method 'missing' for ::TestMe}

}

#
# test error transparency of "-debug" option
#
nx::test case nsf-debug-error {
  nsf::proc foo {} {
    set exception [catch {bar} errorMsg options]
    if {$exception} {
      puts stderr O=$options
      puts stderr <<$::errorInfo>>
      set result [list $exception $errorMsg [string length $::errorInfo] $::errorCode]
    } else {
      set result ""
    }
    return $result
  }
  nsf::proc bar {} {return -code error -errorcode MyException "exception"}

  ? {foo} {1 exception 35 MyException}

  #
  # redefine bar with debug flag
  #
  nsf::proc -debug bar {} {return -code error -errorcode MyException "exception"}

  ? {foo} {1 exception 35 MyException}
}


#
# test virtual arg resolution + filtering
#
nx::test case nsf-method-get-variants {

  nx::Class create Person {
    :property name
    :create p1
  }

  set ::handle1 [p1     info lookup method configure]
  set ::handle2 [Person info lookup method create]
  set ::handle3 [Person info lookup method new]

  #
  # configure
  #
  ? {nsf::cmd::info syntax -context p1 $::handle1} \
      "?-name /value/? ?-object-mixins /mixinreg .../? ?-object-filters /filterreg .../? ?-class /class/? ?/__initblock/?"

  ? {nsf::cmd::info parameter -context p1 $::handle1} \
      "-name -object-mixins:mixinreg,slot=::nx::Object::slot::object-mixins,slotset,method=object-mixin,0..n -object-filters:filterreg,slot=::nx::Object::slot::object-filters,slotset,method=object-filter,0..n -class:class,alias,method=::nsf::methods::object::class __initblock:cmd,optional,nodashalnum"

  ? {nsf::cmd::info args -context p1 $::handle1} \
      "name object-mixins object-filters class __initblock"

  #
  # filter on (virtual) arguments
  #
  ? {nsf::cmd::info parameter -context p1 $::handle1 na*} "-name"
  ? {nsf::cmd::info args      -context p1 $::handle1 na*} "name"
  ? {nsf::cmd::info syntax    -context p1 $::handle1 na*} "?-name /value/?"

  ? {nsf::cmd::info parameter -context p1 $::handle1 *a*} "-name -class:class,alias,method=::nsf::methods::object::class"
  ? {nsf::cmd::info args      -context p1 $::handle1 *a*} "name class"
  ? {nsf::cmd::info syntax    -context p1 $::handle1 *a*} "?-name /value/? ?-class /class/?"


  #
  # create
  #
  ? {nsf::cmd::info syntax -context Person $::handle2} \
      "/objectName/ ?-name /value/? ?-object-mixins /mixinreg .../? ?-object-filters /filterreg .../? ?-class /class/? ?/__initblock/?"

  ? {nsf::cmd::info parameter -context Person $::handle2} \
      "objectName -name -object-mixins:mixinreg,slot=::nx::Object::slot::object-mixins,slotset,method=object-mixin,0..n -object-filters:filterreg,slot=::nx::Object::slot::object-filters,slotset,method=object-filter,0..n -class:class,alias,method=::nsf::methods::object::class __initblock:cmd,optional,nodashalnum"

  ? {nsf::cmd::info args -context Person $::handle2} \
      "objectName name object-mixins object-filters class __initblock"


  #
  # new
  #
  ? {nsf::cmd::info syntax -context Person $::handle3} \
      "?-childof /value/? ?-name /value/? ?-object-mixins /mixinreg .../? ?-object-filters /filterreg .../? ?-class /class/? ?/__initblock/?"
  ? {nsf::cmd::info parameter -context Person $::handle3} \
      "-childof -name -object-mixins:mixinreg,slot=::nx::Object::slot::object-mixins,slotset,method=object-mixin,0..n -object-filters:filterreg,slot=::nx::Object::slot::object-filters,slotset,method=object-filter,0..n -class:class,alias,method=::nsf::methods::object::class __initblock:cmd,optional,nodashalnum"
  ? {nsf::cmd::info args -context Person $::handle3} \
      "-childof name object-mixins object-filters class __initblock"

  #
  # filter on (virtual) arguments
  #
  ? {nsf::cmd::info parameter -context Person $::handle3 na*} "-name"
  ? {nsf::cmd::info args      -context Person $::handle3 na*} "name"
  ? {nsf::cmd::info syntax    -context Person $::handle3 na*} "?-name /value/?"

  ? {nsf::cmd::info parameter -context Person $::handle3 *a*} "-name -class:class,alias,method=::nsf::methods::object::class"
  ? {nsf::cmd::info args      -context Person $::handle3 *a*} "name class"
  ? {nsf::cmd::info syntax    -context Person $::handle3 *a*} "?-name /value/? ?-class /class/?"

  ? {nsf::cmd::info args      -context Person $::handle3 *il*} "-childof object-filters"


  #
  # Queries without context
  #
  ? {nsf::cmd::info parameter $::handle1} args:virtualobjectargs
  ? {nsf::cmd::info parameter $::handle2} "objectName args:virtualclassargs"
  ? {nsf::cmd::info parameter $::handle3} "-childof args:virtualclassargs"


  #
  # Test cases, where no instance was created yet (no internally
  # cached parameters)
  #

  nx::Class create Student { :property matnr }

  set ::handle4 [Student info lookup method create]

  ? {nsf::cmd::info syntax -context Student $::handle4} \
      "/objectName/ ?-matnr /value/? ?-object-mixins /mixinreg .../? ?-object-filters /filterreg .../? ?-class /class/? ?/__initblock/?"
}

nx::test case nsf-config-array {
  ? {array exists ::nsf::config} 1
  set opts [list development memcount memtrace profile dtrace assertions]
  foreach opt $opts {
    ? [list info exists ::nsf::config($opt)] 1
    ? [list string is boolean $::nsf::config($opt)] 1
  }
}

#
# recursive debug calls
#
nx::test case nsf-debug-recursive {
  set ::count 0

  set oldCall [nsf::cmd::info definition ::nsf::debug::call]
  nsf::proc -debug ::nsf::debug::call args {
    incr ::count
    #puts "MYDEBUG $args"
  }
  nsf::proc -debug foo {} {return 1}

  ? {foo} "1"
  ? {set ::count} 1

  # restore original definition of ::nsf::debug::call
  eval $oldCall
}

#
# recursive log calls
#
nx::test case nsf-log-recursive {

  #
  # First the case, where the log function calls another Tcl function
  # (which might be debugged)
  #
  set oldCall [nsf::cmd::info definition ::nsf::log]
  nsf::proc ::nsf::log args {
    incr ::count
    #puts "::nsf::log <$args> ... before foo"
    foo
    #puts "::nsf::log <$args> ... after foo"
    return
  }
  nsf::proc foo {} {return 1}
  nsf::proc bar {} {nsf::log notice hello}

  #
  # "foo" calls no nsf::log, but "bar" calls it once
  #
  set ::count 0
  ? {foo} "1"
  ? {set ::count} 0

  set ::count 0
  ? {bar} ""
  ? {set ::count} 1

  #
  # now we add the debug flag to foo, therefore, "foo" will call
  # "nsf::log", which might become an infinite recursion loop.
  #
  nsf::proc -debug foo {} {return 1}

  #
  # "foo" is has now "-debug" set, therefore, it calls the log function
  #
  set ::count 0
  ? {foo} "1"
  ? {set ::count} 2

  #
  # "bar" calls "log", which in turn calls a debugged function
  #
  set ::count 0
  ? {bar} ""
  ? {set ::count} 3

  # restore original definition of ::nsf::log
  eval $oldCall

}

nx::test case nsf-proc-rename-delete {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }
  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"

  ? {::ns1::foo -x ok} "1-ok"

  rename ::ns1::foo ""

  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  namespace eval ::ns1 {}
}

nx::test case nsf-proc-ns-delete {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }
  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"

  ? {::ns1::foo -x ok} "1-ok"

  namespace delete ::ns1

  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

}

nx::test case nsf-proc-rename-redefine {
  namespace eval ::ns1 {}

  nsf::proc ns1::foo {
    {-x:required}
  } { return 1-$x }

  ? {ns1::foo -x ok} 1-ok

  rename ns1::foo ns1::foo.orig

  nsf::proc ns1::foo {
    {-x:required}
  } { return 2-$x }

  ? {ns1::foo -x ok} 2-ok

  namespace delete ::ns1
}

nx::test case nsf-proc-rename-redefine-call {
  namespace eval ::ns1 {}

  nsf::proc ns1::foo {
    {-x:required}
  } { return 1-$x }

  ? {ns1::foo -x ok} 1-ok

  rename ns1::foo ns1::foo.orig

  nsf::proc ns1::foo {
    {-x:required}
  } { return 2-$x }

  ? {ns1::foo -x ok} 2-ok

  ? {ns1::foo.orig -x ok} 1-ok;

  namespace delete ::ns1
}

nx::test case nsf-proc-backstage-rename {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }
  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"

  ? {::ns1::foo -x ok} "1-ok"

  rename ::nsf::procs::ns1::foo ""

  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  ? {::ns1::foo -x ok} {cannot lookup command '::nsf::procs::ns1::foo'}

  rename ::ns1::foo ""

  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  namespace eval ::ns1 {}
}

nx::test case nsf-proc-backstage-rename-2 {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }
  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"

  ? {::ns1::foo -x ok} "1-ok"

  rename ::nsf::procs::ns1::foo ""
  nx::Object create ::nsf::procs::ns1::foo

  ? {info commands ::ns1::foo} "::ns1::foo"
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""

  ? {::ns1::foo -x ok} \
      {command '::nsf::procs::ns1::foo' is not a proc}

  rename ::ns1::foo ""

  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"
  ? {info procs ::ns1::foo} ""
  ? {info procs ::nsf::procs::ns1::foo} ""


  if {${::tcl86}} {
    ? {::ns1::foo -x ok} {TCL LOOKUP COMMAND ::ns1::foo} {invalid command name "::ns1::foo"}
  } else {
    ? {::ns1::foo -x ok} {invalid command name "::ns1::foo"}
  }

  namespace eval ::ns1 {}
  rename ::nsf::procs::ns1::foo ""
}

nx::test case nsf-proc-preexisting {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""

  proc ::nsf::procs::ns1::foo {x} { return 0-$x}

  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} "::nsf::procs::ns1::foo"

  ? {nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }} ""

  ? {::ns1::foo -x ok} "1-ok"

  namespace delete ::ns1
}

nx::test case nsf-proc-preexisting-rename {
  namespace eval ::ns1 {}
  ? {info commands ::ns1::foo} ""
  ? {info commands ::nsf::procs::ns1::foo} ""

  proc ::nsf::procs::ns1::foo.orig {x} { return 0-$x}

  ? {info commands ::ns1::foo.orig} ""
  ? {info commands ::nsf::procs::ns1::foo.orig} "::nsf::procs::ns1::foo.orig"

  ? {nsf::proc ::ns1::foo {
    {-x:required}
  } { return 1-$x }} ""

  ? {::ns1::foo -x ok} "1-ok"

    if {${::tcl86}} {
      ? {rename ns1::foo ns1::foo.orig} {TCL OPERATION RENAME TARGET_EXISTS} {can't rename to "::nsf::procs::ns1::foo.orig": command already exists}
  } else {
    ? {rename ns1::foo ns1::foo.orig} {can't rename to "::nsf::procs::ns1::foo.orig": command already exists}
  }


  namespace delete ::ns1
}

nx::test case switch-info {
  namespace eval ::ns1 {}
  set handle ::n1::foo

  set params [list -p1:boolean -p2:switch args]
  set def [list ::nsf::proc $handle $params return]
  {*}$def

  ? [list nsf::cmd::info args $handle] "p1 p2 args"
  ? [list nsf::cmd::info definition $handle] $def
  ? [list nsf::cmd::info exists $handle] 1
  ? [list nsf::cmd::info parameter $handle] $params
  ? [list nsf::cmd::info syntax $handle] "?-p1 /boolean/? ?-p2? ?/arg .../?"
  
  namespace delete ::ns1
}


# - TO-DO: interp hide/expose


#
# Local variables:
#    mode: tcl
#    tcl-indent-level: 2
#    indent-tabs-mode: nil
# End: