1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-19 19:55:30 +08:00
otto/reflect_test.go
Steven Hartland c25bb49761 Automatic numeric parameter conversion
Javascript uses int64 (literals) and float64 (default) representations for numbers so to allow easy use of go funcs apply automatic conversion for function parameters where it is safe to do so.
2015-02-12 15:48:45 +00:00

614 lines
11 KiB
Go

package otto
import (
"fmt"
"math"
"reflect"
"testing"
)
type _abcStruct struct {
Abc bool
Def int
Ghi string
Jkl interface{}
Mno _mnoStruct
Pqr map[string]int8
}
func (abc _abcStruct) String() string {
return abc.Ghi
}
func (abc *_abcStruct) FuncPointer() string {
return "abc"
}
func (abc _abcStruct) Func() {
return
}
func (abc _abcStruct) FuncReturn1() string {
return "abc"
}
func (abc _abcStruct) FuncReturn2() (string, error) {
return "def", nil
}
func (abc _abcStruct) Func1Return1(a string) string {
return a
}
func (abc _abcStruct) Func2Return1(x, y string) string {
return x + y
}
func (abc _abcStruct) FuncEllipsis(xyz ...string) int {
return len(xyz)
}
func (abc _abcStruct) FuncReturnStruct() _mnoStruct {
return _mnoStruct{}
}
func (abs _abcStruct) Func1Int(i int) int {
return i + 1
}
func (abs _abcStruct) Func1Int8(i int8) int8 {
return i + 1
}
func (abs _abcStruct) Func1Int16(i int16) int16 {
return i + 1
}
func (abs _abcStruct) Func1Int32(i int32) int32 {
return i + 1
}
func (abs _abcStruct) Func1Int64(i int64) int64 {
return i + 1
}
func (abs _abcStruct) Func1Uint(i uint) uint {
return i + 1
}
func (abs _abcStruct) Func1Uint8(i uint8) uint8 {
return i + 1
}
func (abs _abcStruct) Func1Uint16(i uint16) uint16 {
return i + 1
}
func (abs _abcStruct) Func1Uint32(i uint32) uint32 {
return i + 1
}
func (abs _abcStruct) Func1Uint64(i uint64) uint64 {
return i + 1
}
func (abs _abcStruct) Func2Int(i, j int) int {
return i + j
}
func (abs _abcStruct) Func2StringInt(s string, i int) string {
return fmt.Sprintf("%v:%v", s, i)
}
func (abs _abcStruct) Func1IntVariadic(a ...int) int {
t := 0
for _, i := range a {
t += i
}
return t
}
func (abs _abcStruct) Func2IntVariadic(s string, a ...int) string {
t := 0
for _, i := range a {
t += i
}
return fmt.Sprintf("%v:%v", s, t)
}
type _mnoStruct struct {
Ghi string
}
func (mno _mnoStruct) Func() string {
return "mno"
}
func TestReflect(t *testing.T) {
if true {
return
}
tt(t, func() {
// Testing dbgf
// These should panic
toValue("Xyzzy").toReflectValue(reflect.Ptr)
stringToReflectValue("Xyzzy", reflect.Ptr)
})
}
func Test_reflectStruct(t *testing.T) {
tt(t, func() {
test, vm := test()
// _abcStruct
{
abc := &_abcStruct{}
vm.Set("abc", abc)
test(`
[ abc.Abc, abc.Ghi ];
`, "false,")
abc.Abc = true
abc.Ghi = "Nothing happens."
test(`
[ abc.Abc, abc.Ghi ];
`, "true,Nothing happens.")
*abc = _abcStruct{}
test(`
[ abc.Abc, abc.Ghi ];
`, "false,")
abc.Abc = true
abc.Ghi = "Xyzzy"
vm.Set("abc", abc)
test(`
[ abc.Abc, abc.Ghi ];
`, "true,Xyzzy")
is(abc.Abc, true)
test(`
abc.Abc = false;
abc.Def = 451;
abc.Ghi = "Nothing happens.";
abc.abc = "Something happens.";
[ abc.Def, abc.abc ];
`, "451,Something happens.")
is(abc.Abc, false)
is(abc.Def, 451)
is(abc.Ghi, "Nothing happens.")
test(`
delete abc.Def;
delete abc.abc;
[ abc.Def, abc.abc ];
`, "451,")
is(abc.Def, 451)
test(`
abc.FuncPointer();
`, "abc")
test(`
abc.Func();
`, "undefined")
test(`
abc.FuncReturn1();
`, "abc")
test(`
abc.Func1Return1("abc");
`, "abc")
test(`
abc.Func2Return1("abc", "def");
`, "abcdef")
test(`
abc.FuncEllipsis("abc", "def", "ghi");
`, 3)
test(`raise:
abc.FuncReturn2();
`, "TypeError")
test(`
abc.FuncReturnStruct();
`, "[object Object]")
test(`
abc.FuncReturnStruct().Func();
`, "mno")
test(`
abc.Func1Int(1);
`, 2)
test(`raise:
abc.Func1Int(1.1);
`, "reflect: Call using float64 as type int")
test(`
var v = 1;
abc.Func1Int(v + 1);
`, 3)
test(`
abc.Func2Int(1, 2);
`, 3)
test(`
abc.Func1Int8(1);
`, 2)
test(`
abc.Func1Int16(1);
`, 2)
test(`
abc.Func1Int32(1);
`, 2)
test(`
abc.Func1Int64(1);
`, 2)
test(`
abc.Func1Uint(1);
`, 2)
test(`
abc.Func1Uint8(1);
`, 2)
test(`
abc.Func1Uint16(1);
`, 2)
test(`
abc.Func1Uint32(1);
`, 2)
test(`
abc.Func1Uint64(1);
`, 2)
test(`
abc.Func2StringInt("test", 1);
`, "test:1")
test(`
abc.Func1IntVariadic(1, 2);
`, 3)
test(`
abc.Func2IntVariadic("test", 1, 2);
`, "test:3")
}
})
}
func Test_reflectMap(t *testing.T) {
tt(t, func() {
test, vm := test()
// map[string]string
{
abc := map[string]string{
"Xyzzy": "Nothing happens.",
"def": "1",
}
vm.Set("abc", abc)
test(`
abc.xyz = "pqr";
[ abc.Xyzzy, abc.def, abc.ghi ];
`, "Nothing happens.,1,")
is(abc["xyz"], "pqr")
}
// map[string]float64
{
abc := map[string]float64{
"Xyzzy": math.Pi,
"def": 1,
}
vm.Set("abc", abc)
test(`
abc.xyz = "pqr";
abc.jkl = 10;
[ abc.Xyzzy, abc.def, abc.ghi ];
`, "3.141592653589793,1,")
is(abc["xyz"], math.NaN())
is(abc["jkl"], float64(10))
}
// map[string]int32
{
abc := map[string]int32{
"Xyzzy": 3,
"def": 1,
}
vm.Set("abc", abc)
test(`
abc.xyz = "pqr";
abc.jkl = 10;
[ abc.Xyzzy, abc.def, abc.ghi ];
`, "3,1,")
is(abc["xyz"], 0)
is(abc["jkl"], int32(10))
test(`
delete abc["Xyzzy"];
`)
_, exists := abc["Xyzzy"]
is(exists, false)
is(abc["Xyzzy"], 0)
}
// map[int32]string
{
abc := map[int32]string{
0: "abc",
1: "def",
}
vm.Set("abc", abc)
test(`
abc[2] = "pqr";
//abc.jkl = 10;
abc[3] = 10;
[ abc[0], abc[1], abc[2], abc[3] ]
`, "abc,def,pqr,10")
is(abc[2], "pqr")
is(abc[3], "10")
test(`
delete abc[2];
`)
_, exists := abc[2]
is(exists, false)
}
})
}
func Test_reflectSlice(t *testing.T) {
tt(t, func() {
test, vm := test()
// []bool
{
abc := []bool{
false,
true,
true,
false,
}
vm.Set("abc", abc)
test(`
abc;
`, "false,true,true,false")
test(`
abc[0] = true;
abc[abc.length-1] = true;
delete abc[2];
abc;
`, "true,true,false,true")
is(abc, []bool{true, true, false, true})
is(abc[len(abc)-1], true)
}
// []int32
{
abc := make([]int32, 4)
vm.Set("abc", abc)
test(`
abc;
`, "0,0,0,0")
test(`
abc[0] = 4.2;
abc[1] = "42";
abc[2] = 3.14;
abc;
`, "4,42,3,0")
is(abc, []int32{4, 42, 3, 0})
test(`
delete abc[1];
delete abc[2];
`)
is(abc[1], 0)
is(abc[2], 0)
}
})
}
func Test_reflectArray(t *testing.T) {
tt(t, func() {
test, vm := test()
// []bool
{
abc := [4]bool{
false,
true,
true,
false,
}
vm.Set("abc", abc)
test(`
abc;
`, "false,true,true,false")
// Unaddressable array
test(`
abc[0] = true;
abc[abc.length-1] = true;
abc;
`, "false,true,true,false")
// Again, unaddressable array
is(abc, [4]bool{false, true, true, false})
is(abc[len(abc)-1], false)
// ...
}
// []int32
{
abc := make([]int32, 4)
vm.Set("abc", abc)
test(`
abc;
`, "0,0,0,0")
test(`
abc[0] = 4.2;
abc[1] = "42";
abc[2] = 3.14;
abc;
`, "4,42,3,0")
is(abc, []int32{4, 42, 3, 0})
}
// []bool
{
abc := [4]bool{
false,
true,
true,
false,
}
vm.Set("abc", &abc)
test(`
abc;
`, "false,true,true,false")
test(`
abc[0] = true;
abc[abc.length-1] = true;
delete abc[2];
abc;
`, "true,true,false,true")
is(abc, [4]bool{true, true, false, true})
is(abc[len(abc)-1], true)
}
})
}
func Test_reflectArray_concat(t *testing.T) {
tt(t, func() {
test, vm := test()
vm.Set("ghi", []string{"jkl", "mno"})
vm.Set("pqr", []interface{}{"jkl", 42, 3.14159, true})
test(`
var def = {
"abc": ["abc"],
"xyz": ["xyz"]
};
xyz = pqr.concat(ghi, def.abc, def, def.xyz);
[ xyz, xyz.length ];
`, "jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz,9")
})
}
func Test_reflectMapInterface(t *testing.T) {
tt(t, func() {
test, vm := test()
{
abc := map[string]interface{}{
"Xyzzy": "Nothing happens.",
"def": "1",
"jkl": "jkl",
}
vm.Set("abc", abc)
vm.Set("mno", &_abcStruct{})
test(`
abc.xyz = "pqr";
abc.ghi = {};
abc.jkl = 3.14159;
abc.mno = mno;
mno.Abc = true;
mno.Ghi = "Something happens.";
[ abc.Xyzzy, abc.def, abc.ghi, abc.mno ];
`, "Nothing happens.,1,[object Object],[object Object]")
is(abc["xyz"], "pqr")
is(abc["ghi"], "[object Object]")
is(abc["jkl"], float64(3.14159))
mno, valid := abc["mno"].(*_abcStruct)
is(valid, true)
is(mno.Abc, true)
is(mno.Ghi, "Something happens.")
}
})
}
func TestPassthrough(t *testing.T) {
tt(t, func() {
test, vm := test()
{
abc := &_abcStruct{
Mno: _mnoStruct{
Ghi: "<Mno.Ghi>",
},
}
vm.Set("abc", abc)
test(`
abc.Mno.Ghi;
`, "<Mno.Ghi>")
vm.Set("pqr", map[string]int8{
"xyzzy": 0,
"Nothing happens.": 1,
})
test(`
abc.Ghi = "abc";
abc.Pqr = pqr;
abc.Pqr["Nothing happens."];
`, 1)
mno := _mnoStruct{
Ghi: "<mno.Ghi>",
}
vm.Set("mno", mno)
test(`
abc.Mno = mno;
abc.Mno.Ghi;
`, "<mno.Ghi>")
}
})
}