blob: c27a946a09738000e416d1ce2a06ca0e87e7cb39 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package builder
import (
"fmt"
"reflect"
"testing"
"android.googlesource.com/platform/tools/gpu/atom"
"android.googlesource.com/platform/tools/gpu/binary"
"android.googlesource.com/platform/tools/gpu/database"
"android.googlesource.com/platform/tools/gpu/gfxapi"
"android.googlesource.com/platform/tools/gpu/log"
"android.googlesource.com/platform/tools/gpu/service/path"
)
type testStruct struct {
binary.Generate
Str string
Ptr *testStruct
}
type testAtom struct {
binary.Generate
api gfxapi.ID
Str string
Sli []bool
Any interface{}
Ptr *testStruct
Map map[string]string
}
type testAPI struct{}
func (testAPI) Name() string { return "foo" }
func (testAPI) ID() gfxapi.ID { return gfxapi.ID{1, 2, 3} }
func (testAPI) GetFramebufferAttachmentSize(state *gfxapi.State, attachment gfxapi.FramebufferAttachment) (uint32, uint32, error) {
return 0, 0, nil
}
func (a testAtom) API() gfxapi.ID { return a.api }
func (testAtom) Flags() atom.Flags { return 0 }
func (testAtom) Observations() *atom.Observations { return &atom.Observations{} }
func (testAtom) Mutate(*gfxapi.State, database.Database, log.Logger) error { return nil }
func newPathTest(t *testing.T, a *atom.List) (*path.Capture, database.Database, log.Logger) {
d, l := database.NewInMemory(nil), log.Testing(t)
p, err := ImportCapture("test", a, d, l)
if err != nil {
t.Fatalf("Failed to create capture: %v", err)
}
return p, d, l
}
func TestGet(t *testing.T) {
gfxapi.Register(testAPI{})
atomA := &testAtom{
api: testAPI{}.ID(),
Str: "aaa",
Sli: []bool{true, false, true},
Any: &testStruct{Str: "bbb"},
Ptr: &testStruct{Str: "ccc", Ptr: &testStruct{Str: "ddd"}},
Map: map[string]string{"cat": "meow", "dog": "woof"},
}
atomB := &testAtom{
Str: "xyz",
Sli: []bool{false, true, false},
Any: &testStruct{Str: "www"},
Map: map[string]string{"bird": "tweet", "fox": "?"},
}
a := atom.NewList(atomA, atomB)
p, d, l := newPathTest(t, a)
// Get tests
for _, test := range []struct {
path path.Path
val interface{}
err error
}{
{p.Atoms().Index(1), a.Atoms[1], nil},
{p.Atoms().Index(1).Field("Str"), "xyz", nil},
{p.Atoms().Index(1).Field("Sli"), []bool{false, true, false}, nil},
{p.Atoms().Index(1).Field("Any"), &testStruct{Str: "www"}, nil},
{p.Atoms().Index(0).Field("Ptr"), &testStruct{Str: "ccc", Ptr: &testStruct{Str: "ddd"}}, nil},
{p.Atoms().Index(1).Field("Sli").ArrayIndex(1), true, nil},
{p.Atoms().Index(1).Field("Sli").Slice(1, 3), []bool{true, false}, nil},
{p.Atoms().Index(1).Field("Str").ArrayIndex(1), byte('y'), nil},
{p.Atoms().Index(1).Field("Str").Slice(1, 3), "yz", nil},
{p.Atoms().Index(1).Field("Map").MapIndex("bird"), "tweet", nil},
{p.Atoms().Index(1).Field("Map").MapIndex([]rune("bird")), "tweet", nil},
// Test invalid paths
{p.Atoms().Index(5), nil, fmt.Errorf(
"Atom at Capture(%v).Atoms[5] is out of bounds [0-1]", p.ID)},
{p.Atoms().Index(1).StateAfter(), nil, fmt.Errorf(
"Atom at Capture(%v).Atoms[1] has no API", p.ID)},
{p.Atoms().Index(0).StateAfter(), nil, fmt.Errorf(
"No state for API '%s' after Capture(%v).Atoms[0]", testAPI{}.Name(), p.ID)},
{p.Atoms().Index(1).Field("doesnotexist"), nil, fmt.Errorf(
"Struct of type builder.testAtom at Capture(%v).Atoms[1] does not have field 'doesnotexist'", p.ID)},
{p.Atoms().Index(1).Field("Ptr").Field("ccc"), nil, fmt.Errorf(
"Pointer at Capture(%v).Atoms[1].Ptr is nil", p.ID)},
{p.Atoms().Index(1).Field("Sli").Field("ccc"), nil, fmt.Errorf(
"Type []bool at Capture(%v).Atoms[1].Sli is not a struct", p.ID)},
{p.Atoms().Index(1).Field("Sli").ArrayIndex(4), nil, fmt.Errorf(
"Index at Capture(%v).Atoms[1].Sli[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Sli").Slice(2, 4), nil, fmt.Errorf(
"Slice at Capture(%v).Atoms[1].Sli[2:4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Str").ArrayIndex(4), nil, fmt.Errorf(
"Index at Capture(%v).Atoms[1].Str[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Ptr").ArrayIndex(4), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not an array, slice or string", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex(10.0), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map has key of type string, got type float64", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex("rabbit"), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map does not contain key rabbit", p.ID)},
{p.Atoms().Index(1).Field("Ptr").MapIndex("foo"), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not a map", p.ID)},
} {
got, err := database.Build(&Get{Path: test.path}, d, l)
if expected := test.err; !reflect.DeepEqual(err, expected) {
t.Errorf("Get(%s) did not return expected error:\nGot: %v\nExpected: %v",
test.path.Path(), err, expected)
}
if expected := test.val; !reflect.DeepEqual(got, expected) {
t.Errorf("Get(%s) was not as expected:\nGot: %T %v\nExpected: %T %v",
test.path.Path(), got, got, expected, expected)
}
}
// Set tests
for _, test := range []struct {
path path.Path
val interface{}
err error
}{
{path: p.Atoms(), val: atom.NewList(atomB)},
{path: p.Atoms().Index(0), val: atomB}, {path: p.Atoms().Index(0).Field("Str"), val: "bbb"},
{path: p.Atoms().Index(0).Field("Sli"), val: []bool{false, true, false}},
{path: p.Atoms().Index(0).Field("Any"), val: 0.123},
{path: p.Atoms().Index(0).Field("Ptr"), val: &testStruct{Str: "ddd"}},
{path: p.Atoms().Index(0).Field("Ptr").Field("Str"), val: "purr"},
{path: p.Atoms().Index(1).Field("Sli").ArrayIndex(1), val: false},
{path: p.Atoms().Index(1).Field("Map").MapIndex("bird"), val: "churp"},
{path: p.Atoms().Index(1).Field("Map").MapIndex([]rune("bird")), val: "churp"},
// Test invalid paths
{p.Atoms().Index(5), nil, fmt.Errorf(
"Atom at Capture(%v).Atoms[5] is out of bounds [0-1]", p.ID)},
{p.Atoms().Index(1).StateAfter(), nil, fmt.Errorf(
"Atom at Capture(%v).Atoms[1] has no API", p.ID)},
{p.Atoms().Index(0).StateAfter(), nil, fmt.Errorf(
"No state for API '%s' after Capture(%v).Atoms[0]", testAPI{}.Name(), p.ID)},
{p.Atoms().Index(1).Field("doesnotexist"), nil, fmt.Errorf(
"Struct of type builder.testAtom at Capture(%v).Atoms[1] does not have field 'doesnotexist'", p.ID)},
{p.Atoms().Index(1).Field("Ptr").Field("ccc"), nil, fmt.Errorf(
"Pointer at Capture(%v).Atoms[1].Ptr is nil", p.ID)},
{p.Atoms().Index(1).Field("Sli").Field("ccc"), nil, fmt.Errorf(
"Type []bool at Capture(%v).Atoms[1].Sli is not a struct", p.ID)},
{p.Atoms().Index(1).Field("Sli").ArrayIndex(4), nil, fmt.Errorf(
"Index at Capture(%v).Atoms[1].Sli[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Str").ArrayIndex(4), nil, fmt.Errorf(
"Index at Capture(%v).Atoms[1].Str[4] is out of bounds [0-2]", p.ID)},
{p.Atoms().Index(1).Field("Ptr").ArrayIndex(4), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not an array, slice or string", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex(10.0), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map has key of type string, got type float64", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex("rabbit"), nil, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map does not contain key rabbit", p.ID)},
{p.Atoms().Index(1).Field("Ptr").MapIndex("foo"), nil, fmt.Errorf(
"Type *builder.testStruct at Capture(%v).Atoms[1].Ptr is not a map", p.ID)},
// Test invalid sets
{p.Atoms().Index(1).Field("Sli").ArrayIndex(2), "blah", fmt.Errorf(
"Slice or array at Capture(%v).Atoms[1].Sli has element of type bool, got type string", p.ID)},
{p.Atoms().Index(1).Field("Map").MapIndex("bird"), 10.0, fmt.Errorf(
"Map at Capture(%v).Atoms[1].Map has value of type string, got type float64", p.ID)},
} {
res, err := database.Build(&Set{Path: test.path, Value: test.val}, d, l)
if expected := test.err; !reflect.DeepEqual(err, expected) {
t.Errorf("Set(%s) did not return expected error:\nGot: %v\nExpected: %v",
test.path.Path(), err, expected)
} else if (res == nil) == (err == nil) {
t.Errorf("Set(%s) returned %T %v and %v.", test.path.Path(), res, res, err)
}
if err == nil {
path := res.(path.Path)
// Check the paths have changed
if reflect.DeepEqual(test.path, p) {
t.Errorf("Set(%s) returned an unchanged path", test.path.Path())
}
// Get the changed value
got, err := database.Build(&Get{Path: path}, d, l)
if expected := error(nil); err != expected {
t.Errorf("Get(%s) did not return expected error:\nGot: %v\nExpected: %v",
test.path.Path(), err, expected)
}
if expected := test.val; !reflect.DeepEqual(got, expected) {
t.Errorf("Get(%s) was not as expected.\nGot: %T %v\nExpected: %T %v",
test.path.Path(), got, got, expected, expected)
}
}
}
}