# This file tests JavaInvoke.java.
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: JavaInvoke.test,v 1.2 1998/10/29 23:23:32 hylands Exp $

# Note: This test file must be sourced from the parent directory
#       or else the defs file may not be properly loaded.

if {[string compare test [info procs test]] == 1} then {source defs}

setupJavaPackage

#
# newInstance
#

test invoke-1.1 {newInstance} {
    list [catch {java::new foo.bar} msg] $msg
} {1 {unknown class "foo.bar"}}

test invoke-1.2 {newInstance} {
    list [catch {java::new tests.JavaTest blah blah blah} msg] $msg
} {1 {can't find constructor with 3 argument(s) for class "tests.JavaTest"}}

test invoke-1.3 {newInstance} {
    list [catch {java::new {tests.JavaTest boolean} blah} msg] $msg
} {1 {expected boolean value but got "blah"}}

test invoke-1.4 {newInstance} {
    list [catch {java::new {tests.JavaTest boolean} true} msg] $msg
} {1 java.lang.NullPointerException}

test invoke-1.5 {newInstance} {
    set x [java::new {tests.JavaTest}]
    $x imethod
} 6

#
# callMethod
#

set INVCLS tcl.lang.JavaInvoke

test invoke-2.1 {callMethod} {
    set x blah
    set t1 [jtest getobject $x]
    set t2 [jtest getobject $x]
    set argvobj [java::new {tcl.lang.TclObject[]} 1]
    list [catch {
	java::call $INVCLS callMethod [java::getinterp] $t1 $t2 $argvobj 0 0 false} msg] $msg
} {1 {tcl.lang.TclException: unknown java object "blah"}}

test invoke-2.2 {callMethod} {
    set x [java::new Object]
    list [catch {$x foo} msg] $msg
} {1 {no such method "foo" in class java.lang.Object}}

test invoke-2.3 {callMethod} {
    set x [java::new Object]
    list [catch {$x wait 1234xx} msg] $msg
} {1 {expected integer but got "1234xx"}}

test invoke-2.4 {callMethod} {
    set x [java::new tests.JavaTest]
    list [catch {$x imethod} msg] $msg
} {0 6}

test invoke-2.5 {callMethod} {
    set x [java::new tests.JavaTest]
    list [catch {[$x -noconvert imethod] toString} msg] $msg
} {0 6}

#
# callStaticMethod
#

test invoke-3.1 {callStaticMethod} {
    list [catch {java::call foo.bar blah} msg] $msg
} {1 {unknown class "foo.bar"}}

test invoke-3.2 {callStaticMethod} {
    list [catch {java::call tests.JavaTest {smethod int}} msg] $msg
} {1 {no such method "smethod int" in class tests.JavaTest}}

test invoke-3.3 {callStaticMethod} {
    list [catch {java::call tests.JavaTest {imethod}} msg] $msg
} {1 {"imethod" is not a static method of class "tests.JavaTest"}}

test invoke-3.4 {callStaticMethod} {
    list [catch {java::call tests.JavaTest {smethod}} msg] $msg
} {0 static}

test invoke-3.5 {callStaticMethod} {
    list [catch {
	[java::call -noconvert tests.JavaTest {smethod}] toString
    } msg] $msg
} {0 static}


#
# call
#

test invoke-4.1 {call} {
    list [catch {
	java::new {java.lang.Integer int} 1 2 3
    } msg] $msg
} {1 {wrong # args for calling constructor "java.lang.Integer int"}}

test invoke-4.2 {call} {
    set x [java::new Object]
    list [catch {
	$x {wait long} 1 2 3
    } msg] $msg
} {1 {wrong # args for calling method "wait long"}}

test invoke-4.2 {call} {
    set x [java::new tests.JavaTest]
    list [catch {$x imethod} msg] $msg
} {0 6}

test invoke-4.4 {call} {
    set x [java::new tests.JavaTest]
    list [catch {$x imethod 123} msg] $msg
} {0 124}

test invoke-4.5 {call} {
    set x [java::new tests.JavaTest]
    list [catch {$x failMethod} msg] $msg
} {1 java.lang.NullPointerException}


#
# getsetfield
#

test invoke-5.1 {getsetfield} {
    set x [java::new tests.JavaTest]
    list [catch {java::field $x JT2} msg] $msg 
} {0 4}

test invoke-5.2 {getsetfield} {
    list [catch {java::field tests.JavaTest JT1} msg] $msg
} {0 3}

test invoke-5.3 {getsetfield} {
    list [catch {java::field foo.bar blah} msg] $msg
} {1 {unknown class or object "foo.bar"}}

test invoke-5.4 {getsetfield} {
    list [catch {java::field [java::null] blah} msg] $msg
} {1 {can't access fields in a null object reference}}

test invoke-5.5 {getsetfield} {
    list [catch {java::field tests.JavaTest iint} msg] $msg
} {1 {can't access an instance field without an object}}

test invoke-5.6 {getsetfield} {
    list [catch {
	[java::field -noconvert tests.JavaTest JT1] toString
    } msg] $msg
} {0 3}

test invoke-5.7 {getsetfield} {
    list [catch {java::field tests.JavaTest sint 1234xx} msg] $msg
} {1 {expected integer but got "1234xx"}}

test invoke-5.8 {getsetfield} {
    list [catch {
	java::field tests.JavaTest sint 1234
	java::field tests.JavaTest sint
    } msg] $msg
} {0 1234}

test invoke-5.9 {getsetfield} {
    list [catch {
	java::field tests.JavaTest JT3
    } msg] $msg
} {1 {can't access field "JT3": java.lang.IllegalAccessException: tests/JavaTest}}

#
# getProperty
#

test invoke-6.1 {getProperty} {
    list [catch {java::prop foo bar} msg] $msg 
} {1 {unknown java object "foo"}}

test invoke-6.2 {getProperty} {
    list [catch {java::prop java.lang.Object bar} msg] $msg 
} {1 {unknown java object "java.lang.Object"}}

test invoke-6.3 {getProperty} {
    list [catch {java::prop [java::null] bar} msg] $msg 
} {1 {can't get property from null object}}

test invoke-6.4 {getProperty} {
    set x [java::new Object]
    list [catch {java::prop $x blah} msg] $msg 
} {1 {unknown property "blah"}}

test invoke-6.5 {getProperty} {
    set x [java::new pkg1.MyClass]
    list [catch {java::prop $x writeOnly} msg] $msg 
} {1 {can't get write-only property "writeOnly"}}

test invoke-6.6 {getProperty} {
    set x [java::new pkg1.MyClass]
    $x setFoo 12345
    list [catch {java::prop $x foo} msg] $msg 
} {0 12345}

#
# setProperty
#

test invoke-7.1 {setProperty} {
    list [catch {java::prop foo bar 123} msg] $msg 
} {1 {unknown java object "foo"}}

test invoke-7.2 {setProperty} {
    list [catch {java::prop java.lang.Object bar 123} msg] $msg 
} {1 {unknown java object "java.lang.Object"}}

test invoke-7.3 {setProperty} {
    list [catch {java::prop [java::null] bar 123} msg] $msg 
} {1 {can't set property in null object}}

test invoke-7.4 {setProperty} {
    set x [java::new Object]
    list [catch {java::prop $x blah 123} msg] $msg 
} {1 {unknown property "blah"}}

test invoke-7.5 {setProperty} {
    set x [java::new pkg1.MyClass]
    list [catch {java::prop $x readOnly joe} msg] $msg 
} {1 {can't set read-only property "readOnly"}}

test invoke-7.7 {setProperty} {
    set x [java::new pkg1.MyClass]
    list [catch {
	java::prop $x foo 44556xx
    } msg] $msg 
} {1 {expected integer but got "44556xx"}}

test invoke-7.8 {setProperty} {
    set x [java::new pkg1.MyClass]
    list [catch {
	java::prop $x foo 44556
	$x getFoo
    } msg] $msg 
} {0 44556}


test invoke-8.1 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] {int}] getName
} {int}

test invoke-8.2 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] {int[]}] getName
} {[I}

test invoke-8.3 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] {int[][]}] getName
} {[[I}

set clsdata(boolean) {[Z}
set clsdata(byte)    {[B}
set clsdata(char)    {[C}
set clsdata(double)  {[D}
set clsdata(float)   {[F}
set clsdata(int)     {[I}
set clsdata(long)    {[J}
set clsdata(short)   {[S}

set i 0

foreach type [lsort [array names clsdata]] {
    incr i
    test invoke-8.4.$i "getClassByName - $type\[\]" "
    \[java::call $INVCLS getClassByName \[java::getinterp\] {$type\[\]} \] \\
	getName
" $clsdata($type)
}

catch {unset clsdata}
set clsdata(boolean) [java::field java.lang.Boolean TYPE]
set clsdata(byte)    [java::field java.lang.Byte TYPE]
set clsdata(char)    [java::field java.lang.Character TYPE]
set clsdata(double)  [java::field java.lang.Double TYPE]
set clsdata(float)   [java::field java.lang.Float TYPE]
set clsdata(int)     [java::field java.lang.Integer TYPE]
set clsdata(long)    [java::field java.lang.Long TYPE]
set clsdata(short)   [java::field java.lang.Short TYPE]

set i 0

foreach type [lsort [array names clsdata]] {
    incr i
    test invoke-8.5.$i "getClassByName - $type" "
    \[java::call $INVCLS getClassByName \[java::getinterp\] $type \] \\
	equals $clsdata($type)
" 1
}

#
# getClassByName
#

test invoke-8.6 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] Integer] getName
} java.lang.Integer

test invoke-8.7 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] {Integer[]}] getName
} {[Ljava.lang.Integer;}

test invoke-8.8 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] java.lang.Integer] \
	getName
} java.lang.Integer

test invoke-8.9 {getClassByName} {
    [java::call $INVCLS getClassByName [java::getinterp] {java.lang.Integer[]}] getName
} {[Ljava.lang.Integer;}

test invoke-8.10 {getClassByName} {
    list [catch {
	java::call $INVCLS getClassByName [java::getinterp] {foo.bar}
    } msg] $msg
} {1 {tcl.lang.TclException: unknown class "foo.bar"}}

test invoke-8.11 {getClassByName} {
    list [catch {
	java::new tcl.lang.Foo
    } msg] $msg
} {1 {cannot load new class into java or tcl package}}

#
# convertJavaObject
#

test invoke-9.1 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x iobjnull
} java0x0
test invoke-9.2 {convertJavaObject} {
    set x [java::new tests.ConvertTest]
    java::field $x strField0
} ""
test invoke-9.3 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x iint
} 123
test invoke-9.4 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x ilong
} 123
test invoke-9.5 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x ishort
} 123
test invoke-9.6 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x ibyte
} 123
test invoke-9.7 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x idouble
} 123.0
test invoke-9.8 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x ifloat
} 123.0
test invoke-9.9 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x istr
} "test string"
test invoke-9.10 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x iobj2
} "test string obj"
test invoke-9.11 {convertJavaObject} {
    set x [java::new tests.ConvertTest]
    java::field $x strField1
} ""
test invoke-9.12 {convertJavaObject} {
    set x [java::new tests.ConvertTest]
    java::field $x strField2
} null
test invoke-9.13 {convertJavaObject} {
    set x [java::new tests.ConvertTest]
    java::field $x strField3
} foo
test invoke-9.14 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    java::field $x iobj1
} 123
test invoke-9.15 {convertJavaObject} {
    set x [java::new tests.JavaTest]
    jtest type [java::field $x iobj3]
} tcl.lang.ReflectObject

#
# convertTclObject
#

catch {unset clsdata}
set clsdata(java.lang.String) {
    {foo {0 foo}}
    {bar {0 bar}}
    {12.3.4.5+ {0 12.3.4.5+}}
}
set clsdata(java.lang.Integer) {
    {0 {0 0}}
    {1 {0 1}}
    {0x100 {0 256}}
    {0x1000000000 
	{1 {tcl.lang.TclException: integer value too large to represent}}}
}
set clsdata(java.lang.Boolean) {
    {0 {0 false}}
    {1 {0 true}}
    {false {0 false}}
    {true {0 true}}
    {duh {1 {tcl.lang.TclException: expected boolean value but got "duh"}}}
}
set clsdata(java.lang.Long) {
    {0 {0 0}}
    {1 {0 1}}
    {0x100 {0 256}}
    {0x1000000000 
	{1 {tcl.lang.TclException: integer value too large to represent}}}
}
set clsdata(java.lang.Float) {
    {0.0 {0 0.0}}
    {1.0 {0 1.0}}
    {123.1 {0 123.1}}
    {1.5.6
   {1 {tcl.lang.TclException: expected floating-point number but got "1.5.6"}}}
}
set clsdata(java.lang.Double) {
    {0.0 {0 0.0}}
    {1.0 {0 1.0}}
    {123.1 {0 123.1}}
    {1.5.6
   {1 {tcl.lang.TclException: expected floating-point number but got "1.5.6"}}}
}
set clsdata(java.lang.Byte) {
    {0 {0 0}}
    {1 {0 1}}
    {0x100
	{1 {tcl.lang.TclException: integer value too large to represent in a byte}}}
}
set clsdata(java.lang.Short) {
    {0 {0 0}}
    {1 {0 1}}
    {0x10000
	{1 {tcl.lang.TclException: integer value too large to represent in a short}}}
}
set clsdata(java.lang.Character) {
    {0 {0 0}}
    {1 {0 1}}
    {k {0 k}}
    {kk {1 {tcl.lang.TclException: expected character but got "kk"}}}
}
set clsdata(java.lang.Object) {
    {0 {0 0}}
    {1 {0 1}}
    {k {0 k}}
    {kk {0 kk}}
    {{foo bar [} {0 {foo bar [}}}
}

set o1 [java::new Object]
set o2 [java::new {Integer int} 12345]
lappend clsdata(java.lang.Object) [list $o1 [list 0 [$o1 toString]]]
lappend clsdata(java.lang.Object) [list $o2 [list 0 12345]]

set INVCLS tcl.lang.JavaInvoke
set interp [java::getinterp]
set i 0
foreach type [lsort [array names clsdata]] {
    foreach pair $clsdata($type) {
	incr i
	set value  [lindex $pair 0]
	set result [lindex $pair 1]

	set cls [java::call Class forName $type]
        test invoke-10.1.$i "convertTclObject - $type, $value " {
	    list [catch {
		[java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]] toString
	    } msg] $msg
	} $result

	if [catch {set cls [java::field $type TYPE]}] {
	    continue
	}
	incr i
        test invoke-10.1.$i "convertTclObject - [$cls getName], $value " {
	    list [catch {
		[java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]] toString
	    } msg] $msg
	} $result
    }
}

# the following list is used to test the various primitive types
# for both static and nonstatic fields

set values {
    {boolean true {0 1}}
    {boolean blat {1 {expected boolean value but got "blat"}}}
    {byte 3 {0 3}}
    {byte 256 {1 {integer value too large to represent in a byte}}}
    {char f {0 f}}
    {char foobar {1 {expected character but got "foobar"}}}
    {double 3.4 {0 3.4}}
    {double blat {1 {expected floating-point number but got "blat"}}}
    {float 3.4 {0 3.40000009537}}
    {float blat {1 {expected floating-point number but got "blat"}}}
    {int 2 {0 2}}
    {int 2147483648 {0 -2147483648}}
    {int 21474836480 {1 {integer value too large to represent}}}
    {int 2.3 {1 {expected integer but got "2.3"}}}
    {long 2147483648 {0 -2147483648}}
    {long 2.3 {1 {expected integer but got "2.3"}}}
    {short 3 {0 3}}
    {short 40000 {1 {integer value too large to represent in a short}}}
    {str foobar {0 foobar}}
    {str {} {0 {}}}
}

set test 1
foreach l $values {
    test invoke-10.2.[incr test] "convertTclObject: $l" {
	list [catch {
	    java::field tests.JavaTest s[lindex $l 0] [lindex $l 1]
	    set result [java::field tests.JavaTest s[lindex $l 0]]
	} msg] $msg
    } [lindex $l 2]
    test invoke-10.2.[incr test] "setField static: $l" {
	list [catch {
	    set o [java::new tests.JavaTest]
	    java::field $o i[lindex $l 0] [lindex $l 1]
	    set result [java::field $o i[lindex $l 0]]
	} msg] $msg
    } [lindex $l 2]
}

test invoke-10.3 {convertTclObject} {
    # Note that this test fails with JDK1.2beta4, bug seems to be 'forName'
    set cls [java::call Class forName tests.JavaTest]
    set value foobar
    list [catch {
	[java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]] toString
    } msg] $msg
} {1 {tcl.lang.TclException: "foobar" is not an object handle of class "tests.JavaTest"}}

test invoke-10.4 {convertTclObject} {
    # Note that this test fails with JDK1.2beta4, bug seems to be 'forName'
    set cls [java::call Class forName tests.JavaTest]
    set value java0x1000000
    list [catch {
	[java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]] toString
    } msg] $msg
} {1 {tcl.lang.TclException: "java0x1000000" is not an object handle of class "tests.JavaTest"}}

test invoke-10.5 {convertTclObject} {
    # Note that this test fails with JDK1.2beta4, bug seems to be 'forName'
    set cls [java::call Class forName tests.JavaTest]
    set value [java::null]
    list [catch {
	java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]
    } msg] $msg
} [list 0 [java::null]]

test invoke-10.6 {convertTclObject} {
    # Note that this test fails with JDK1.2beta4, bug seems to be 'forName'
    set cls [java::call Class forName tests.JavaTest]
    set value [java::null]
    list [catch {
	java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]
    } msg] $msg
} [list 0 [java::null]]

set value [java::new tests.JavaTest]
#to string compare objects they must be reffed as same type
set value [java::cast java.lang.Object $value]
test invoke-10.7 {convertTclObject} {
    # Note that this test fails with JDK1.2beta4, bug seems to be 'forName'
    set cls [java::call Class forName tests.JavaTest]
    list [catch {
	java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]
    } msg] $msg
} [list 0 $value]

set value [java::new tests.JavaTest]
test invoke-10.8 {convertTclObject} {
    set cls [java::call Class forName java.lang.Integer]
    list [catch {
	java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]
    } msg] $msg
} [list 1 "tcl.lang.TclException: expected object of type java.lang.Integer but got \"$value\" (tests.JavaTest)"]

set value [java::new {Short short} 123]
test invoke-10.8 {convertTclObject} {
    set cls [java::call Class forName java.lang.Integer]
    list [catch {
	java::call -noconvert $INVCLS convertTclObject $interp $cls                       [jtest getobject $value]
    } msg] $msg
} [list 1 "tcl.lang.TclException: expected object of type java.lang.Integer but got \"$value\" (java.lang.Short)"]

#----------------------------------------------------------------------
#
# Some old black-box tests
#
#----------------------------------------------------------------------


test invoke-11.1 {getClassByName} {
    catch {
	java::new {java.lang.Integer int} 1
    }
} 0

test invoke-11.2 {getClassByName} {
    catch {
	java::new {Integer int} 1
    }
} 0

test invoke-11.3 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    $k {equals Object} $k
} 1

test invoke-11.4 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    java::instanceof $k Object
} 1

test invoke-11.5 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    java::instanceof $k java.lang.Integer
} 1

test invoke-11.6 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    java::instanceof $k Integer
} 1

test invoke-11.7 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    java::instanceof $k Long
} 0

test invoke-11.8 {getClassByName} {
    set k [java::new {java.lang.Integer int} 1]
    java::instanceof $k int
} 0

test invoke-11.9 {getClassByName} {
    java::call Integer {toString int} 0001
} 1

test invoke-11.10 {getClassByName} {
    [java::field System out] equals [java::field java.lang.System out]
} 1

catch {unset clsdata}

