Skip to content
This repository has been archived by the owner on Aug 9, 2018. It is now read-only.

Commit

Permalink
Test JSON decoding and fix implentation
Browse files Browse the repository at this point in the history
Add a test that decodes a JSON object, and detect links in it. Then encode
it again and it must match the original file. The test failed (because the
link was a map[string]interface{} instead of a Node). The fix post-process
the result of the JSON decoder to convert map[string]interface{} to Node.
  • Loading branch information
mildred committed Oct 29, 2015
1 parent e711171 commit d68f39d
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 4 deletions.
10 changes: 10 additions & 0 deletions coding/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

pb/bin/multicodec:
$(MAKE) -C pb bin/multicodec

json.testfile: pb/bin/multicodec Makefile
: >$@
pb/bin/multicodec header /multicodec >>$@
pb/bin/multicodec header /json >>$@
echo '{"@codec":"/json","abc":{"mlink":"QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V"}}' >>$@

5 changes: 1 addition & 4 deletions coding/coding.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package ipfsld
import (
mc "github.com/jbenet/go-multicodec"
mccbor "github.com/jbenet/go-multicodec/cbor"
mcjson "github.com/jbenet/go-multicodec/json"
mcmux "github.com/jbenet/go-multicodec/mux"

ipld "github.com/ipfs/go-ipld"
Expand All @@ -24,7 +23,7 @@ func init() {
defaultCodec = string(mc.HeaderPath(mccbor.Header))
muxCodec = mcmux.MuxMulticodec([]mc.Multicodec{
mccbor.Multicodec(),
mcjson.Multicodec(false),
jsonMulticodec(),
pb.Multicodec(),
}, selectCodec)
}
Expand Down Expand Up @@ -61,8 +60,6 @@ func codecKey(n ipld.Node) (string, error) {
if !ok {
// if no codec is defined, use our default codec
chdr = defaultCodec

// except, if it looks like an old, style protobuf object
if pb.IsOldProtobufNode(n) {
chdr = string(pb.Header)
}
Expand Down
54 changes: 54 additions & 0 deletions coding/coding_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package ipfsld

import (
"io/ioutil"
"testing"
"reflect"
"bytes"

ipld "github.com/ipfs/go-ipld"

mc "github.com/jbenet/go-multicodec"
mctest "github.com/jbenet/go-multicodec/test"
)

var json_testfile []byte

func init() {
var err error
json_testfile, err = ioutil.ReadFile("json.testfile")
if err != nil {
panic("could not read json.testfile. please run: make json.testfile")
}
}

type TC struct {
cbor []byte
src ipld.Node
Expand Down Expand Up @@ -86,3 +100,43 @@ func TestRoundtripBasicMC(t *testing.T) {
mctest.RoundTripTest(t, codec, &(tca.src), &tcb)
}
}

// Test decoding and encoding a json file
func TestJsonDecodeEncode(t *testing.T) {
var n ipld.Node
codec := Multicodec()

if err := mc.Unmarshal(codec, json_testfile, &n); err != nil {
t.Log(json_testfile)
t.Error(err)
return
}

linksExpected := map[string]ipld.Link{
"abc": ipld.Link {
"mlink": "QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V",
},
}
linksActual := ipld.Links(n)
if !reflect.DeepEqual(linksExpected, linksActual) {
t.Log(linksExpected)
t.Log(linksActual)
t.Logf("node: %#v\n", n)
t.Fatalf("Links are not expected")
}

encoded, err := mc.Marshal(codec, &n)
if err != nil {
t.Error(err)
return
}

if !bytes.Equal(json_testfile, encoded) {
t.Error("marshalled values not equal")
t.Log(string(json_testfile))
t.Log(string(encoded))
t.Log(json_testfile)
t.Log(encoded)
}
}

71 changes: 71 additions & 0 deletions coding/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package ipfsld

import (
"io"

mc "github.com/jbenet/go-multicodec"
mcjson "github.com/jbenet/go-multicodec/json"
ipld "github.com/ipfs/go-ipld"
)

type codec struct {
mc.Multicodec
}

type decoder struct {
mc.Decoder
}

func jsonMulticodec() mc.Multicodec {
return &codec{mcjson.Multicodec(false)}
}

func (c *codec) Decoder(r io.Reader) mc.Decoder {
return &decoder{ c.Multicodec.Decoder(r) }
}

func (c *decoder) Decode(v interface{}) error {
err := c.Decoder.Decode(v)
if err == nil {
convert(v)
}
return err
}

func convert(val interface{}) interface{} {
switch val.(type) {
case *map[string]interface{}:
vmi := val.(*map[string]interface{})
n := ipld.Node{}
for k, v := range *vmi {
n[k] = convert(v)
(*vmi)[k] = convert(v)
}
return &n
case map[string]interface{}:
vmi := val.(map[string]interface{})
n := ipld.Node{}
for k, v := range vmi {
n[k] = convert(v)
vmi[k] = convert(v)
}
return n
case *[]interface{}:
convert(*val.(*[]interface{}))
case []interface{}:
slice := val.([]interface{})
for k, v := range slice {
slice[k] = convert(v)
}
case *ipld.Node:
convert(*val.(*ipld.Node))
case ipld.Node:
n := val.(ipld.Node)
for k, v := range n {
n[k] = convert(v)
}
default:
}
return val
}

3 changes: 3 additions & 0 deletions coding/json.testfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/multicodec
/json
{"@codec":"/json","abc":{"mlink":"QmXg9Pp2ytZ14xgmQjYEiHjVjMFXzCVVEcRTWJBmLgR39V"}}

0 comments on commit d68f39d

Please sign in to comment.