| // Copyright 2015 The Vanadium 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 vom_test |
| |
| import ( |
| "bytes" |
| "fmt" |
| "io" |
| "reflect" |
| "sync" |
| "testing" |
| |
| "v.io/v23/vdl" |
| "v.io/v23/vom" |
| "v.io/v23/vom/vomtest" |
| |
| // Import verror to ensure that interface tests result in *verror.E |
| _ "v.io/v23/verror" |
| ) |
| |
| // TODO(toddw): Add all useful tests from decoder_test.go |
| |
| var ( |
| rtIface = reflect.TypeOf((*interface{})(nil)).Elem() |
| rtValue = reflect.TypeOf(vdl.Value{}) |
| ) |
| |
| func TestXDecoder(t *testing.T) { |
| // The decoder tests take a long time, so we run them concurrently. |
| var pending sync.WaitGroup |
| for _, test := range vomtest.AllPass() { |
| pending.Add(1) |
| go func(test vomtest.Entry) { |
| defer pending.Done() |
| testXDecoder(t, "[go value]", test, rvPtrValue(test.Value)) |
| testXDecoder(t, "[go iface]", test, rvPtrIface(test.Value)) |
| vv, err := vdl.ValueFromReflect(test.Value) |
| if err != nil { |
| t.Errorf("%s: ValueFromReflect failed: %v", test.Name(), err) |
| return |
| } |
| vvWant := reflect.ValueOf(vv) |
| testXDecoder(t, "[new *vdl.Value]", test, vvWant) |
| testXDecoderFunc(t, "[zero vdl.Value]", test, vvWant, func() reflect.Value { |
| return reflect.ValueOf(vdl.ZeroValue(vv.Type())) |
| }) |
| }(test) |
| } |
| pending.Wait() |
| } |
| |
| func rvPtrValue(rv reflect.Value) reflect.Value { |
| result := reflect.New(rv.Type()) |
| result.Elem().Set(rv) |
| return result |
| } |
| |
| func rvPtrIface(rv reflect.Value) reflect.Value { |
| result := reflect.New(rtIface) |
| result.Elem().Set(rv) |
| return result |
| } |
| |
| func testXDecoder(t *testing.T, pre string, test vomtest.Entry, rvWant reflect.Value) { |
| testXDecoderFunc(t, pre, test, rvWant, func() reflect.Value { |
| return reflect.New(rvWant.Type().Elem()) |
| }) |
| // TODO(toddw): Add tests that start with a randomly-set value. |
| } |
| |
| func testXDecoderFunc(t *testing.T, pre string, test vomtest.Entry, rvWant reflect.Value, rvNew func() reflect.Value) { |
| readEOF := make([]byte, 1) |
| for _, mode := range vom.AllReadModes { |
| // Test vom.NewXDecoder. |
| { |
| name := fmt.Sprintf("%s (%s) %s", pre, mode, test.Name()) |
| rvGot := rvNew() |
| reader := mode.TestReader(bytes.NewReader(test.Bytes())) |
| dec := vom.NewDecoder(reader) |
| if err := dec.Decode(rvGot.Interface()); err != nil { |
| t.Errorf("%s: Decode failed: %v", name, err) |
| return |
| } |
| if !vdl.DeepEqualReflect(rvGot, rvWant) { |
| t.Errorf("%s\nGOT %v\nWANT %v", name, rvGot, rvWant) |
| return |
| } |
| if n, err := reader.Read(readEOF); n != 0 || err != io.EOF { |
| t.Errorf("%s: reader got (%d,%v), want (0,EOF)", name, n, err) |
| } |
| } |
| // Test vom.NewXDecoderWithTypeDecoder |
| { |
| name := fmt.Sprintf("%s (%s with TypeDecoder) %s", pre, mode, test.Name()) |
| rvGot := rvNew() |
| readerT := mode.TestReader(bytes.NewReader(test.TypeBytes())) |
| decT := vom.NewTypeDecoder(readerT) |
| decT.Start() |
| reader := mode.TestReader(bytes.NewReader(test.ValueBytes())) |
| dec := vom.NewDecoderWithTypeDecoder(reader, decT) |
| err := dec.Decode(rvGot.Interface()) |
| decT.Stop() |
| if err != nil { |
| t.Errorf("%s: Decode failed: %v", name, err) |
| return |
| } |
| if !vdl.DeepEqualReflect(rvGot, rvWant) { |
| t.Errorf("%s\nGOT %v\nWANT %v", name, rvGot, rvWant) |
| return |
| } |
| if n, err := reader.Read(readEOF); n != 0 || err != io.EOF { |
| t.Errorf("%s: reader got (%d,%v), want (0,EOF)", name, n, err) |
| } |
| if n, err := readerT.Read(readEOF); n != 0 || err != io.EOF { |
| t.Errorf("%s: readerT got (%d,%v), want (0,EOF)", name, n, err) |
| } |
| } |
| } |
| // Test single-shot vom.Decode twice, to ensure we test the cache hit case. |
| for i := 0; i < 2; i++ { |
| name := fmt.Sprintf("%s (single-shot %d) %s", pre, i, test.Name()) |
| rvGot := rvNew() |
| if err := vom.Decode(test.Bytes(), rvGot.Interface()); err != nil { |
| t.Errorf("%s: Decode failed: %v", name, err) |
| return |
| } |
| if !vdl.DeepEqualReflect(rvGot, rvWant) { |
| t.Errorf("%s\nGOT %v\nWANT %v", name, rvGot, rvWant) |
| return |
| } |
| } |
| } |