merkledag_test.go 5.69 KB
Newer Older
1
package merkledag_test
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
2 3

import (
4
	"bytes"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
5
	"fmt"
6 7
	"io"
	"io/ioutil"
8
	"strings"
9
	"sync"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
10
	"testing"
11

12 13 14 15
	ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
	dssync "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
	"github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
	bstore "github.com/ipfs/go-ipfs/blocks/blockstore"
16
	key "github.com/ipfs/go-ipfs/blocks/key"
17
	bserv "github.com/ipfs/go-ipfs/blockservice"
18
	bstest "github.com/ipfs/go-ipfs/blockservice/test"
19 20 21 22 23 24 25
	offline "github.com/ipfs/go-ipfs/exchange/offline"
	imp "github.com/ipfs/go-ipfs/importer"
	chunk "github.com/ipfs/go-ipfs/importer/chunk"
	. "github.com/ipfs/go-ipfs/merkledag"
	"github.com/ipfs/go-ipfs/pin"
	uio "github.com/ipfs/go-ipfs/unixfs/io"
	u "github.com/ipfs/go-ipfs/util"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
26 27
)

Jeromy's avatar
Jeromy committed
28 29 30 31 32 33
type dagservAndPinner struct {
	ds DAGService
	mp pin.ManualPinner
}

func getDagservAndPinner(t *testing.T) dagservAndPinner {
34 35
	db := dssync.MutexWrap(ds.NewMapDatastore())
	bs := bstore.NewBlockstore(db)
Jeromy's avatar
Jeromy committed
36 37 38 39 40 41 42 43 44 45 46 47
	blockserv, err := bserv.New(bs, offline.Exchange(bs))
	if err != nil {
		t.Fatal(err)
	}
	dserv := NewDAGService(blockserv)
	mpin := pin.NewPinner(db, dserv).GetManual()
	return dagservAndPinner{
		ds: dserv,
		mp: mpin,
	}
}

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
func TestNode(t *testing.T) {

	n1 := &Node{Data: []byte("beep")}
	n2 := &Node{Data: []byte("boop")}
	n3 := &Node{Data: []byte("beep boop")}
	if err := n3.AddNodeLink("beep-link", n1); err != nil {
		t.Error(err)
	}
	if err := n3.AddNodeLink("boop-link", n2); err != nil {
		t.Error(err)
	}

	printn := func(name string, n *Node) {
		fmt.Println(">", name)
		fmt.Println("data:", string(n.Data))

		fmt.Println("links:")
		for _, l := range n.Links {
			fmt.Println("-", l.Name, l.Size, l.Hash)
		}

		e, err := n.Encoded(false)
		if err != nil {
			t.Error(err)
		} else {
			fmt.Println("encoded:", e)
		}

		h, err := n.Multihash()
		if err != nil {
			t.Error(err)
		} else {
			fmt.Println("hash:", h)
		}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
82 83 84 85

		k, err := n.Key()
		if err != nil {
			t.Error(err)
86
		} else if k != key.Key(h) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
87 88 89 90
			t.Error("Key is not equivalent to multihash")
		} else {
			fmt.Println("key: ", k)
		}
91 92

		SubtestNodeStat(t, n)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
93 94 95 96 97 98
	}

	printn("beep", n1)
	printn("boop", n2)
	printn("beep boop", n3)
}
99

100 101 102 103 104 105 106 107 108 109 110 111 112
func SubtestNodeStat(t *testing.T, n *Node) {
	enc, err := n.Encoded(true)
	if err != nil {
		t.Error("n.Encoded(true) failed")
		return
	}

	cumSize, err := n.Size()
	if err != nil {
		t.Error("n.Size() failed")
		return
	}

113 114 115 116 117 118
	k, err := n.Key()
	if err != nil {
		t.Error("n.Key() failed")
		return
	}

119 120 121 122 123 124
	expected := NodeStat{
		NumLinks:       len(n.Links),
		BlockSize:      len(enc),
		LinksSize:      len(enc) - len(n.Data), // includes framing.
		DataSize:       len(n.Data),
		CumulativeSize: int(cumSize),
125
		Hash:           k.B58String(),
126 127 128 129 130 131 132 133
	}

	actual, err := n.Stat()
	if err != nil {
		t.Error("n.Stat() failed")
		return
	}

134
	if expected != *actual {
135
		t.Errorf("n.Stat incorrect.\nexpect: %s\nactual: %s", expected, actual)
136 137 138 139 140
	} else {
		fmt.Printf("n.Stat correct: %s\n", actual)
	}
}

141 142 143
type devZero struct{}

func (_ devZero) Read(b []byte) (int, error) {
rht's avatar
rht committed
144
	for i := range b {
145 146 147 148 149
		b[i] = 0
	}
	return len(b), nil
}

150
func TestBatchFetch(t *testing.T) {
Jeromy's avatar
Jeromy committed
151 152
	read := io.LimitReader(u.NewTimeSeededRand(), 1024*32)
	runBatchFetchTest(t, read)
153
}
154 155

func TestBatchFetchDupBlock(t *testing.T) {
Jeromy's avatar
Jeromy committed
156 157
	read := io.LimitReader(devZero{}, 1024*32)
	runBatchFetchTest(t, read)
158 159
}

Jeromy's avatar
Jeromy committed
160
func runBatchFetchTest(t *testing.T, read io.Reader) {
161
	var dagservs []DAGService
162
	for _, bsi := range bstest.Mocks(t, 5) {
163 164
		dagservs = append(dagservs, NewDAGService(bsi))
	}
Jeromy's avatar
Jeromy committed
165 166 167

	spl := &chunk.SizeSplitter{512}

168
	root, err := imp.BuildDagFromReader(read, dagservs[0], spl, nil)
Jeromy's avatar
Jeromy committed
169 170 171 172
	if err != nil {
		t.Fatal(err)
	}

173 174
	t.Log("finished setup.")

Jeromy's avatar
Jeromy committed
175
	dagr, err := uio.NewDagReader(context.TODO(), root, dagservs[0])
176 177 178
	if err != nil {
		t.Fatal(err)
	}
Jeromy's avatar
Jeromy committed
179 180

	expected, err := ioutil.ReadAll(dagr)
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
	if err != nil {
		t.Fatal(err)
	}

	err = dagservs[0].AddRecursive(root)
	if err != nil {
		t.Fatal(err)
	}

	t.Log("Added file to first node.")

	k, err := root.Key()
	if err != nil {
		t.Fatal(err)
	}

197
	wg := sync.WaitGroup{}
198
	for i := 1; i < len(dagservs); i++ {
199
		wg.Add(1)
200
		go func(i int) {
201
			defer wg.Done()
Jeromy's avatar
Jeromy committed
202
			first, err := dagservs[i].Get(context.Background(), k)
203 204 205 206 207
			if err != nil {
				t.Fatal(err)
			}
			fmt.Println("Got first node back.")

Jeromy's avatar
Jeromy committed
208
			read, err := uio.NewDagReader(context.TODO(), first, dagservs[i])
209 210 211 212 213 214 215 216 217 218 219 220 221 222
			if err != nil {
				t.Fatal(err)
			}
			datagot, err := ioutil.ReadAll(read)
			if err != nil {
				t.Fatal(err)
			}

			if !bytes.Equal(datagot, expected) {
				t.Fatal("Got bad data back!")
			}
		}(i)
	}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
223
	wg.Wait()
224
}
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291

func TestRecursiveAdd(t *testing.T) {
	a := &Node{Data: []byte("A")}
	b := &Node{Data: []byte("B")}
	c := &Node{Data: []byte("C")}
	d := &Node{Data: []byte("D")}
	e := &Node{Data: []byte("E")}

	err := a.AddNodeLink("blah", b)
	if err != nil {
		t.Fatal(err)
	}

	err = b.AddNodeLink("foo", c)
	if err != nil {
		t.Fatal(err)
	}

	err = b.AddNodeLink("bar", d)
	if err != nil {
		t.Fatal(err)
	}

	err = d.AddNodeLink("baz", e)
	if err != nil {
		t.Fatal(err)
	}

	dsp := getDagservAndPinner(t)
	err = dsp.ds.AddRecursive(a)
	if err != nil {
		t.Fatal(err)
	}

	assertCanGet(t, dsp.ds, a)
	assertCanGet(t, dsp.ds, b)
	assertCanGet(t, dsp.ds, c)
	assertCanGet(t, dsp.ds, d)
	assertCanGet(t, dsp.ds, e)
}

func assertCanGet(t *testing.T, ds DAGService, n *Node) {
	k, err := n.Key()
	if err != nil {
		t.Fatal(err)
	}

	_, err = ds.Get(context.TODO(), k)
	if err != nil {
		t.Fatal(err)
	}
}

func TestCantGet(t *testing.T) {
	dsp := getDagservAndPinner(t)
	a := &Node{Data: []byte("A")}

	k, err := a.Key()
	if err != nil {
		t.Fatal(err)
	}

	_, err = dsp.ds.Get(context.TODO(), k)
	if !strings.Contains(err.Error(), "not found") {
		t.Fatal("expected err not found, got: ", err)
	}
}