blob: 5c852531c51ffdd87d1befe0bb9559e8f550f1a7 [file] [log] [blame]
package field_test
import (
"reflect"
"testing"
_ "veyron/lib/testutil"
"veyron/services/store/memstore/field"
"veyron2/storage"
)
type A struct {
B int
C []int
D map[string]int
E storage.ID
F []storage.ID
G map[string]storage.ID
}
type V struct {
UID storage.ID
}
func pathEq(p1, p2 storage.PathName) bool {
if len(p1) != len(p2) {
return false
}
for i, x := range p1 {
if p2[i] != x {
return false
}
}
return true
}
func TestGetField(t *testing.T) {
v := &A{
B: 5,
C: []int{6, 7},
D: map[string]int{"a": 8, "b": 9},
E: storage.NewID(),
F: []storage.ID{storage.NewID()},
G: map[string]storage.ID{"a": storage.NewID()},
}
// Identity.
x, s := field.Get(v, storage.PathName{})
if x.Interface() != v || !pathEq(storage.PathName{}, s) {
t.Errorf("Identity failed: %v", s)
}
// B field.
x, s = field.Get(v, storage.PathName{"B"})
if x.Interface() != 5 || !pathEq(storage.PathName{}, s) {
t.Errorf("Expected 5, got %v, suffix=%v", x.Interface(), s)
}
// C field.
x, s = field.Get(v, storage.PathName{"C"})
if !pathEq(storage.PathName{}, s) {
t.Errorf("Failed to get C: %v")
}
{
y, ok := x.Interface().([]int)
if !ok || len(y) != 2 || y[0] != 6 || y[1] != 7 {
t.Errorf("C has the wrong value: %v", x)
}
}
x, s = field.Get(v, storage.PathName{"C", "0"})
if x.Interface() != 6 || !pathEq(storage.PathName{}, s) {
t.Errorf("Expected 6, got %v, %v", x, s)
}
x, s = field.Get(v, storage.PathName{"C", "1"})
if x.Interface() != 7 || !pathEq(storage.PathName{}, s) {
t.Errorf("Expected 7, got %v, %v", x, s)
}
x, s = field.Get(v, storage.PathName{"C", "2"})
if !pathEq(storage.PathName{"2"}, s) {
t.Errorf("Expected %v, got %v", storage.PathName{"2"}, s)
}
{
y, ok := x.Interface().([]int)
if !ok || len(y) != 2 || y[0] != 6 || y[1] != 7 {
t.Errorf("C has the wrong value: %v", x)
}
}
// D field.
x, s = field.Get(v, storage.PathName{"D"})
if !pathEq(storage.PathName{}, s) {
t.Errorf("Failed to get D")
}
{
y, ok := x.Interface().(map[string]int)
if !ok || len(y) != 2 || y["a"] != 8 || y["b"] != 9 {
t.Errorf("Bad value: %v", y)
}
}
x, s = field.Get(v, storage.PathName{"D", "a"})
if x.Interface() != 8 || !pathEq(storage.PathName{}, s) {
t.Errorf("Expected 8, got %v", x)
}
x, s = field.Get(v, storage.PathName{"D", "b"})
if x.Interface() != 9 || !pathEq(storage.PathName{}, s) {
t.Errorf("Expected 9, got %v", x)
}
x, s = field.Get(v, storage.PathName{"D", "c"})
if !pathEq(storage.PathName{"c"}, s) {
t.Errorf("Expected %v, got %v", storage.PathName{"c"}, s)
}
{
y, ok := x.Interface().(map[string]int)
if !ok || len(y) != 2 || y["a"] != 8 || y["b"] != 9 {
t.Errorf("Bad value: %v", y)
}
}
// E field.
x, s = field.Get(v, storage.PathName{"E"})
if x.Interface() != v.E || !pathEq(storage.PathName{}, s) {
t.Errorf("Failed to get E: %v", x.Interface())
}
x, s = field.Get(v, storage.PathName{"E", "a", "b", "c"})
if x.Interface() != v.E || !pathEq(storage.PathName{"a", "b", "c"}, s) {
t.Errorf("Failed to get E: %v, %v", x.Interface(), s)
}
}
func TestSetSliceField(t *testing.T) {
v := &[]string{"a", "b", "c"}
rv := reflect.ValueOf(v)
// Test simple get and set.
b, _ := field.Get(v, storage.PathName{"1"})
if "b" != b.Interface() {
t.Errorf(`Expected "b", got %v`, b.Interface())
}
if ok, _ := field.Set(rv, "1", "other"); ok != field.SetAsValue {
t.Errorf("field.Set failed on slice: %v", ok)
}
b, _ = field.Get(v, storage.PathName{"1"})
if "other" != b.Interface() {
t.Errorf(`Expected "a", got %v`, b.Interface())
}
// Test get on a non-existant field.
ne, _ := field.Get(v, storage.PathName{"4"})
if ne.Kind() != reflect.Slice {
t.Errorf("Expected to get a top level slice, got: %v", ne.Interface())
}
ne, _ = field.Get(v, storage.PathName{"-1"})
if ne.Kind() != reflect.Slice {
t.Errorf("Expected to get a top level slice, got: %v", ne.Interface())
}
nepath := storage.PathName{"X"}
ne, s := field.Get(v, nepath)
if ne.Kind() != reflect.Slice {
t.Errorf("Expected to get a top level slice, got: %v", ne.Interface())
}
if !reflect.DeepEqual(s, nepath) {
t.Errorf("Expected path %v, got %v.", nepath, s)
}
// Test adding a value.
if ok, _ := field.Set(rv, "@", "AppendedVal"); ok != field.SetAsValue {
t.Errorf("Expected to succeed in appending value: %v", ok)
}
appended, _ := field.Get(v, storage.PathName{"3"})
if "AppendedVal" != appended.Interface() {
t.Errorf(`Expected "AppendedVal", got %v`, appended.Interface())
}
// Test set of an incompatible value fails.
if ok, _ := field.Set(rv, "1", true); ok == field.SetAsValue {
t.Errorf("Expected field.Set to fail when an incompatible value is being set.")
}
}
func TestSetEmptySliceField(t *testing.T) {
v := &[]string{}
rv := reflect.ValueOf(v)
ne, _ := field.Get(v, storage.PathName{"0"})
if ne.Kind() != reflect.Slice {
t.Errorf("Expected to get a top level slice, got: %v", ne.Interface())
}
if ok, _ := field.Set(rv, "0", "a"); ok == field.SetAsValue {
t.Errorf("Expected field.Set to fail")
}
}
func TestSetMapField(t *testing.T) {
v := &map[string]string{
"A": "a",
"B": "b",
}
rv := reflect.ValueOf(v)
// Test simple get and set.
a, _ := field.Get(v, storage.PathName{"A"})
if "a" != a.Interface() {
t.Errorf(`Expected "a", got %v`, a.Interface())
}
if ok, _ := field.Set(rv, "A", "other"); ok != field.SetAsValue {
t.Errorf("field.Set failed on map: %v", ok)
}
a, _ = field.Get(v, storage.PathName{"A"})
if "other" != a.Interface() {
t.Errorf(`Expected "a", got %v`, a.Interface())
}
// Test get on a non-existant field.
nepath := storage.PathName{"NonExistant"}
ne, s := field.Get(v, nepath)
if !reflect.DeepEqual(s, nepath) {
t.Errorf("Expected path %v, got %v.", nepath, s)
}
if ne.Kind() != reflect.Map {
t.Errorf("Expected to get a top level map, got: %v", ne.Interface())
}
// Test that set on a non-existant field adds the field.
if ok, _ := field.Set(rv, "C", "c"); ok != field.SetAsValue {
t.Errorf("Expected field.Set to succeed: %v", ok)
}
c, _ := field.Get(v, storage.PathName{"C"})
if "c" != c.Interface() {
t.Errorf(`Expected "c", got %v`, c.Interface())
}
// Test set of an incompatible value fails.
if ok, _ := field.Set(rv, "A", true); ok == field.SetAsValue {
t.Errorf("Expected field.Set to fail when an incompatible value is being set.")
}
}
func TestSetEmptyMapField(t *testing.T) {
v := &map[string]interface{}{}
rv := reflect.ValueOf(v)
ne, _ := field.Get(v, storage.PathName{"A"})
if ne.Kind() != reflect.Map {
t.Errorf("Expected to get a top level map, got: %v", ne.Interface())
}
if ok, _ := field.Set(rv, "A", "a"); ok != field.SetAsValue {
t.Errorf("Expected field.Set to succeed: %v", ok)
}
a, _ := field.Get(v, storage.PathName{"A"})
if "a" != a.Interface() {
t.Errorf(`Expected "a", got %v`, a.Interface())
}
}
func TestSetStructField(t *testing.T) {
a := &A{
B: 5,
C: []int{6, 7},
D: map[string]int{"a": 8, "b": 9},
E: storage.NewID(),
F: []storage.ID{storage.NewID()},
G: map[string]storage.ID{"a": storage.NewID()},
}
v := reflect.ValueOf(a)
// B field.
x, _ := field.Get(a, storage.PathName{"B"})
if x.Interface() != 5 {
t.Errorf("Expected 5, got %v", x)
}
if ok, _ := field.Set(v, "B", 15); ok != field.SetAsValue {
t.Errorf("field.Set failed: %v", ok)
}
x, _ = field.Get(a, storage.PathName{"B"})
if x.Interface() != 15 {
t.Errorf("Expected 15, got %v", x)
}
// C field.
if ok, _ := field.Set(v, "C", []int{7}); ok != field.SetAsValue {
t.Errorf("Failed to set C: %v", ok)
}
x, _ = field.Get(a, storage.PathName{"C", "0"})
if x.Interface() != 7 {
t.Errorf("Expected 6, got %v", x)
}
p, _ := field.Get(a, storage.PathName{"C"})
if ok, _ := field.Set(p, "0", 8); ok != field.SetAsValue {
t.Errorf("Failed to set C: %v", ok)
}
x, _ = field.Get(a, storage.PathName{"C", "0"})
if x.Interface() != 8 {
t.Errorf("Expected 8, got %v", x)
}
p, _ = field.Get(a, storage.PathName{"C"})
if ok, _ := field.Set(p, "@", 9); ok != field.SetAsValue {
t.Errorf("Failed to set C")
}
x, _ = field.Get(a, storage.PathName{"C", "1"})
if x.Interface() != 9 {
t.Errorf("Expected 9, got %v", x)
}
// D field.
if ok, _ := field.Set(v, "D", map[string]int{"a": 1}); ok != field.SetAsValue {
t.Errorf("Failed to set D")
}
x, _ = field.Get(a, storage.PathName{"D", "a"})
if x.Interface() != 1 {
t.Errorf("Expected 1, got %v", x)
}
p, _ = field.Get(a, storage.PathName{"D"})
if ok, _ := field.Set(p, "a", 2); ok != field.SetAsValue {
t.Errorf("Failed to set D")
}
x, _ = field.Get(a, storage.PathName{"D", "a"})
if x.Interface() != 2 {
t.Errorf("Expected 2, got %v", x)
}
// E field.
id := storage.NewID()
ok, id2 := field.Set(v, "E", id)
if ok != field.SetAsValue || id2 != id {
t.Errorf("Failed to set E: %b, %s/%s", ok, id, id2)
}
// F field.
p, _ = field.Get(a, storage.PathName{"F"})
ok, fid := field.Set(p, "0", "fail")
if ok != field.SetAsID {
t.Errorf("Failed to set F: %v", x)
}
x, _ = field.Get(a, storage.PathName{"F", "0"})
if x.Interface() != fid {
t.Errorf("Expected %v, got %v", id, x.Interface())
}
// G field.
p, _ = field.Get(a, storage.PathName{"G"})
ok, fid = field.Set(p, "key", "fail")
if ok != field.SetAsID {
t.Errorf("Failed to set G")
}
x, _ = field.Get(a, storage.PathName{"G", "key"})
if x.Interface() != fid {
t.Errorf("Expected %v, got %v", id, x)
}
}
func TestRemoveField(t *testing.T) {
a := &A{
B: 5,
C: []int{6, 7},
D: map[string]int{"a": 8, "b": 9},
E: storage.NewID(),
F: []storage.ID{storage.NewID()},
G: map[string]storage.ID{"a": storage.NewID()},
}
v := reflect.ValueOf(a)
if field.Remove(v, "B") {
t.Errorf("Unexpected success")
}
p, _ := field.Get(a, storage.PathName{"C"})
if field.Remove(p, "0") {
t.Errorf("Unexpected success")
}
p, _ = field.Get(a, storage.PathName{"D"})
if !field.Remove(p, "a") {
t.Errorf("Unexpected failure")
}
x, s := field.Get(a, storage.PathName{"D", "a"})
if !pathEq(storage.PathName{"a"}, s) {
t.Errorf("Unexpected value: %v", x)
}
}