Fix new vdl convert tests to work again.

A variety of changes, including float64/float32 conversions,
retaining reflect type info in ValueFromReflect, and fixing a
MimicValue bug wrt zero base fields.

Change-Id: I35f257766f66fd9bf916e8567f8595c16216a22e
diff --git a/vdl/new_convert_test.go b/vdl/new_convert_test.go
index 7b03157..57573a5 100644
--- a/vdl/new_convert_test.go
+++ b/vdl/new_convert_test.go
@@ -18,10 +18,10 @@
 	for _, entry := range vdltest.AllPass() {
 		rvTargetPtr := reflect.New(entry.Target.Type())
 		if err := vdl.Convert(rvTargetPtr.Interface(), entry.Source.Interface()); err != nil {
-			t.Errorf("%s: error %v", entry.Name(), err)
+			t.Errorf("%s: Convert failed: %v", entry.Name(), err)
 		}
-		if !vdl.DeepEqualReflect(rvTargetPtr.Elem(), entry.Target) {
-			t.Errorf("%[1]s:\nGOT  %[2]v\nWANT %[3]v", entry.Name(), rvTargetPtr.Elem(), entry.Target)
+		if got, want := rvTargetPtr.Elem(), entry.Target; !vdl.DeepEqualReflect(got, want) {
+			t.Errorf("%s\nGOT  %v\nWANT %v", entry.Name(), got, want)
 		}
 	}
 }
@@ -30,7 +30,7 @@
 	for _, entry := range vdltest.AllFail() {
 		rvTargetPtr := reflect.New(entry.Target.Type())
 		if err := vdl.Convert(rvTargetPtr.Interface(), entry.Source.Interface()); err == nil {
-			t.Errorf("%s: expected failure", entry.Name())
+			t.Errorf("%s: Convert passed, wanted failure", entry.Name())
 		}
 	}
 }
diff --git a/vdl/new_value_reader_test.go b/vdl/new_value_reader_test.go
index 4ada3cd..fed2366 100644
--- a/vdl/new_value_reader_test.go
+++ b/vdl/new_value_reader_test.go
@@ -13,15 +13,15 @@
 	"v.io/v23/vdl/vdltest"
 )
 
-func TestValueReadNew(t *testing.T) {
+func TestValueReader(t *testing.T) {
 	for _, entry := range vdltest.ToEntryValues(vdltest.AllPass()) {
 		out := vdl.ZeroValue(entry.Target.Type())
 		if err := out.VDLRead(entry.Source.Decoder()); err != nil {
-			t.Errorf("%s: error in ValueRead: %v", entry.Name(), err)
+			t.Errorf("%s: VDLRead failed: %v", entry.Name(), err)
 			continue
 		}
-		if !vdl.EqualValue(entry.Target, out) {
-			t.Errorf("%s: got %v, want %v", entry.Name(), out, entry.Target)
+		if got, want := out, entry.Target; !vdl.EqualValue(got, want) {
+			t.Errorf("%s\nGOT  %v\nWANT %v", entry.Name(), got, want)
 		}
 	}
 }
diff --git a/vdl/pipe.go b/vdl/pipe.go
index cebaa18..0daea79 100644
--- a/vdl/pipe.go
+++ b/vdl/pipe.go
@@ -8,6 +8,7 @@
 	"errors"
 	"fmt"
 	"math"
+	"reflect"
 	"sync"
 )
 
@@ -25,6 +26,14 @@
 	return dec.Close(Read(dec, dst))
 }
 
+func convertPipeReflect(dst, src reflect.Value) error {
+	enc, dec := newPipe()
+	go func() {
+		enc.Close(WriteReflect(enc, src))
+	}()
+	return dec.Close(ReadReflect(dec, dst))
+}
+
 type pipeStackEntry struct {
 	Type       *Type
 	NextOp     pipeOp
diff --git a/vdl/target.go b/vdl/target.go
index 517ebb3..cc9af88 100644
--- a/vdl/target.go
+++ b/vdl/target.go
@@ -172,7 +172,7 @@
 		return ZeroValue(AnyType), nil
 	}
 	var result *Value
-	err := convertPipe(&result, rv.Interface())
+	err := convertPipeReflect(reflect.ValueOf(&result), rv)
 	return result, err
 }
 
diff --git a/vdl/value.go b/vdl/value.go
index 979428c..20c0a8c 100644
--- a/vdl/value.go
+++ b/vdl/value.go
@@ -354,7 +354,15 @@
 	case int64:
 		return arep == b.rep.(int64)
 	case float64:
-		return arep == b.rep.(float64)
+		// Float32 is represented as float64, but we must convert to float32 for
+		// equality comparisons.  Otherwise a single float32 may be represented as
+		// different values, causing equality failures.
+		switch a.t.kind {
+		case Float32:
+			return float32(arep) == float32(b.rep.(float64))
+		default:
+			return arep == b.rep.(float64)
+		}
 	case string:
 		return arep == b.rep.(string)
 	case enumIndex:
diff --git a/vdl/value_rep.go b/vdl/value_rep.go
index d481fdf..a83151c 100644
--- a/vdl/value_rep.go
+++ b/vdl/value_rep.go
@@ -118,8 +118,14 @@
 // fastKeyRep returns a representation of key that may be used in a regular Go
 // map.  It's only called on keys where useFastIndex returns true.
 func fastKeyRep(key *Value) interface{} {
-	if key.t.IsBytes() {
-		// Turn []byte into a string so that it can be used as a map key.
+	switch {
+	case key.Kind() == Float32:
+		// Float32 is represented as float64 in vdl.Value, but we must convert to
+		// float32 to ensure map lookups work with the correct precision.  Otherwise
+		// a single float32 may be reprsesented as different keys.
+		return float32(key.rep.(float64))
+	case key.t.IsBytes():
+		// Convert []byte into a string so that it can be used as a map key.
 		return string(key.Bytes())
 	}
 	return key.rep
diff --git a/vdl/vdltest/.api b/vdl/vdltest/.api
index 5bfc25c..9844374 100644
--- a/vdl/vdltest/.api
+++ b/vdl/vdltest/.api
@@ -1660,7 +1660,9 @@
 pkg vdltest, type EntryValue struct
 pkg vdltest, type EntryValue struct, Label string
 pkg vdltest, type EntryValue struct, Source *vdl.Value
+pkg vdltest, type EntryValue struct, SourceLabel string
 pkg vdltest, type EntryValue struct, Target *vdl.Value
+pkg vdltest, type EntryValue struct, TargetLabel string
 pkg vdltest, type GenMode int
 pkg vdltest, type TypeGenerator struct
 pkg vdltest, type TypeGenerator struct, BaseTypesPerKind []int
diff --git a/vdl/vdltest/entry.go b/vdl/vdltest/entry.go
index 4ca27c6..9d55eba 100644
--- a/vdl/vdltest/entry.go
+++ b/vdl/vdltest/entry.go
@@ -36,14 +36,24 @@
 // EntryValue is like Entry, but represents the target and source values as
 // *vdl.Value, rather than interface{}.
 type EntryValue struct {
-	Label  string
-	Target *vdl.Value
-	Source *vdl.Value
+	Label       string
+	TargetLabel string
+	Target      *vdl.Value
+	SourceLabel string
+	Source      *vdl.Value
 }
 
 // Name returns the name of the EntryValue.
 func (e EntryValue) Name() string {
-	return e.Label + " Target(" + e.Target.String() + ") Source(" + e.Source.String() + ")"
+	tLabel := e.TargetLabel
+	if tLabel == "" {
+		tLabel = e.Target.String()
+	}
+	sLabel := e.SourceLabel
+	if sLabel == "" {
+		sLabel = e.Source.String()
+	}
+	return e.Label + " Target(" + tLabel + ") Source(" + sLabel + ")"
 }
 
 // ToEntryValue converts the Entry e into an EntryValue.
@@ -57,9 +67,11 @@
 		panic(err)
 	}
 	return EntryValue{
-		Label:  e.Label,
-		Target: target,
-		Source: source,
+		Label:       e.Label,
+		TargetLabel: e.TargetLabel,
+		Target:      target,
+		SourceLabel: e.SourceLabel,
+		Source:      source,
 	}
 }
 
diff --git a/vdl/vdltest/entry_generator.go b/vdl/vdltest/entry_generator.go
index f786ad3..4e85040 100644
--- a/vdl/vdltest/entry_generator.go
+++ b/vdl/vdltest/entry_generator.go
@@ -146,7 +146,11 @@
 	ev := g.genPass("Zero", vdl.ZeroValue(tt), g.ZeroEntryLimit, sourceAll)
 	if tt.Kind() == vdl.Optional {
 		// Add entry to convert from any(nil) to optional(nil).
-		ev = append(ev, EntryValue{"NilAny", vdl.ZeroValue(tt), vdl.ZeroValue(vdl.AnyType)})
+		ev = append(ev, EntryValue{
+			Label:  "NilAny",
+			Target: vdl.ZeroValue(tt),
+			Source: vdl.ZeroValue(vdl.AnyType),
+		})
 	}
 	// Handle some special-cases.
 	switch {
@@ -256,7 +260,11 @@
 	var ev []EntryValue
 	if mode.Canonical() {
 		// Add the canonical identity conversion for each target value.
-		ev = append(ev, EntryValue{label, target, target})
+		ev = append(ev, EntryValue{
+			Label:  label,
+			Target: target,
+			Source: target,
+		})
 	}
 	// Add up to limit conversion entries.  The strategy is to add an entry for
 	// each source type where we can create a value that can convert to the
@@ -286,7 +294,11 @@
 				break
 			}
 			num++
-			ev = append(ev, EntryValue{label, target, source})
+			ev = append(ev, EntryValue{
+				Label:  label,
+				Target: target,
+				Source: source,
+			})
 		}
 	}
 	return ev
diff --git a/vdl/vdltest/mimic_value.go b/vdl/vdltest/mimic_value.go
index e34cee3..70d3aed 100644
--- a/vdl/vdltest/mimic_value.go
+++ b/vdl/vdltest/mimic_value.go
@@ -315,15 +315,15 @@
 	value := vdl.ZeroValue(tt)
 	for ix := 0; ix < base.Type().NumField(); ix++ {
 		baseField := base.StructField(ix)
-		if baseField.IsZero() {
-			// Skip zero base fields.  It's fine for the base field to be missing from
-			// tt, as long as the base field is zero, since Convert(dst, src) sets all
-			// dst (which has type base.Type) fields to zero before setting each
-			// matching field in src (which has type tt).
-			continue
-		}
 		ttField, ttIndex := tt.FieldByName(base.Type().Field(ix).Name)
 		if ttIndex == -1 {
+			if baseField.IsZero() {
+				// Skip zero base fields.  It's fine for the base field to be missing
+				// from tt, as long as the base field is zero, since Convert(dst, src)
+				// sets all dst (which has type base.Type) fields to zero before setting
+				// each matching field in src (which has type tt).
+				continue
+			}
 			// This is a non-zero base field that doesn't exist in tt.  There's no way
 			// to create a value of type tt that converts to exactly the base value.
 			return nil
diff --git a/vdl/vdltest/vdltest.vdl.go b/vdl/vdltest/vdltest.vdl.go
index df9c33c..48e0bef 100644
--- a/vdl/vdltest/vdltest.vdl.go
+++ b/vdl/vdltest/vdltest.vdl.go
@@ -39270,25 +39270,15 @@
 		Label:       "Zero",
 		TargetLabel: "VStructDepth1_Any{}",
 		Target:      VStructDepth1_Any{},
-		SourceLabel: "VStructDepth2_All{}",
-		Source: VStructDepth2_All{
-			F0: VArray2_TypeObject{
-				vdl.AnyType,
-				vdl.AnyType,
-			},
-			F8: VStructDepth1_All{
-				F5: vdl.AnyType,
-			},
-			F10: VUnionDepth1_AllF0{},
-			F11: VUnionDepth1_Float64F29{},
-		},
+		SourceLabel: "?VStructEmpty{}",
+		Source:      &VStructEmpty{},
 	},
 	{
 		Label:       "Zero",
 		TargetLabel: "VStructDepth1_Any{}",
 		Target:      VStructDepth1_Any{},
-		SourceLabel: "?VStructEmpty{}",
-		Source:      &VStructEmpty{},
+		SourceLabel: "VStructEmpty{}",
+		Source:      VStructEmpty{},
 	},
 	{
 		IsCanonical: true,
@@ -47546,8 +47536,12 @@
 				vdl.AnyType,
 			},
 		},
-		SourceLabel: "VStructDepth1_All{}",
+		SourceLabel: "VStructDepth1_All{F0: VArray2_TypeObject{}}",
 		Source: VStructDepth1_All{
+			F0: VArray2_TypeObject{
+				vdl.AnyType,
+				vdl.AnyType,
+			},
 			F5: vdl.AnyType,
 		},
 	},
@@ -47560,8 +47554,13 @@
 				vdl.AnyType,
 			},
 		},
-		SourceLabel: "VStructDepth1_Any{}",
-		Source:      VStructDepth1_Any{},
+		SourceLabel: "VStructDepth1_Any{F0: VArray2_TypeObject{}}",
+		Source: VStructDepth1_Any{
+			F0: VArray2_TypeObject{
+				vdl.AnyType,
+				vdl.AnyType,
+			},
+		},
 	},
 	{
 		IsCanonical: true,
@@ -57467,8 +57466,10 @@
 		Label:       "Zero",
 		TargetLabel: "VStructDepth3_VArray1_Set_VEnumBcd{}",
 		Target:      VStructDepth3_VArray1_Set_VEnumBcd{},
-		SourceLabel: "VStructDepth1_Any{}",
-		Source:      VStructDepth1_Any{},
+		SourceLabel: "VStructDepth1_Any{F0: VArray1_Set_VEnumBcd{}}",
+		Source: VStructDepth1_Any{
+			F0: VArray1_Set_VEnumBcd{},
+		},
 	},
 	{
 		IsCanonical: true,
@@ -74904,28 +74905,17 @@
 		Label:       "Zero",
 		TargetLabel: "XStructDepth1_Any{}",
 		Target:      XStructDepth1_Any{},
-		SourceLabel: "?XStructDepth3_XArray1_Set_XEnumBcd{}",
-		Source:      &XStructDepth3_XArray1_Set_XEnumBcd{},
+		SourceLabel: "XStructDepth1_All{}",
+		Source: XStructDepth1_All{
+			F5: vdl.AnyType,
+		},
 	},
 	{
 		Label:       "Zero",
 		TargetLabel: "XStructDepth1_Any{}",
 		Target:      XStructDepth1_Any{},
-		SourceLabel: "XStructDepth3_All{}",
-		Source: XStructDepth3_All{
-			F4: XStructDepth2_All{
-				F0: XArray2_TypeObject{
-					vdl.AnyType,
-					vdl.AnyType,
-				},
-				F8: XStructDepth1_All{
-					F5: vdl.AnyType,
-				},
-				F10: XUnionDepth1_AllF0{},
-				F11: XUnionDepth1_Float64F29{},
-			},
-			F5: XUnionDepth2_AllF0{},
-		},
+		SourceLabel: "?XStructEmpty{}",
+		Source:      &XStructEmpty{},
 	},
 	{
 		IsCanonical: true,
diff --git a/vdl/vdltest/ventry_pass_gen.vdl b/vdl/vdltest/ventry_pass_gen.vdl
index 6ee1ac6..fa285f0 100644
--- a/vdl/vdltest/ventry_pass_gen.vdl
+++ b/vdl/vdltest/ventry_pass_gen.vdl
@@ -12,8 +12,8 @@
 // ------------------------------------------------------------------------------------------
 // |             |  Total  | +Max | +Min |-Max |-Min | Full  |NilAny|Random | Zero  |isZero |
 // ------------------------------------------------------------------------------------------
-// |total        |1040,1717|23,141|23,226|15,65|15,94|349,331|  0, 8|263,240|352,612|352,452| [!can max=14]
-// |isZero       | 352, 452| 0,  0| 0,  0| 0, 0| 0, 0|  0,  2|  0, 8|  0,  0|352,442|352,452| [!can max=3]
+// |total        |1040,1717|23,141|23,226|15,65|15,94|349,331|  0, 8|263,240|352,612|352,449| [!can max=14]
+// |isZero       | 352, 449| 0,  0| 0,  0| 0, 0| 0, 0|  0,  2|  0, 8|  0,  0|352,439|352,449| [!can max=3]
 // ------------------------------------------------------------------------------------------
 // |any          |   1,   8| 0,  0| 0,  0| 0, 0| 0, 0|  0,  0|  0, 8|  0,  0|  1,  0|  1,  8| [nil=9]
 // |optional     |  21,  62| 0,  0| 0,  0| 0, 0| 0, 0|  8,  4|  0, 0|  5,  4|  8, 54|  8, 11| [!can max=3] [nil=19]
@@ -35,10 +35,10 @@
 // |list         | 176, 348| 0,  0| 0,  0| 0, 0| 0, 0| 66, 93|  0, 0| 44, 62| 66,193| 66,132| [!can max=2] [len max=3]
 // |set          | 100, 116| 0,  0| 0,  0| 0, 0| 0, 0| 38, 32|  0, 0| 24, 20| 38, 64| 38, 64| [!can max=2] [len max=3]
 // |map          | 102, 106| 0,  0| 0,  0| 0, 0| 0, 0| 38, 28|  0, 0| 26, 16| 38, 62| 38, 62| [!can max=2] [len max=3]
-// |struct       | 193, 208| 0,  0| 0,  0| 0, 0| 0, 0| 67, 63|  0, 0| 57, 50| 69, 95| 69, 96| [!can max=2]
+// |struct       | 193, 208| 0,  0| 0,  0| 0, 0| 0, 0| 67, 63|  0, 0| 57, 50| 69, 95| 69, 93| [!can max=2]
 // |union        | 177, 187| 0,  0| 0,  0| 0, 0| 0, 0| 62, 62|  0, 0| 52, 52| 63, 73| 63, 16| [!can max=2]
 // ------------------------------------------------------------------------------------------
-// |IsNamed      | 761,1075|13, 78|13,128| 9,37| 9,56|258,226|  0, 0|199,180|260,370|260,277| [!can max=14]
+// |IsNamed      | 761,1075|13, 78|13,128| 9,37| 9,56|258,226|  0, 0|199,180|260,370|260,274| [!can max=14]
 // |IsUnnamed    | 279, 642|10, 63|10, 98| 6,28| 6,38| 91,105|  0, 8| 64, 60| 92,242| 92,175| [!can max=11]
 // |IsBytes      |  18,  15| 0,  0| 0,  0| 0, 0| 0, 0|  6,  4|  0, 0|  6,  2|  6,  9|  6,  3| [!can max=2]
 // |IsPartOfCycle|   9,   4| 0,  0| 0,  0| 0, 0| 0, 0|  3,  0|  0, 0|  3,  0|  3,  4|  3,  4| [!can max=2]
@@ -3352,8 +3352,8 @@
 	},
 	// Canonical
 	{ true, `Zero`, `VStructDepth1_Any{}`, VStructDepth1_Any{}, `VStructDepth1_Any{}`, VStructDepth1_Any{} },
-	{ false, `Zero`, `VStructDepth1_Any{}`, VStructDepth1_Any{}, `VStructDepth2_All{}`, VStructDepth2_All{} },
 	{ false, `Zero`, `VStructDepth1_Any{}`, VStructDepth1_Any{}, `?VStructEmpty{}`, ?VStructEmpty{} },
+	{ false, `Zero`, `VStructDepth1_Any{}`, VStructDepth1_Any{}, `VStructEmpty{}`, VStructEmpty{} },
 	// Canonical
 	{ true, `Full`,
 	  `VStructDepth1_Any{F0: int64(-123)}`,
@@ -6469,14 +6469,14 @@
 	{ false, `Zero`,
 	  `VStructDepth2_VArray2_TypeObject{}`,
 	  VStructDepth2_VArray2_TypeObject{},
-	  `VStructDepth1_All{}`,
-	  VStructDepth1_All{},
+	  `VStructDepth1_All{F0: VArray2_TypeObject{}}`,
+	  VStructDepth1_All{F0: VArray2_TypeObject{}},
 	},
 	{ false, `Zero`,
 	  `VStructDepth2_VArray2_TypeObject{}`,
 	  VStructDepth2_VArray2_TypeObject{},
-	  `VStructDepth1_Any{}`,
-	  VStructDepth1_Any{},
+	  `VStructDepth1_Any{F0: VArray2_TypeObject{}}`,
+	  VStructDepth1_Any{F0: VArray2_TypeObject{}},
 	},
 	// Canonical
 	{ true, `Full`,
@@ -8730,8 +8730,8 @@
 	{ false, `Zero`,
 	  `VStructDepth3_VArray1_Set_VEnumBcd{}`,
 	  VStructDepth3_VArray1_Set_VEnumBcd{},
-	  `VStructDepth1_Any{}`,
-	  VStructDepth1_Any{},
+	  `VStructDepth1_Any{F0: VArray1_Set_VEnumBcd{}}`,
+	  VStructDepth1_Any{F0: VArray1_Set_VEnumBcd{}},
 	},
 	// Canonical
 	{ true, `Full`,
diff --git a/vdl/vdltest/xentry_pass_gen.vdl b/vdl/vdltest/xentry_pass_gen.vdl
index 19e9d27..f994f92 100644
--- a/vdl/vdltest/xentry_pass_gen.vdl
+++ b/vdl/vdltest/xentry_pass_gen.vdl
@@ -2498,13 +2498,8 @@
 	},
 	// Canonical
 	{ true, `Zero`, `XStructDepth1_Any{}`, XStructDepth1_Any{}, `XStructDepth1_Any{}`, XStructDepth1_Any{} },
-	{ false, `Zero`,
-	  `XStructDepth1_Any{}`,
-	  XStructDepth1_Any{},
-	  `?XStructDepth3_XArray1_Set_XEnumBcd{}`,
-	  ?XStructDepth3_XArray1_Set_XEnumBcd{},
-	},
-	{ false, `Zero`, `XStructDepth1_Any{}`, XStructDepth1_Any{}, `XStructDepth3_All{}`, XStructDepth3_All{} },
+	{ false, `Zero`, `XStructDepth1_Any{}`, XStructDepth1_Any{}, `XStructDepth1_All{}`, XStructDepth1_All{} },
+	{ false, `Zero`, `XStructDepth1_Any{}`, XStructDepth1_Any{}, `?XStructEmpty{}`, ?XStructEmpty{} },
 	// Canonical
 	{ true, `Full`,
 	  `XStructDepth1_Any{F0: int64(-123)}`,
diff --git a/vom/xdecoder_test.go b/vom/xdecoder_test.go
index ff885ef..7d3db6b 100644
--- a/vom/xdecoder_test.go
+++ b/vom/xdecoder_test.go
@@ -41,7 +41,7 @@
 			vv, err := vdl.ValueFromReflect(test.Value)
 			if err != nil {
 				t.Errorf("%s: ValueFromReflect failed: %v", test.Name(), err)
-				continue
+				return
 			}
 			vvWant := reflect.ValueOf(vv)
 			testXDecoder(t, "[new *vdl.Value]", test, vvWant)