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

chore: add tests to verify allowable data layouts #58

Merged
merged 1 commit into from
Oct 12, 2020
Merged
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
299 changes: 299 additions & 0 deletions pb/compat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
package merkledag_pb

// mirrored in JavaScript @ https://github.com/ipld/js-dag-pb/blob/master/test/test-compat.js

import (
"encoding/hex"
"encoding/json"
"testing"
)

var dataZero []byte = make([]byte, 0)
var dataSome []byte = []byte{0, 1, 2, 3, 4}
var cidBytes []byte = []byte{1, 85, 0, 5, 0, 1, 2, 3, 4}
var zeroName string = ""
var someName string = "some name"
var zeroTsize uint64 = 0
var someTsize uint64 = 1010
var largeTsize uint64 = 9007199254740991 // JavaScript Number.MAX_SAFE_INTEGER

type testCase struct {
name string
node *PBNode
expectedBytes string
expectedForm string
}

var testCases = []testCase{
{
name: "empty",
node: &PBNode{},
expectedBytes: "",
expectedForm: "{}",
},
{
name: "Data zero",
node: &PBNode{Data: dataZero},
expectedBytes: "0a00",
expectedForm: `{
"Data": ""
}`,
},
{
name: "Data some",
node: &PBNode{Data: dataSome},
expectedBytes: "0a050001020304",
expectedForm: `{
"Data": "0001020304"
}`,
},
{
name: "Links zero",
node: &PBNode{Links: make([]*PBLink, 0)},
expectedBytes: "",
expectedForm: "{}",
},
{
name: "Data some Links zero",
node: &PBNode{Data: dataSome, Links: make([]*PBLink, 0)},
expectedBytes: "0a050001020304",
expectedForm: `{
"Data": "0001020304"
}`,
},
{
name: "Links empty",
node: &PBNode{Links: []*PBLink{{}}},
expectedBytes: "1200",
expectedForm: `{
"Links": [
{}
]
}`,
},
{
name: "Data some Links empty",
node: &PBNode{Data: dataSome, Links: []*PBLink{{}}},
expectedBytes: "12000a050001020304",
expectedForm: `{
"Data": "0001020304",
"Links": [
{}
]
}`,
},
{
name: "Links Hash zero",
node: &PBNode{Links: []*PBLink{{Hash: dataZero}}},
expectedBytes: "12020a00",
expectedForm: `{
"Links": [
{
"Hash": ""
}
]
}`,
},
{
name: "Links Hash some",
node: &PBNode{Links: []*PBLink{{Hash: cidBytes}}},
expectedBytes: "120b0a09015500050001020304",
expectedForm: `{
"Links": [
{
"Hash": "015500050001020304"
}
]
}`,
},
{
name: "Links Name zero",
node: &PBNode{Links: []*PBLink{{Name: &zeroName}}},
expectedBytes: "12021200",
expectedForm: `{
"Links": [
{
"Name": ""
}
]
}`,
},
{
name: "Links Hash some Name zero",
node: &PBNode{Links: []*PBLink{{Hash: cidBytes, Name: &zeroName}}},
expectedBytes: "120d0a090155000500010203041200",
expectedForm: `{
"Links": [
{
"Hash": "015500050001020304",
"Name": ""
}
]
}`,
},
{
name: "Links Name some",
node: &PBNode{Links: []*PBLink{{Name: &someName}}},
expectedBytes: "120b1209736f6d65206e616d65",
expectedForm: `{
"Links": [
{
"Name": "some name"
}
]
}`,
},
{
name: "Links Hash some Name some",
node: &PBNode{Links: []*PBLink{{Hash: cidBytes, Name: &someName}}},
expectedBytes: "12160a090155000500010203041209736f6d65206e616d65",
expectedForm: `{
"Links": [
{
"Hash": "015500050001020304",
"Name": "some name"
}
]
}`,
},
{
name: "Links Tsize zero",
node: &PBNode{Links: []*PBLink{{Tsize: &zeroTsize}}},
expectedBytes: "12021800",
expectedForm: `{
"Links": [
{
"Tsize": 0
}
]
}`,
},
{
name: "Links Hash some Tsize zero",
node: &PBNode{Links: []*PBLink{{Hash: cidBytes, Tsize: &zeroTsize}}},
expectedBytes: "120d0a090155000500010203041800",
expectedForm: `{
"Links": [
{
"Hash": "015500050001020304",
"Tsize": 0
}
]
}`,
},
{
name: "Links Tsize some",
node: &PBNode{Links: []*PBLink{{Tsize: &someTsize}}},
expectedBytes: "120318f207",
expectedForm: `{
"Links": [
{
"Tsize": 1010
}
]
}`,
},
{
name: "Links Hash some Tsize some",
node: &PBNode{Links: []*PBLink{{Hash: cidBytes, Tsize: &largeTsize}}},
expectedBytes: "12140a0901550005000102030418ffffffffffffff0f",
expectedForm: `{
"Links": [
{
"Hash": "015500050001020304",
"Tsize": 9007199254740991
}
]
}`,
},
}

func TestCompat(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
verifyRoundTrip(t, tc)
})
}
}

func verifyRoundTrip(t *testing.T, tc testCase) {
actualBytes, actualForm, err := nodeRoundTripToString(t, tc.node)
if err != nil {
t.Fatal(err)
}

if actualBytes != tc.expectedBytes {
t.Logf(
"Expected bytes: [%v]\nGot: [%v]\n",
tc.expectedBytes,
actualBytes)
t.Error("Did not match")
}

if actualForm != tc.expectedForm {
t.Logf(
"Expected form: [%v]\nGot: [%v]\n",
tc.expectedForm,
actualForm)
t.Error("Did not match")
}
}

func nodeRoundTripToString(t *testing.T, n *PBNode) (string, string, error) {
bytes, err := n.Marshal()
if err != nil {
return "", "", err
}
t.Logf("[%v]\n", hex.EncodeToString(bytes))
rt := new(PBNode)
if err := rt.Unmarshal(bytes); err != nil {
return "", "", err
}
str, err := json.MarshalIndent(cleanPBNode(t, rt), "", "\t")
if err != nil {
return "", "", err
}
return hex.EncodeToString(bytes), string(str), nil
}

// convert a PBLink into a map for clean JSON marshalling
func cleanPBLink(t *testing.T, link *PBLink) map[string]interface{} {
if link == nil {
return nil
}
// this would be a bad pb decode
if link.XXX_unrecognized != nil {
t.Fatal("Got unexpected XXX_unrecognized")
}
nl := make(map[string]interface{})
if link.Hash != nil {
nl["Hash"] = hex.EncodeToString(link.Hash)
}
if link.Name != nil {
nl["Name"] = link.Name
}
if link.Tsize != nil {
nl["Tsize"] = link.Tsize
}
return nl
}

// convert a PBNode into a map for clean JSON marshalling
func cleanPBNode(t *testing.T, node *PBNode) map[string]interface{} {
// this would be a bad pb decode
if node.XXX_unrecognized != nil {
t.Fatal("Got unexpected XXX_unrecognized")
}
nn := make(map[string]interface{})
if node.Data != nil {
nn["Data"] = hex.EncodeToString(node.Data)
}
if node.Links != nil {
links := make([]map[string]interface{}, len(node.Links))
for i, l := range node.Links {
links[i] = cleanPBLink(t, l)
}
nn["Links"] = links
}
return nn
}