###############################################################################
#
# object2.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]

###############################################################################
# MONO: Due to a Mono bug, some tests are disabled on Mono.
#       See: https://bugzilla.novell.com/show_bug.cgi?id=471252
###############################################################################

runTest {test object-2.1 {arguments, ref, out, nested, multi array, etc} -body {
  catch {unset t1}; # input/output param
  set t1() "this is not an integer; however, it does not matter"
  set t1(0) 0x1234

  catch {unset t2}; # input/output param
  set t2() "this is not an integer; however, it does not matter"
  set t2(-1,-2) 0x999
  set t2(0,0) 0x01
  set t2(0,1) 0x02
  set t2(1,0) 0x04
  set t2(1,1) 0x08
  set t2(2,1) 0x10

  catch {unset t3}; # input/output param
  set t3() "this element will not be changed"
  set t3(0) "this element will be changed"

  catch {unset t4}; # output only param
  catch {unset t5}; # output only param
  catch {unset t6}; # output only param

  list [set o1 [object create Eagle._Tests.Default]] [set o2 [object invoke \
      $o1 TestComplexMethod 127 909 yes [expr pi()] t1 t2 t3 t4 t5 t6]] \
      [testArrayGet t1] [testArrayGet t2] [testArrayGet t3] $t4 [testArrayGet \
      t5 true] [testArrayGet t6 true] [unset o2] [object dispose $o1] [unset \
      o1] [llength [info objects]] [set o3 [object create System.Int32]] \
      [object invoke -membertypes {-Method -Property} -flags {+NonPublic \
      -Public -Static -InvokeMethod} $o3 m_value 9999] [set o4 [object invoke \
      -create System.Int32 Parse 10101]] [set o5 [object create -nocase \
      system.int32]] [object invoke -membertypes {-Method -Property} -flags \
      {+NonPublic -Public -Static -InvokeMethod} $o5 m_value 9999] [object \
      invoke System.String Format "{0} {1} {2}" $o3 $o4 $o5] [object dispose \
      $o5] [object dispose $o4] [object dispose $o3] [llength [info objects]]
} -cleanup {
  unset -nocomplain o1 o2 o3 o4 o5 t1 t2 t3 t4 t5 t6 t6_0 t6_1 t6_2 w x y z
} -constraints {eagle compile.TEST refCount monoBug22\
Eagle._Tests.Default.TestComplexMethod} -match regexp -result {^Default#\d+\
Default#\d+ \{\{\} \{this is not an integer; however, it does not matter\} 0\
4661\} \{\{\} \{this is not an integer; however, it does not matter\} -1,-1 0\
-1,-2 (?:2457|2477) -1,0 0 -1,1 0 0,-1 0 0,-2 0 0,0 2 0,1 4 1,-1 0 1,-2 0 1,0 3\
1,1 4 2,-1 0 2,-2 0 2,0 0 2,1 37\} \{\{\} \{this element will not be changed\}\
0 \d+\} \{\d{4}\.\d{2}\.\d{2}T\d{2}:\d{2}:\d{2}\.\d{3} (?:\+|-)?\d{4}\} \{0 127\
1 909 2 True 3 3\.14159265358979\} \{0 t6_0 1 t6_1 2 t6_2\} \{\} disposed \{\}\
1 System#Int32#\d+ \{\} System#Int32#\d+ System#Int32#\d+ \{\} \{9999 10101\
9999\} removed removed removed 1$}}

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

runTest {test object-2.2 {member with char[] argument type} -body {
  list [unset -nocomplain foo] [set a [object create System.String foo]] \
      [set foo 2] [set b [object create System.String foo]]
} -cleanup {
  unset -nocomplain a b foo
} -constraints {eagle} -match regexp -result \
{^\{\} System#String#\d+ 2 System#String#\d+$}}

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

runTest {test object-2.3 {conversion of list to one-dimensional array} -setup {
  unset -nocomplain error
} -body {
  array set error {0 "" 1 "" 2 "" 3 ""}

  list [catch {object invoke -flags +NonPublic -parametertypes [list Byte\[\]] \
      Eagle._Tests.Default TestToHexadecimalString [list 1 2 3]} \
      error(0)] $error(0) [catch {object invoke Eagle._Tests.Default \
      TestMulti2Array [list 1 2 3]} error(1)] $error(1) [catch {object invoke \
      Eagle._Tests.Default TestMulti3Array [list 1 2 3]} error(2)] $error(2) \
      [catch {object invoke Eagle._Tests.Default TestNestedArray [list 1 2 3]} \
      error(3)] $error(3)
} -cleanup {
  unset -nocomplain error
} -constraints {eagle dotNet compile.TEST\
Eagle._Tests.Default.TestToHexadecimalString\
Eagle._Tests.Default.TestMulti2Array\
Eagle._Tests.Default.TestMulti3Array\
Eagle._Tests.Default.TestNestedArray} -match regexp -result \
{^0 010203 1 \{could not convert method #\d+\
"Eagle\._Tests\.Default\.TestMulti2Array" argument #0 "array" with value "1 2\
3" to type "System\.Int32\[,\]": cannot convert list to an array of rank 2\}\
1 \{could not convert method #\d+ "Eagle\._Tests\.Default\.TestMulti3Array"\
argument #0 "array" with value "1 2 3" to type "System\.Int32\[,,\]": cannot\
convert list to an array of rank 3\} 1 \{could not convert method #\d+\
"Eagle\._Tests\.Default\.TestNestedArray" argument #0 "array" with value "1 2\
3" to type "System\.Int32\[\]\[\]": variable not found in call frame\}$}}

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

if {[isEagle]} then {
  set vflags [object invoke Enum Parse VariableFlags GlobalOnly]

  if {[string first , $vflags] != -1} then {
    set vflags [appendArgs \{ $vflags \}]
  }
} else {
  set vflags ""
}

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

runTest {test object-2.4 {enumerated type output parameters} -body {
  set flags GlobalOnly; set variable null; set error null
  list [object invoke -flags +NonPublic Interpreter.GetActive GetVariable \
      null eagle_platform null flags variable error] $flags $variable $error
} -cleanup {
  unset -nocomplain flags variable error
} -constraints {eagle} -match regexp -result [string map [list <flags> \
$vflags] {^Ok <flags> Variable#\d+ \{\}$}]}

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

unset -nocomplain vflags

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

runTest {test object-2.5 {honor the -type option} -body {
  #
  # NOTE: This call will raise an error unless the -type option is honored
  #       because the console host does not have a get_Title method; however,
  #       the IInteractiveHost interface does.
  #
  object invoke -type Eagle._Interfaces.Public.IInteractiveHost \
      Interpreter.GetActive.Host Title; return success
} -constraints {eagle} -result {success}}

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

runTest {test object-2.6 {honor the -objectname/-alias options} -body {
  set x [object invoke -alias Interpreter GetActive]
  set y [object invoke -objectname interp2 -alias Interpreter GetActive]

  list [object invoke $x Id] [$x Id] [object invoke interp2 Id] [interp2 Id] \
      [expr {[object invoke $x Id] == [$x Id]}] \
      [expr {[object invoke interp2 Id] == [interp2 Id]}] \
      [expr {[object invoke $x Id] == [object invoke interp2 Id]}]
} -cleanup {
  unset -nocomplain y x
} -constraints {eagle} -match regexp -result {^\d+ \d+ \d+ \d+ True True True$}}

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

runTest {test object-2.7 {no refCount on undefined vars} -setup {
  unset -nocomplain result id; set id 0
} -body {
  set yyy [object invoke -alias Interpreter GetActive]

  lappend result [set nextId [regexp -inline -- {\d+} $yyy]]
  lappend result $yyy

  lappend result [catch {set id [$yyy Id]} msg] $msg
  unset yyy; # remove variable/object (now undefined)

  #
  # HACK: We need to make sure the internal NextId() method call used for
  #       constructing the opaque object handle results in the exact same
  #       value as the above one.  Otherwise, this test will not be testing
  #       the right thing.
  #
  incr nextId -1
  object invoke -flags +NonPublic Interpreter.GetActive nextId $nextId
  incr nextId

  set yyy [object invoke -alias Interpreter GetActive]

  lappend result $yyy
  lappend result [catch {$yyy Id} msg] $msg

  regexp -- [appendArgs ^ $nextId " " \
      [string trim [string repeat "Interpreter#$nextId 0 $id " 2]] \
      \$] $result
} -cleanup {
  unset -nocomplain msg nextId yyy result id
} -constraints {eagle refCount} -result {1}}

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

runTest {test object-2.8 {honor NoDispose flag during interp disposal} -body {
  set object [object create Eagle._Tests.Default+Disposable]

  set result null
  set interp [object invoke -alias Interpreter Create result]

  set result null
  set parameters [list \
      -flags +NonPublic $interp AddObject foo null NoDispose null 0]

  if {[haveConstraint compile.NATIVE] && \
      [haveConstraint compile.TCL]} then {
    lappend parameters null
  }

  if {[haveConstraint compile.DEBUGGER] && \
      [haveConstraint compile.DEBUGGER_ARGUMENTS]} then {
    lappend parameters null
  }

  lappend parameters $object result
  set code [eval object invoke $parameters]

  if {$code ne "Ok"} then {
    error [object invoke $result ToString]
  }

  set results [list]
  lappend results [object invoke $object ToString]

  object dispose $interp
  lappend results [object invoke $object ToString]

  object invoke $object Dispose
  lappend results [object invoke $object ToString]

  set results
} -cleanup {
  unset -nocomplain parameters result code interp object results
} -constraints {eagle compile.TEST\
member_Eagle._Tests.Default.Disposable.ToString} -match regexp -result \
{^\{id = \d+, disposing = False, disposed = False\} \{id = \d+, disposing =\
False, disposed = False\} \{id = \d+, disposing = True, disposed = True\}$}}

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

runTest {test object-2.9 {invoke with custom named object} -setup {
  set interp [object invoke Interpreter GetActive]
  set name [appendArgs customObj # [object invoke $interp NextId]]
  set options [object invoke Utility GetInvokeOptions Default]

  set result null
  set code [object invoke Utility FixupReturnValue "" null null null None \
      $options Default $name null $interp true false true false false result]

  if {$code ne "Ok"} then {
    error [object invoke $result ToString]
  }
} -body {
  list [object invoke $name ToString] \
      [object invoke Interpreter IsPendingCleanup $name]
} -cleanup {
  unset -nocomplain code result options name interp
} -constraints {eagle} -match regexp -result {^\d+ False$}}

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

runTest {test object-2.10 {non-primitive ScriptBinder return types} -setup {
  unset -nocomplain type1 version2 version1 uri2 uri1 list1 timeSpan1 \
      dateTime2 dateTime1 guid1

  catch {
    #
    # NOTE: The DateTimeFormat property of the interpreter is available
    #       starting with the Beta 28 release.
    #
    set savedDateTimeFormat [object invoke Interpreter.GetActive \
        DateTimeFormat]

    object invoke Interpreter.GetActive DateTimeFormat "M/d/yyyy h:mm:ss tt"
  }
} -body {
  list [set guid1 [object invoke Guid Empty]] \
      [set dateTime1 [object invoke -create -alias DateTime Parse \
          2063-04-04T11:23:42.1221996]] \
      [set dateTime2 [object invoke DateTime Parse \
          2063-04-04T11:23:42.1221996]] \
      [set timeSpan1 [$dateTime1 Subtract 1]] \
      [set list1 [object invoke StringList FromString "a b c"]] \
      [set uri1 [object create -alias Uri http://localhost/]] \
      [set uri2 [$uri1 MakeRelativeUri http://localhost/]] \
      [set version1 [object create -alias Version 1.0.0.0]] \
      [set version2 [$version1 Clone]] \
      [set type1 [$uri1 GetType]]
} -cleanup {
  catch {
    #
    # NOTE: The DateTimeFormat property of the interpreter is available
    #       starting with the Beta 28 release.
    #
    object invoke Interpreter.GetActive DateTimeFormat $savedDateTimeFormat
    unset -nocomplain savedDateTimeFormat
  }

  unset -nocomplain type1 version2 version1 uri2 uri1 list1 timeSpan1 \
      dateTime2 dateTime1 guid1
} -constraints {eagle} -match regexp -result \
{^00000000-0000-0000-0000-000000000000 System#DateTime#\d+ \{4/4/2063 11:23:42\
AM\} 753223\.11:23:42\.1221995 \{a b c\} System#Uri#\d+ \{\} System#Version#\d+\
1\.0\.0\.0 System\.Uri$}}

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

runTest {test object-2.11 {scalar variable to array within object} -setup {
  unset -nocomplain input output
} -body {
  array set output {1 1.3 2 3 3 test 4 True}

  list [object invoke Eagle._Tests.Default TestObjectAsArray null output] \
      [testArrayGet output true] [testArrayGet output_1 true] [object invoke \
      Eagle._Tests.Default TestObjectAsArray valid output] [testArrayGet \
      output true] [testArrayGet output_1 true]
} -cleanup {
  unset -nocomplain input output output_1
} -constraints {eagle compile.TEST Eagle._Tests.Default.TestObjectAsArray} \
-result {False {1 output_1 2 3 3 test 4 True} {1 1.3 2 3 3 test 4 True} True {0\
valid 1 output_1 2 3 3 test 4 True} {1 output_1 2 3 3 test 4 True}}}

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

runTest {test object-2.12 {negative array lower and upper bounds} -setup {
  set o1 [object create Eagle._Tests.Default]
} -body {
  catch {unset t7}; # input/output param
  set t7() "this is not an integer; however, it does not matter"

  list [set rt7_1 [object invoke $o1 TestMoreComplexMethod true t7]] \
      [testArrayGet t7] [set rt7_2 [object invoke $o1 TestMoreComplexMethod \
      false t7]] [testArrayGet t7]
} -cleanup {
  unset -nocomplain rt7_2 rt7_1 t7 o1
} -constraints {eagle compile.TEST monoBug22\
Eagle._Tests.Default.TestMoreComplexMethod} -match regexp -result \
{^\{System#Int32\[,\]#\d+\} \{\{\} \{this is not an integer; however, it does\
not matter\} -3,10 0 -3,6 0 -3,7 0 -3,8 0 -3,9 0 -4,10 0 -4,6 0 -4,7 0 -4,8 0\
-4,9 0 -5,10 0 -5,6 0 -5,7 0 -5,8 0 -5,9 0 -6,10 0 -6,6 0 -6,7 0 -6,8 0 -6,9\
0\} \{System#Int32\[,\]#\d+\} \{\{\} \{this is not an integer; however, it does\
not matter\} -3,10 -30 -3,6 -18 -3,7 -21 -3,8 -24 -3,9 -27 -4,10 -40 -4,6 -24\
-4,7 -28 -4,8 -32 -4,9 -36 -5,10 -50 -5,6 -30 -5,7 -35 -5,8 -40 -5,9 -45 -6,10\
-60 -6,6 -36 -6,7 -42 -6,8 -48 -6,9 -54\}$}}

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

runTest {test object-2.13 {negative array lower and upper bounds} -setup {
  catch {unset t7}; # input/output param
  set t7() "this is not an integer; however, it does not matter"
  set t7(-6,6) [expr {-6 * 6}]
  set t7(-6,7) [expr {-6 * 7}]
  set t7(-6,8) [expr {-6 * 8}]
  set t7(-6,9) [expr {-6 * 9}]
  set t7(-6,10) [expr {-6 * 10}]
  set t7(-5,6) [expr {-5 * 6}]
  set t7(-5,7) [expr {-5 * 7}]
  set t7(-5,8) [expr {-5 * 8}]
  set t7(-5,9) [expr {-5 * 9}]
  set t7(-5,10) [expr {-5 * 10}]
  set t7(-4,6) [expr {-4 * 6}]
  set t7(-4,7) [expr {-4 * 7}]
  set t7(-4,8) [expr {-4 * 8}]
  set t7(-4,9) [expr {-4 * 9}]
  set t7(-4,10) [expr {-4 * 10}]
  set t7(-3,6) [expr {-3 * 6}]
  set t7(-3,7) [expr {-3 * 7}]
  set t7(-3,8) [expr {-3 * 8}]
  set t7(-3,9) [expr {-3 * 9}]
  set t7(-3,10) [expr {-3 * 10}]
} -body {
  list [object invoke Eagle._Tests.Default TestMulti2Array t7] \
      [testArrayGet t7]
} -cleanup {
  unset -nocomplain t7
} -constraints {eagle compile.TEST monoBug22\
Eagle._Tests.Default.TestMulti2Array} -result {True {{} {this is not an\
integer; however, it does not matter} -3,10 -30 -3,6 -18 -3,7 -21 -3,8 -24 -3,9\
-27 -4,10 -40 -4,6 -24 -4,7 -28 -4,8 -32 -4,9 -36 -5,10 -50 -5,6 -30 -5,7 -35\
-5,8 -40 -5,9 -45 -6,10 -60 -6,6 -36 -6,7 -42 -6,8 -48 -6,9 -54}}}

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

runTest {test object-2.14 {multi-dimensional array return} -setup {
  set array [object invoke -create \
      Array CreateInstance Int32 [list 2 3] [list -4 -5]]
} -body {
  set return [object invoke \
      -flags +NonPublic Eagle._Components.Private.MarshalOps \
      Identity $array]
} -cleanup {
  unset -nocomplain return array
} -constraints {eagle} -match regexp -result {^System#Int32\[,\]#\d+$}}

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

runTest {test object-2.15 {forced loose matched parameter types} -setup {
  set t2(-1) 1234
} -body {
  object invoke -flags +NonPublic \
      -marshalflags {-StrictMatchType +ForceParameterType} \
      -parametertypes [list Int32\[\]] \
      Eagle._Components.Private.MarshalOps Identity t2
} -cleanup {
  unset -nocomplain t2
} -constraints {eagle} -result 1234}

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

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