Make put of nil maps (and a few other cases) work pre-VOM2

This involves more tests of the field package, a rewrite of deep equals, a small hack to make slice settable (which will go away for VOM2) and a few other changes.

Change-Id: Ie2048a934570caa0b823c3d0cb149b0c5fc13fdd
diff --git a/services/store/memstore/field/reflect.go b/services/store/memstore/field/reflect.go
index c12f667..5a76e29 100644
--- a/services/store/memstore/field/reflect.go
+++ b/services/store/memstore/field/reflect.go
@@ -48,6 +48,10 @@
 	SetAsID
 )
 
+const (
+	SliceAppendSuffix = "@"
+)
+
 var (
 	nullID    storage.ID
 	nullValue reflect.Value
@@ -131,13 +135,13 @@
 //
 // Here are the possible cases:
 //
-// 1. setFieldFailed if the operation failed because the value has the wrong type
+// 1. SetFailed if the operation failed because the value has the wrong type
 //    or the path doesn't exist.
 //
-// 2. setFieldAsValue if the operation was successful, and the value xval was
+// 2. SetAsValue if the operation was successful, and the value xval was
 //    stored.  The returned storage.ID is null.
 //
-// 3. setFieldAsId if the operation was successful, but the type of the field is
+// 3. SetAsId if the operation was successful, but the type of the field is
 //    storage.ID and xval does not have type storage.ID.  In this case, the value
 //    xval is not stored; the storage.ID is returned instead.  If the field does
 //    not already exist, a new storage.ID is created (and returned).
@@ -157,8 +161,10 @@
 		return setMapField(v, name, xval)
 	case reflect.Array, reflect.Slice:
 		return setSliceField(v, name, xval)
+	case reflect.Struct:
+		return setStructField(v, name, xval)
 	default:
-		return setRegularField(v, name, xval)
+		return SetFailed, nullID
 	}
 }
 
@@ -168,9 +174,6 @@
 	if tyKey.Kind() != reflect.String {
 		return SetFailed, nullID
 	}
-	if v.IsNil() {
-		v.Set(reflect.MakeMap(tyV))
-	}
 	key := reflect.ValueOf(name).Convert(tyKey)
 	r, x, id := coerceValue(tyV.Elem(), v.MapIndex(key), xval)
 	if r == SetFailed {
@@ -181,11 +184,13 @@
 }
 
 func setSliceField(v reflect.Value, field string, xval interface{}) (SetResult, storage.ID) {
-	if field == "@" {
+	if field == SliceAppendSuffix {
 		r, x, id := coerceValue(v.Type().Elem(), nullValue, xval)
 		if r == SetFailed {
 			return SetFailed, nullID
 		}
+		// This can panic if v is not settable. It is a requirement that users of this method
+		// ensure that it is settable.
 		v.Set(reflect.Append(v, x))
 		return r, id
 	}
@@ -202,16 +207,17 @@
 	return r, id
 }
 
-func setRegularField(v reflect.Value, name string, xval interface{}) (SetResult, storage.ID) {
-	v = findNextField(v, name)
-	if !v.CanSet() {
+func setStructField(v reflect.Value, name string, xval interface{}) (SetResult, storage.ID) {
+	field, found := v.Type().FieldByName(name)
+	if !found {
 		return SetFailed, nullID
 	}
-	r, x, id := coerceValue(v.Type(), v, xval)
+	fieldVal := v.FieldByName(name)
+	r, x, id := coerceValue(field.Type, fieldVal, xval)
 	if r == SetFailed {
 		return SetFailed, nullID
 	}
-	v.Set(x)
+	fieldVal.Set(x)
 	return r, id
 }
 
diff --git a/services/store/memstore/field/reflect_test.go b/services/store/memstore/field/reflect_test.go
index 517bff7..5c85253 100644
--- a/services/store/memstore/field/reflect_test.go
+++ b/services/store/memstore/field/reflect_test.go
@@ -129,7 +129,132 @@
 	}
 }
 
-func TestSetField(t *testing.T) {
+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},
diff --git a/services/store/memstore/state/mutable_snapshot.go b/services/store/memstore/state/mutable_snapshot.go
index c95d9cd..7b7c675 100644
--- a/services/store/memstore/state/mutable_snapshot.go
+++ b/services/store/memstore/state/mutable_snapshot.go
@@ -400,7 +400,7 @@
 		return sn.putTagsValue(checker, path, suffix[1:], c, v)
 	}
 	value := deepcopy(c.Value)
-	p, s := field.Get(value, suffix)
+	p, s := field.Get(makeInnerReference(value), suffix)
 	if len(s) != 0 {
 		return nil, ErrNotFound
 	}
diff --git a/services/store/memstore/state/mutable_snapshot_test.go b/services/store/memstore/state/mutable_snapshot_test.go
index abeea27..62ace5d 100644
--- a/services/store/memstore/state/mutable_snapshot_test.go
+++ b/services/store/memstore/state/mutable_snapshot_test.go
@@ -31,6 +31,7 @@
 	stat, err := sn.Put(rootPublicID, storage.ParsePath(path), dir)
 	if err != nil || stat == nil {
 		t.Errorf("%s(%d): mkdir %s: %s", file, line, path, err)
+		return storage.ID{}, dir
 	}
 	m, ok := sn.mutations.Delta[stat.ID]
 	if !ok {
@@ -264,3 +265,27 @@
 	expectNotExists(t, sn, id5)
 	checkInRefs(t, sn)
 }
+
+// Tests that nil maps are converted to empty maps.
+func TestPutToNilMap(t *testing.T) {
+	sn := newMutableSnapshot(rootPublicID)
+
+	var m map[string]interface{}
+	if _, err := sn.Put(rootPublicID, storage.PathName{}, m); err != nil {
+		t.Error("failure during nil map put: ", err)
+	}
+	if _, err := sn.Put(rootPublicID, storage.PathName{"z"}, "z"); err != nil {
+		t.Error("failure during put of child of nil map: ", err)
+	}
+}
+
+// Tests that slices are settable so that we can append.
+func TestAppendToSlice(t *testing.T) {
+	sn := newMutableSnapshot(rootPublicID)
+	if _, err := sn.Put(rootPublicID, storage.ParsePath("/"), []int{}); err != nil {
+		t.Error("failure during put of empty slice: ", err)
+	}
+	if _, err := sn.Put(rootPublicID, storage.ParsePath("/@"), 1); err != nil {
+		t.Error("failure during append to slice: ", err)
+	}
+}
diff --git a/services/store/memstore/state/util.go b/services/store/memstore/state/util.go
index 42e07fe..cb72db1 100644
--- a/services/store/memstore/state/util.go
+++ b/services/store/memstore/state/util.go
@@ -7,22 +7,81 @@
 	"sort"
 
 	"veyron2/storage"
-	"veyron2/vom"
 )
 
+// This function returns an interface with a pointer to the element in val.
+// Note that this is different from returning &val which returns a pointer to
+// val. This is required temporarily before we switch to VOM value so that
+// we can append to slices.
+// TODO(bprosnitz) This is hacky -- remove this when we switch to VOM Value
+func makeInnerReference(val interface{}) interface{} {
+	rv := reflect.ValueOf(val)
+	ptr := reflect.New(rv.Type())
+	ptr.Elem().Set(rv)
+	return ptr.Interface()
+}
+
+func deepcopyReflect(rv reflect.Value) reflect.Value {
+	switch rv.Kind() {
+	case reflect.Array:
+		arr := reflect.New(rv.Type()).Elem()
+		for i := 0; i < rv.Len(); i++ {
+			valcopy := deepcopyReflect(rv.Index(i))
+			arr.Index(i).Set(valcopy)
+		}
+		return arr
+	case reflect.Slice:
+		s := reflect.MakeSlice(rv.Type(), rv.Len(), rv.Cap())
+		for i := 0; i < rv.Len(); i++ {
+			valcopy := deepcopyReflect(rv.Index(i))
+			s.Index(i).Set(valcopy)
+		}
+		ptr := reflect.New(rv.Type())
+		ptr.Elem().Set(s)
+		return ptr.Elem()
+	case reflect.Map:
+		m := reflect.MakeMap(rv.Type())
+		keys := rv.MapKeys()
+		for _, key := range keys {
+			val := rv.MapIndex(key)
+			keycopy := deepcopyReflect(key)
+			valcopy := deepcopyReflect(val)
+			m.SetMapIndex(keycopy, valcopy)
+		}
+		return m
+	case reflect.Struct:
+		s := reflect.New(rv.Type()).Elem()
+		for i := 0; i < rv.NumField(); i++ {
+			valcopy := deepcopyReflect(rv.Field(i))
+			s.Field(i).Set(valcopy)
+		}
+		return s
+	case reflect.Ptr:
+		ptr := reflect.New(rv.Type()).Elem()
+		elem := reflect.New(rv.Type().Elem())
+		ptr.Set(elem)
+		ptr.Elem().Set(deepcopyReflect(rv.Elem()))
+		return ptr
+	case reflect.Interface:
+		intr := reflect.New(rv.Type()).Elem()
+		intr.Set(deepcopyReflect(rv.Elem()))
+		return intr
+	case reflect.Chan, reflect.Func, reflect.UnsafePointer:
+		panic(fmt.Sprintf("deepcopy of kind %v not supported", rv.Kind()))
+	default:
+		// Primitives (copy it so we can't set the original)
+		return reflect.ValueOf(rv.Interface())
+	}
+}
+
 // deepcopy performs a deep copy of a value.  We need this to simulate secondary
 // storage where each time a value is stored, it is copied to secondary storage;
 // and when it is retrieved, it is copied out of secondary storage.
 func deepcopy(v interface{}) interface{} {
-	var buf bytes.Buffer
-	if err := vom.NewEncoder(&buf).Encode(v); err != nil {
-		panic(fmt.Sprintf("Can't encode %v: %s", v, err))
+	if v == nil {
+		return nil
 	}
-	cp := reflect.New(reflect.TypeOf(v)).Elem().Interface()
-	if err := vom.NewDecoder(&buf).Decode(&cp); err != nil {
-		panic(fmt.Sprintf("Can't decode %v: %s", v, err))
-	}
-	return cp
+	return deepcopyReflect(reflect.ValueOf(v)).Interface()
 }
 
 // addIDToSort adds a storage.ID to a sorted array.
diff --git a/services/store/memstore/state/util_test.go b/services/store/memstore/state/util_test.go
index 25fca8a..38653ef 100644
--- a/services/store/memstore/state/util_test.go
+++ b/services/store/memstore/state/util_test.go
@@ -6,6 +6,7 @@
 package state
 
 import (
+	"reflect"
 	"runtime"
 	"testing"
 
@@ -50,3 +51,66 @@
 		t.Errorf("%s(%d): can't remove %s: %s", file, line, path, err)
 	}
 }
+
+func TestDeepcopy(t *testing.T) {
+	type basicTestStruct struct {
+		X int
+	}
+	type compositeHoldingTestStruct struct {
+		A  [2]int
+		Sl []string
+		M  map[string]int
+		St basicTestStruct
+	}
+
+	var intr interface{} = []string{"X"}
+
+	tests := []interface{}{
+		nil,
+		0,
+		true,
+		"str",
+		[3]int{4, 5, 6},
+		[]string{"A", "B"},
+		map[string]int{"A": 4, "B": 3},
+		basicTestStruct{7},
+		&basicTestStruct{7},
+		compositeHoldingTestStruct{
+			[2]int{3, 4},
+			[]string{"A"},
+			map[string]int{"A": 5},
+			basicTestStruct{X: 3},
+		},
+		intr,
+	}
+
+	for _, test := range tests {
+		copiedVal := deepcopy(test)
+		if !reflect.DeepEqual(copiedVal, test) {
+			t.Errorf("failure in deepcopy. Expected %v, got %v", test, copiedVal)
+		}
+	}
+}
+
+func TestDeepcopySliceSettability(t *testing.T) {
+	rvSliceCopy := deepcopyReflect(reflect.ValueOf([]int{3, 4}))
+	if !rvSliceCopy.CanSet() {
+		t.Errorf("can't set slice. This is required for appending to slices")
+	}
+}
+
+func TestDeepcopyNilMap(t *testing.T) {
+	var nilMap map[int]int
+	mapCopy := deepcopy(nilMap)
+	if !reflect.DeepEqual(mapCopy, map[int]int{}) {
+		t.Errorf("expected an empty map, got %v", mapCopy)
+	}
+
+	type structWithMap struct {
+		M map[int]int
+	}
+	s := deepcopy(&structWithMap{})
+	if !reflect.DeepEqual(s, &structWithMap{map[int]int{}}) {
+		t.Errorf("expected an empty map in the struct, got %v", s)
+	}
+}