blob: ff59c8b22e6ac48c498e4a1940915b2a66e65f0b [file] [log] [blame]
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package java
import (
"reflect"
"testing"
"golang.org/x/mobile/internal/importers"
)
func TestImport(t *testing.T) {
if !IsAvailable() {
t.Skipf("javap not available")
}
tests := []struct {
ref importers.PkgRef
name string
methods []*FuncSet
}{
{
ref: importers.PkgRef{Pkg: "java/lang/Object", Name: "equals"},
name: "java.lang.Object",
methods: []*FuncSet{
&FuncSet{
Name: "equals",
GoName: "Equals",
CommonSig: CommonSig{
Params: []*Type{&Type{Kind: Object, Class: "java.lang.Object"}}, Ret: &Type{Kind: Boolean}, HasRet: true,
},
Funcs: []*Func{&Func{FuncSig: FuncSig{Name: "equals", Desc: "(Ljava/lang/Object;)Z"}, ArgDesc: "Ljava/lang/Object;", JNIName: "equals", Public: true, Params: []*Type{&Type{Kind: Object, Class: "java.lang.Object"}}, Ret: &Type{Kind: Boolean}}},
},
},
},
{
ref: importers.PkgRef{Pkg: "java/lang/Runnable", Name: "run"},
name: "java.lang.Runnable",
methods: []*FuncSet{
&FuncSet{
Name: "run",
GoName: "Run",
CommonSig: CommonSig{},
Funcs: []*Func{&Func{FuncSig: FuncSig{Name: "run", Desc: "()V"}, ArgDesc: "", JNIName: "run", Public: true, Abstract: true}},
},
},
},
}
toString := &FuncSet{
Name: "toString",
GoName: "ToString",
CommonSig: CommonSig{
Ret: &Type{Kind: String}, HasRet: true,
},
Funcs: []*Func{&Func{FuncSig: FuncSig{Name: "toString", Desc: "()Ljava/lang/String;"}, ArgDesc: "", JNIName: "toString", Public: true, Ret: &Type{Kind: String}}},
}
for _, test := range tests {
refs := &importers.References{
Refs: []importers.PkgRef{test.ref},
Names: make(map[string]struct{}),
}
for _, m := range test.methods {
refs.Names[m.GoName] = struct{}{}
}
classes, err := (&Importer{}).Import(refs)
if err != nil {
t.Fatal(err)
}
if len(classes) != 1 {
t.Fatalf("got %d classes, expected 1", len(classes))
}
cls := classes[0]
if cls.Name != test.name {
t.Errorf("got class name %s, expected %s", cls.Name, test.name)
}
methods := test.methods
if !cls.Interface {
methods = append(methods, toString)
}
loop:
for _, exp := range methods {
for _, got := range cls.AllMethods {
if reflect.DeepEqual(exp, got) {
continue loop
}
}
t.Errorf("failed to find method: %+v", exp)
}
}
}
func testClsMap() map[string]*Class {
//
// A--
// / \ \
// B C \
// \ / \ \
// D E F
//
return map[string]*Class{
"A": &Class{},
"B": &Class{
Supers: []string{"A"},
},
"C": &Class{
Supers: []string{"A"},
},
"D": &Class{
Supers: []string{"B", "C"},
},
"E": &Class{
Supers: []string{"C"},
},
"F": &Class{
Supers: []string{"A"},
},
}
}
func TestCommonTypes(t *testing.T) {
clsMap := testClsMap()
tests := [][3]*Type{
{nil, nil, nil},
{&Type{Kind: Int}, nil, nil},
{&Type{Kind: Int}, &Type{Kind: Float}, nil},
{&Type{Kind: Int}, &Type{Kind: Int}, &Type{Kind: Int}},
{&Type{Kind: Object, Class: "D"}, &Type{Kind: Object, Class: "D"}, &Type{Kind: Object, Class: "D"}},
{&Type{Kind: Object, Class: "D"}, &Type{Kind: Object, Class: "E"}, &Type{Kind: Object, Class: "C"}},
{&Type{Kind: Object, Class: "D"}, &Type{Kind: Object, Class: "F"}, &Type{Kind: Object, Class: "A"}},
{&Type{Kind: Object, Class: "B"}, &Type{Kind: Object, Class: "E"}, &Type{Kind: Object, Class: "A"}},
}
for _, test := range tests {
t1, t2, exp := test[0], test[1], test[2]
got := commonType(clsMap, t1, t2)
if !reflect.DeepEqual(got, exp) {
t.Errorf("commonType(%+v, %+v) = %+v, expected %+v", t1, t2, got, exp)
}
}
}
func TestCommonSig(t *testing.T) {
tests := []struct {
Sigs []CommonSig
CommonSig
}{
{
Sigs: []CommonSig{
CommonSig{}, // f()
},
CommonSig: CommonSig{}, // f()
},
{
Sigs: []CommonSig{
CommonSig{Throws: true, HasRet: true, Ret: &Type{Kind: Int}}, // int f() throws
},
// int f() throws
CommonSig: CommonSig{Throws: true, HasRet: true, Ret: &Type{Kind: Int}},
},
{
Sigs: []CommonSig{
CommonSig{}, // f()
CommonSig{Params: []*Type{&Type{Kind: Int}}}, // f(int)
},
CommonSig: CommonSig{ // f(int...)
Variadic: true,
Params: []*Type{&Type{Kind: Int}},
},
},
{
Sigs: []CommonSig{
CommonSig{Params: []*Type{&Type{Kind: Int}}}, // f(int)
CommonSig{Params: []*Type{&Type{Kind: Float}}}, // f(float)
},
CommonSig: CommonSig{ // f(interface{})
Params: []*Type{nil},
},
},
{
Sigs: []CommonSig{
CommonSig{Params: []*Type{&Type{Kind: Int}}}, // f(int)
CommonSig{Params: []*Type{&Type{Kind: Int}, &Type{Kind: Int}}}, // f(int, int)
},
CommonSig: CommonSig{ // f(int, int...)
Variadic: true,
Params: []*Type{&Type{Kind: Int}, &Type{Kind: Int}},
},
},
{
Sigs: []CommonSig{
CommonSig{Params: []*Type{&Type{Kind: Object, Class: "A"}}}, // f(A)
CommonSig{Params: []*Type{&Type{Kind: Object, Class: "B"}}}, // f(B)
},
CommonSig: CommonSig{ // f(A)
Params: []*Type{&Type{Kind: Object, Class: "A"}},
},
},
}
clsMap := testClsMap()
for _, test := range tests {
got := combineSigs(clsMap, test.Sigs...)
if !reflect.DeepEqual(got, test.CommonSig) {
t.Errorf("commonSig(%+v) = %+v, expected %+v", test.Sigs, got, test.CommonSig)
}
}
}