Просмотр исходного кода

XDR incorrect encoding of uint16; tests and benchmarks

Jakob Borg 11 лет назад
Родитель
Сommit
7633b9672f
7 измененных файлов с 268 добавлено и 5 удалено
  1. 57 0
      xdr/bench_test.go
  2. 53 0
      xdr/bench_xdr_test.go
  3. 51 0
      xdr/encdec_test.go
  4. 57 0
      xdr/encdec_xdr_test.go
  5. 1 1
      xdr/reader.go
  6. 45 0
      xdr/refl_test.go
  7. 4 4
      xdr/writer.go

+ 57 - 0
xdr/bench_test.go

@@ -0,0 +1,57 @@
+// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
+// Use of this source code is governed by an MIT-style license that can be
+// found in the LICENSE file.
+
+package xdr_test
+
+import (
+	"bytes"
+	"testing"
+)
+
+type XDRBenchStruct struct {
+	I1 uint64
+	I2 uint32
+	I3 uint16
+	Bs []byte
+	S  string
+}
+
+var res []byte // no to be optimized away
+var s = XDRBenchStruct{
+	I1: 42,
+	I2: 43,
+	I3: 44,
+	Bs: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18},
+	S:  "Hello World!",
+}
+var e = s.MarshalXDR()
+
+func BenchmarkThisMarshal(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		res = s.MarshalXDR()
+	}
+}
+
+func BenchmarkThisUnmarshal(b *testing.B) {
+	var t XDRBenchStruct
+	for i := 0; i < b.N; i++ {
+		err := t.UnmarshalXDR(e)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func BenchmarkEncode(b *testing.B) {
+	bs := make([]byte, 0, 65536)
+	buf := bytes.NewBuffer(bs)
+
+	for i := 0; i < b.N; i++ {
+		_, err := s.EncodeXDR(buf)
+		if err != nil {
+			b.Fatal(err)
+		}
+		buf.Reset()
+	}
+}

+ 53 - 0
xdr/bench_xdr_test.go

@@ -0,0 +1,53 @@
+// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
+// Use of this source code is governed by an MIT-style license that can be
+// found in the LICENSE file.
+
+package xdr_test
+
+import (
+	"bytes"
+	"io"
+
+	"github.com/calmh/syncthing/xdr"
+)
+
+func (o XDRBenchStruct) EncodeXDR(w io.Writer) (int, error) {
+	var xw = xdr.NewWriter(w)
+	return o.encodeXDR(xw)
+}
+
+func (o XDRBenchStruct) MarshalXDR() []byte {
+	var buf bytes.Buffer
+	var xw = xdr.NewWriter(&buf)
+	o.encodeXDR(xw)
+	return buf.Bytes()
+}
+
+func (o XDRBenchStruct) encodeXDR(xw *xdr.Writer) (int, error) {
+	xw.WriteUint64(o.I1)
+	xw.WriteUint32(o.I2)
+	xw.WriteUint16(o.I3)
+	xw.WriteBytes(o.Bs)
+	xw.WriteString(o.S)
+	return xw.Tot(), xw.Error()
+}
+
+func (o *XDRBenchStruct) DecodeXDR(r io.Reader) error {
+	xr := xdr.NewReader(r)
+	return o.decodeXDR(xr)
+}
+
+func (o *XDRBenchStruct) UnmarshalXDR(bs []byte) error {
+	var buf = bytes.NewBuffer(bs)
+	var xr = xdr.NewReader(buf)
+	return o.decodeXDR(xr)
+}
+
+func (o *XDRBenchStruct) decodeXDR(xr *xdr.Reader) error {
+	o.I1 = xr.ReadUint64()
+	o.I2 = xr.ReadUint32()
+	o.I3 = xr.ReadUint16()
+	o.Bs = xr.ReadBytes()
+	o.S = xr.ReadString()
+	return xr.Error()
+}

+ 51 - 0
xdr/encdec_test.go

@@ -0,0 +1,51 @@
+// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
+// Use of this source code is governed by an MIT-style license that can be
+// found in the LICENSE file.
+
+package xdr_test
+
+import (
+	"bytes"
+	"testing"
+	"testing/quick"
+)
+
+// Contains all supported types
+type TestStruct struct {
+	I    int
+	I16  int16
+	UI16 uint16
+	I32  int32
+	UI32 uint32
+	I64  int64
+	UI64 uint64
+	BS   []byte
+	S    string
+}
+
+func TestEncDec(t *testing.T) {
+	fn := func(t0 TestStruct) bool {
+		bs := t0.MarshalXDR()
+		var t1 TestStruct
+		err := t1.UnmarshalXDR(bs)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		// Not comparing with DeepEqual since we'll unmarshal nil slices as empty
+		if t0.I != t1.I ||
+			t0.I16 != t1.I16 || t0.UI16 != t1.UI16 ||
+			t0.I32 != t1.I32 || t0.UI32 != t1.UI32 ||
+			t0.I64 != t1.I64 || t0.UI64 != t1.UI64 ||
+			bytes.Compare(t0.BS, t1.BS) != 0 ||
+			t0.S != t1.S {
+			t.Logf("%#v", t0)
+			t.Logf("%#v", t1)
+			return false
+		}
+		return true
+	}
+	if err := quick.Check(fn, nil); err != nil {
+		t.Error(err)
+	}
+}

+ 57 - 0
xdr/encdec_xdr_test.go

@@ -0,0 +1,57 @@
+package xdr_test
+
+import (
+	"bytes"
+	"io"
+
+	"github.com/calmh/syncthing/xdr"
+)
+
+func (o TestStruct) EncodeXDR(w io.Writer) (int, error) {
+	var xw = xdr.NewWriter(w)
+	return o.encodeXDR(xw)
+}
+
+func (o TestStruct) MarshalXDR() []byte {
+	var buf bytes.Buffer
+	var xw = xdr.NewWriter(&buf)
+	o.encodeXDR(xw)
+	return buf.Bytes()
+}
+
+func (o TestStruct) encodeXDR(xw *xdr.Writer) (int, error) {
+	xw.WriteUint64(uint64(o.I))
+	xw.WriteUint16(uint16(o.I16))
+	xw.WriteUint16(o.UI16)
+	xw.WriteUint32(uint32(o.I32))
+	xw.WriteUint32(o.UI32)
+	xw.WriteUint64(uint64(o.I64))
+	xw.WriteUint64(o.UI64)
+	xw.WriteBytes(o.BS)
+	xw.WriteString(o.S)
+	return xw.Tot(), xw.Error()
+}
+
+func (o *TestStruct) DecodeXDR(r io.Reader) error {
+	xr := xdr.NewReader(r)
+	return o.decodeXDR(xr)
+}
+
+func (o *TestStruct) UnmarshalXDR(bs []byte) error {
+	var buf = bytes.NewBuffer(bs)
+	var xr = xdr.NewReader(buf)
+	return o.decodeXDR(xr)
+}
+
+func (o *TestStruct) decodeXDR(xr *xdr.Reader) error {
+	o.I = int(xr.ReadUint64())
+	o.I16 = int16(xr.ReadUint16())
+	o.UI16 = xr.ReadUint16()
+	o.I32 = int32(xr.ReadUint32())
+	o.UI32 = xr.ReadUint32()
+	o.I64 = int64(xr.ReadUint64())
+	o.UI64 = xr.ReadUint64()
+	o.BS = xr.ReadBytes()
+	o.S = xr.ReadString()
+	return xr.Error()
+}

+ 1 - 1
xdr/reader.go

@@ -105,7 +105,7 @@ func (r *Reader) ReadUint16() uint16 {
 		return 0
 	}
 
-	v := uint16(r.b[1]) | uint16(r.b[0])<<8
+	v := uint16(r.b[3]) | uint16(r.b[2])<<8
 
 	if debug {
 		dl.Debugf("@0x%x: rd uint16=%d (0x%04x)", s, v, v)

+ 45 - 0
xdr/refl_test.go

@@ -0,0 +1,45 @@
+// Copyright (C) 2014 Jakob Borg and other contributors. All rights reserved.
+// Use of this source code is governed by an MIT-style license that can be
+// found in the LICENSE file.
+
+// +build refl
+
+package xdr_test
+
+import (
+	"bytes"
+	"testing"
+
+	refl "github.com/davecgh/go-xdr/xdr"
+)
+
+func TestCompareMarshals(t *testing.T) {
+	e0 := s.MarshalXDR()
+	e1, err := refl.Marshal(s)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if bytes.Compare(e0, e1) != 0 {
+		t.Fatalf("Encoding mismatch;\n\t%x (this)\n\t%x (refl)", e0, e1)
+	}
+}
+
+func BenchmarkReflMarshal(b *testing.B) {
+	var err error
+	for i := 0; i < b.N; i++ {
+		res, err = refl.Marshal(s)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func BenchmarkReflUnmarshal(b *testing.B) {
+	var t XDRBenchStruct
+	for i := 0; i < b.N; i++ {
+		_, err := refl.Unmarshal(e, &t)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}

+ 4 - 4
xdr/writer.go

@@ -79,10 +79,10 @@ func (w *Writer) WriteUint16(v uint16) (int, error) {
 		dl.Debugf("wr uint16=%d", v)
 	}
 
-	w.b[0] = byte(v >> 8)
-	w.b[1] = byte(v)
-	w.b[2] = 0
-	w.b[3] = 0
+	w.b[0] = 0
+	w.b[1] = 0
+	w.b[2] = byte(v >> 8)
+	w.b[3] = byte(v)
 
 	var l int
 	l, w.err = w.w.Write(w.b[:4])