Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add raft tests; backwards compatible time.Time #13

Merged
merged 3 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions codec/internal/testdata/raft.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package testdata

import "time"

// copy of all the raft data types

type ProtocolVersion int
type LogType uint8
type SnapshotVersion int
type ServerID string
type ServerAddress string
type ServerSuffrage int
type Log struct {
Index uint64
Term uint64
Type LogType
Data []byte
Extensions []byte
AppendedAt time.Time
}
type RPCHeader struct {
ProtocolVersion ProtocolVersion
ID []byte
Addr []byte
}
type AppendEntriesRequest struct {
RPCHeader
Term uint64
Leader []byte
PrevLogEntry uint64
PrevLogTerm uint64
Entries []*Log
LeaderCommitIndex uint64
}
type AppendEntriesResponse struct {
RPCHeader
Term uint64
LastLog uint64
Success bool
NoRetryBackoff bool
}
type InstallSnapshotRequest struct {
RPCHeader
SnapshotVersion SnapshotVersion
Term uint64
Leader []byte
LastLogIndex uint64
LastLogTerm uint64
Peers []byte
Configuration []byte
ConfigurationIndex uint64
Size int64
}
type InstallSnapshotResponse struct {
RPCHeader
Term uint64
Success bool
}
type RequestVoteRequest struct {
RPCHeader
Term uint64
Candidate []byte
LastLogIndex uint64
LastLogTerm uint64
LeadershipTransfer bool
}
type RequestVoteResponse struct {
RPCHeader
Term uint64
Peers []byte
Granted bool
}
type Server struct {
Suffrage ServerSuffrage
ID ServerID
Address ServerAddress
}
type Configuration struct {
Servers []Server
}

type SerializeTest struct {
Name string
EncodedBytesHex string
ExpectedData interface{}
}
116 changes: 116 additions & 0 deletions codec/internal/testdata/raft_v055.go

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions codec/internal/testdata/raft_v115.go

Large diffs are not rendered by default.

116 changes: 116 additions & 0 deletions codec/internal/testdata/raft_v116.go

Large diffs are not rendered by default.

27 changes: 19 additions & 8 deletions codec/msgpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,21 +891,32 @@ func (d *msgpackDecDriver) DecodeTime() (t time.Time) {
}

func (d *msgpackDecDriver) decodeTime(clen int) (t time.Time) {
// bs = d.r.readx(clen)
bs := d.r.readx(uint(clen))

// Decode as a binary marshalled string for compatibility with other versions of go-msgpack.
// time.Time should always be encoded as 16 bytes or fewer in the binary marshalling format,
// so will always fit within the 32 byte max for fixed strings
if d.bd >= mpFixStrMin && d.bd <= mpFixStrMax {
err := t.UnmarshalBinary(bs)
if err == nil {
return
}
// fallthrough on failure
}

d.bdRead = false
switch clen {
case 4:
t = time.Unix(int64(bigen.Uint32(d.r.readx(4))), 0).UTC()
t = time.Unix(int64(bigen.Uint32(bs)), 0).UTC()
case 8:
tv := bigen.Uint64(d.r.readx(8))
tv := bigen.Uint64(bs)
t = time.Unix(int64(tv&0x00000003ffffffff), int64(tv>>34)).UTC()
case 12:
nsec := bigen.Uint32(d.r.readx(4))
sec := bigen.Uint64(d.r.readx(8))
nsec := bigen.Uint32(bs[:4])
sec := bigen.Uint64(bs[4:])
t = time.Unix(int64(sec), int64(nsec)).UTC()
default:
d.d.errorf("invalid length of bytes for decoding time - expecting 4 or 8 or 12, got %d", clen)
return
d.d.errorf("invalid bytes for decoding time - expecting string or 4, 8, or 12 bytes, got %d", clen)
}
return
}
Expand Down Expand Up @@ -956,7 +967,7 @@ func (d *msgpackDecDriver) decodeExtV(verifyTag bool, tag byte) (xtag byte, xbs

//--------------------------------------------------

//MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format.
// MsgpackHandle is a Handle for the Msgpack Schema-Free Encoding Format.
type MsgpackHandle struct {
BasicHandle

Expand Down
107 changes: 107 additions & 0 deletions codec/raft_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package codec

import (
"bytes"
"encoding/hex"
"reflect"
"testing"
"time"

"github.com/hashicorp/go-msgpack/v2/codec/internal/testdata"
)

// Tests that msgpack correctly deserializes all legacy hashicorp/raft entries, byte-for-byte.
// These were generated by running all the Raft tests and capturing all msgpack encodings.

func decodeMsgPack(buf []byte, out interface{}) error {
r := bytes.NewBuffer(buf)
hd := MsgpackHandle{}
dec := NewDecoder(r, &hd)
return dec.Decode(out)
}

func serializeTests(t *testing.T, tests []testdata.SerializeTest) {
t.Helper()
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
expected, err := hex.DecodeString(test.EncodedBytesHex)
if err != nil {
t.Fatal(err)
}
typ := reflect.TypeOf(test.ExpectedData)
x := reflect.New(typ).Elem().Interface()

err = decodeMsgPack(expected, &x)
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(x, test.ExpectedData) {
// to help figure out what is different since the Logs are pointers
if aer, ok := x.(testdata.AppendEntriesRequest); ok {
for _, log := range aer.Entries {
if log != nil {
t.Errorf("log %##v", *log)
}
}
}
t.Errorf("expected %#v but got %#v", test.ExpectedData, x)
}
})
}

}

func TestRaftBytes_v116(t *testing.T) {
serializeTests(t, testdata.RaftV116)
}

func TestRaftBytes_v115(t *testing.T) {
serializeTests(t, testdata.RaftV115)
}

func TestRaftBytes_v055(t *testing.T) {
serializeTests(t, testdata.RaftV055)
}

func TestTimeBytes(t *testing.T) {
testCases := []struct {
name string
data string
expected string
}{
{
"v1.1.6 non-UTC with nanos",
"af010000000eda5a48a43b9ac9ff01a4",
"2022-07-08T22:47:48.999999999+07:00",
},
{
"v1.1.6",
"af010000000eda5aab140e044990ffff",
"2022-07-08T22:47:48.235162Z",
},
{
"v1.1.5",
"a83811264062c8b414",
"2022-07-08T22:47:48.235162Z",
},
}

for _, test := range testCases {
var got time.Time
data, err := hex.DecodeString(test.data)
if err != nil {
t.Fatal(err)
}
err = decodeMsgPack(data, &got)
if err != nil {
t.Fatal(err)
}
expected, err := time.Parse(time.RFC3339Nano, test.expected)
if err != nil {
t.Fatal(err)
}
if !got.Equal(expected) {
t.Errorf("%s: Got %s expected %s", test.name, got.Format(time.RFC3339Nano), expected.Format(time.RFC3339Nano))
}
}
}
20 changes: 19 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,22 @@ module github.com/hashicorp/go-msgpack/v2

go 1.13

require golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b
require (
bitbucket.org/bodhisnarkva/cbor v0.0.0-20170201010848-113f42203c94
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Sereal/Sereal v0.0.0-20221130110801-16a4f76670cd
github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/json-iterator/go v1.1.12
github.com/mailru/easyjson v0.7.7
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7
github.com/tinylib/msgp v1.1.6
github.com/ugorji/go/codec v1.2.7
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
gopkg.in/vmihailenco/msgpack.v2 v2.9.2
gopkg.in/yaml.v2 v2.4.0 // indirect
)
86 changes: 86 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
bitbucket.org/bodhisnarkva/cbor v0.0.0-20170201010848-113f42203c94 h1:mIPAugcfnbnaazg3ttUVbHbJaY+e3aUf4Wr7lONml5I=
bitbucket.org/bodhisnarkva/cbor v0.0.0-20170201010848-113f42203c94/go.mod h1:pl6BcNYTFXkbj1OCW5EIJkgrzmmEFwU6oaelsR/9pMQ=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Sereal/Sereal v0.0.0-20221130110801-16a4f76670cd h1:rP6LH3aVJTIxgTA3q79sSfnt8DvOlt17IRAklRBN+xo=
github.com/Sereal/Sereal v0.0.0-20221130110801-16a4f76670cd/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892 h1:qg9VbHo1TlL0KDM0vYvBG9EY0X0Yku5WYIPoFWt8f6o=
github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892/go.mod h1:CTDl0pzVzE5DEzZhPfvhY/9sPFMQIxaJ9VAMs9AagrE=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 h1:xoIK0ctDddBMnc74udxJYBqlo9Ylnsp1waqjLsnef20=
github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9 h1:sEvmEcJVKBNUvgCUClbUQeHOAa9U0I2Ce1BooMvVCY4=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/vmihailenco/msgpack.v2 v2.9.2 h1:gjPqo9orRVlSAH/065qw3MsFCDpH7fa1KpiizXyllY4=
gopkg.in/vmihailenco/msgpack.v2 v2.9.2/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=