// 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) } } }