Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b2695b0

Browse files
committedOct 4, 2015
Merge pull request #1769 from ipfs/mfs-api-redux
implement ipfs files command
2 parents 2a2b237 + d69891f commit b2695b0

File tree

8 files changed

+1315
-11
lines changed

8 files changed

+1315
-11
lines changed
 

‎core/builder.go

+5
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,10 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
159159
}
160160
n.Resolver = &path.Resolver{DAG: n.DAG}
161161

162+
err = n.loadFilesRoot()
163+
if err != nil {
164+
return err
165+
}
166+
162167
return nil
163168
}

‎core/commands/files/files.go

+707
Large diffs are not rendered by default.

‎core/commands/root.go

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"strings"
66

77
cmds "github.com/ipfs/go-ipfs/commands"
8+
files "github.com/ipfs/go-ipfs/core/commands/files"
89
unixfs "github.com/ipfs/go-ipfs/core/commands/unixfs"
910
evlog "github.com/ipfs/go-ipfs/thirdparty/eventlog"
1011
)
@@ -94,6 +95,7 @@ var rootSubcommands = map[string]*cmds.Command{
9495
"dht": DhtCmd,
9596
"diag": DiagCmd,
9697
"dns": DNSCmd,
98+
"files": files.FilesCmd,
9799
"get": GetCmd,
98100
"id": IDCmd,
99101
"log": LogCmd,

‎core/core.go

+55-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"time"
1818

1919
b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58"
20+
ds "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
2021
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
2122
goprocess "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
2223
mamask "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/whyrusleeping/multiaddr-filter"
@@ -40,11 +41,13 @@ import (
4041
offroute "github.com/ipfs/go-ipfs/routing/offline"
4142

4243
bstore "github.com/ipfs/go-ipfs/blocks/blockstore"
44+
key "github.com/ipfs/go-ipfs/blocks/key"
4345
bserv "github.com/ipfs/go-ipfs/blockservice"
4446
exchange "github.com/ipfs/go-ipfs/exchange"
4547
bitswap "github.com/ipfs/go-ipfs/exchange/bitswap"
4648
bsnet "github.com/ipfs/go-ipfs/exchange/bitswap/network"
4749
rp "github.com/ipfs/go-ipfs/exchange/reprovide"
50+
mfs "github.com/ipfs/go-ipfs/mfs"
4851

4952
mount "github.com/ipfs/go-ipfs/fuse/mount"
5053
merkledag "github.com/ipfs/go-ipfs/merkledag"
@@ -53,6 +56,7 @@ import (
5356
pin "github.com/ipfs/go-ipfs/pin"
5457
repo "github.com/ipfs/go-ipfs/repo"
5558
config "github.com/ipfs/go-ipfs/repo/config"
59+
uio "github.com/ipfs/go-ipfs/unixfs/io"
5660
)
5761

5862
const IpnsValidatorTag = "ipns"
@@ -92,6 +96,7 @@ type IpfsNode struct {
9296
Resolver *path.Resolver // the path resolution system
9397
Reporter metrics.Reporter
9498
Discovery discovery.Service
99+
FilesRoot *mfs.Root
95100

96101
// Online
97102
PeerHost p2phost.Host // the network host (server+client)
@@ -249,8 +254,14 @@ func (n *IpfsNode) teardown() error {
249254
log.Debug("core is shutting down...")
250255
// owned objects are closed in this teardown to ensure that they're closed
251256
// regardless of which constructor was used to add them to the node.
252-
closers := []io.Closer{
253-
n.Repo,
257+
var closers []io.Closer
258+
259+
// NOTE: the order that objects are added(closed) matters, if an object
260+
// needs to use another during its shutdown/cleanup process, it should be
261+
// closed before that other object
262+
263+
if n.FilesRoot != nil {
264+
closers = append(closers, n.FilesRoot)
254265
}
255266

256267
if n.Exchange != nil {
@@ -264,6 +275,10 @@ func (n *IpfsNode) teardown() error {
264275
closers = append(closers, mount.Closer(n.Mounts.Ipns))
265276
}
266277

278+
if dht, ok := n.Routing.(*dht.IpfsDHT); ok {
279+
closers = append(closers, dht.Process())
280+
}
281+
267282
if n.Blocks != nil {
268283
closers = append(closers, n.Blocks)
269284
}
@@ -272,14 +287,13 @@ func (n *IpfsNode) teardown() error {
272287
closers = append(closers, n.Bootstrapper)
273288
}
274289

275-
if dht, ok := n.Routing.(*dht.IpfsDHT); ok {
276-
closers = append(closers, dht.Process())
277-
}
278-
279290
if n.PeerHost != nil {
280291
closers = append(closers, n.PeerHost)
281292
}
282293

294+
// Repo closed last, most things need to preserve state here
295+
closers = append(closers, n.Repo)
296+
283297
var errs []error
284298
for _, closer := range closers {
285299
if err := closer.Close(); err != nil {
@@ -390,6 +404,41 @@ func (n *IpfsNode) loadBootstrapPeers() ([]peer.PeerInfo, error) {
390404
return toPeerInfos(parsed), nil
391405
}
392406

407+
func (n *IpfsNode) loadFilesRoot() error {
408+
dsk := ds.NewKey("/local/filesroot")
409+
pf := func(ctx context.Context, k key.Key) error {
410+
return n.Repo.Datastore().Put(dsk, []byte(k))
411+
}
412+
413+
var nd *merkledag.Node
414+
val, err := n.Repo.Datastore().Get(dsk)
415+
416+
switch {
417+
case err == ds.ErrNotFound || val == nil:
418+
nd = uio.NewEmptyDirectory()
419+
_, err := n.DAG.Add(nd)
420+
if err != nil {
421+
return fmt.Errorf("failure writing to dagstore: %s", err)
422+
}
423+
case err == nil:
424+
k := key.Key(val.([]byte))
425+
nd, err = n.DAG.Get(n.Context(), k)
426+
if err != nil {
427+
return fmt.Errorf("error loading filesroot from DAG: %s", err)
428+
}
429+
default:
430+
return err
431+
}
432+
433+
mr, err := mfs.NewRoot(n.Context(), n.DAG, nd, pf)
434+
if err != nil {
435+
return err
436+
}
437+
438+
n.FilesRoot = mr
439+
return nil
440+
}
441+
393442
// SetupOfflineRouting loads the local nodes private key and
394443
// uses it to instantiate a routing system in offline mode.
395444
// This is primarily used for offline ipns modifications.

‎mfs/ops.go

+140-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,149 @@ package mfs
33
import (
44
"errors"
55
"fmt"
6+
"os"
7+
gopath "path"
68
"strings"
9+
10+
dag "github.com/ipfs/go-ipfs/merkledag"
711
)
812

9-
func rootLookup(r *Root, path string) (FSNode, error) {
13+
// Mv moves the file or directory at 'src' to 'dst'
14+
func Mv(r *Root, src, dst string) error {
15+
srcDir, srcFname := gopath.Split(src)
16+
17+
var dstDirStr string
18+
var filename string
19+
if dst[len(dst)-1] == '/' {
20+
dstDirStr = dst
21+
filename = srcFname
22+
} else {
23+
dstDirStr, filename = gopath.Split(dst)
24+
}
25+
26+
// get parent directories of both src and dest first
27+
dstDir, err := lookupDir(r, dstDirStr)
28+
if err != nil {
29+
return err
30+
}
31+
32+
srcDirObj, err := lookupDir(r, srcDir)
33+
if err != nil {
34+
return err
35+
}
36+
37+
srcObj, err := srcDirObj.Child(srcFname)
38+
if err != nil {
39+
return err
40+
}
41+
42+
nd, err := srcObj.GetNode()
43+
if err != nil {
44+
return err
45+
}
46+
47+
fsn, err := dstDir.Child(filename)
48+
if err == nil {
49+
switch n := fsn.(type) {
50+
case *File:
51+
_ = dstDir.Unlink(filename)
52+
case *Directory:
53+
dstDir = n
54+
default:
55+
return fmt.Errorf("unexpected type at path: %s", dst)
56+
}
57+
} else if err != os.ErrNotExist {
58+
return err
59+
}
60+
61+
err = dstDir.AddChild(filename, nd)
62+
if err != nil {
63+
return err
64+
}
65+
66+
err = srcDirObj.Unlink(srcFname)
67+
if err != nil {
68+
return err
69+
}
70+
71+
return nil
72+
}
73+
74+
func lookupDir(r *Root, path string) (*Directory, error) {
75+
di, err := Lookup(r, path)
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
d, ok := di.(*Directory)
81+
if !ok {
82+
return nil, fmt.Errorf("%s is not a directory", path)
83+
}
84+
85+
return d, nil
86+
}
87+
88+
// PutNode inserts 'nd' at 'path' in the given mfs
89+
func PutNode(r *Root, path string, nd *dag.Node) error {
90+
dirp, filename := gopath.Split(path)
91+
92+
pdir, err := lookupDir(r, dirp)
93+
if err != nil {
94+
return err
95+
}
96+
97+
return pdir.AddChild(filename, nd)
98+
}
99+
100+
// Mkdir creates a directory at 'path' under the directory 'd', creating
101+
// intermediary directories as needed if 'parents' is set to true
102+
func Mkdir(r *Root, path string, parents bool) error {
103+
parts := strings.Split(path, "/")
104+
if parts[0] == "" {
105+
parts = parts[1:]
106+
}
107+
108+
// allow 'mkdir /a/b/c/' to create c
109+
if parts[len(parts)-1] == "" {
110+
parts = parts[:len(parts)-1]
111+
}
112+
113+
if len(parts) == 0 {
114+
// this will only happen on 'mkdir /'
115+
return fmt.Errorf("cannot mkdir '%s'", path)
116+
}
117+
118+
cur := r.GetValue().(*Directory)
119+
for i, d := range parts[:len(parts)-1] {
120+
fsn, err := cur.Child(d)
121+
if err == os.ErrNotExist && parents {
122+
mkd, err := cur.Mkdir(d)
123+
if err != nil {
124+
return err
125+
}
126+
fsn = mkd
127+
} else if err != nil {
128+
return err
129+
}
130+
131+
next, ok := fsn.(*Directory)
132+
if !ok {
133+
return fmt.Errorf("%s was not a directory", strings.Join(parts[:i], "/"))
134+
}
135+
cur = next
136+
}
137+
138+
_, err := cur.Mkdir(parts[len(parts)-1])
139+
if err != nil {
140+
if !parents || err != os.ErrExist {
141+
return err
142+
}
143+
}
144+
145+
return nil
146+
}
147+
148+
func Lookup(r *Root, path string) (FSNode, error) {
10149
dir, ok := r.GetValue().(*Directory)
11150
if !ok {
12151
return nil, errors.New("root was not a directory")

‎test/sharness/t0250-files-api.sh

+343
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
#!/bin/sh
2+
#
3+
# Copyright (c) 2015 Jeromy Johnson
4+
# MIT Licensed; see the LICENSE file in this repository.
5+
#
6+
7+
test_description="test the unix files api"
8+
9+
. lib/test-lib.sh
10+
11+
test_init_ipfs
12+
13+
# setup files for testing
14+
test_expect_success "can create some files for testing" '
15+
FILE1=$(echo foo | ipfs add -q) &&
16+
FILE2=$(echo bar | ipfs add -q) &&
17+
FILE3=$(echo baz | ipfs add -q) &&
18+
mkdir stuff_test &&
19+
echo cats > stuff_test/a &&
20+
echo dogs > stuff_test/b &&
21+
echo giraffes > stuff_test/c &&
22+
DIR1=$(ipfs add -q stuff_test | tail -n1)
23+
'
24+
25+
verify_path_exists() {
26+
# simply running ls on a file should be a good 'check'
27+
ipfs files ls $1
28+
}
29+
30+
verify_dir_contents() {
31+
dir=$1
32+
shift
33+
rm -f expected
34+
touch expected
35+
for e in $@
36+
do
37+
echo $e >> expected
38+
done
39+
40+
test_expect_success "can list dir" '
41+
ipfs files ls $dir > output
42+
'
43+
44+
test_expect_success "dir entries look good" '
45+
test_sort_cmp output expected
46+
'
47+
}
48+
49+
test_files_api() {
50+
test_expect_success "can mkdir in root" '
51+
ipfs files mkdir /cats
52+
'
53+
54+
test_expect_success "directory was created" '
55+
verify_path_exists /cats
56+
'
57+
58+
test_expect_success "directory is empty" '
59+
verify_dir_contents /cats
60+
'
61+
62+
test_expect_success "check root hash" '
63+
ipfs files stat / | head -n1 > roothash
64+
'
65+
66+
test_expect_success "cannot mkdir /" '
67+
test_expect_code 1 ipfs files mkdir /
68+
'
69+
70+
test_expect_success "check root hash was not changed" '
71+
ipfs files stat / | head -n1 > roothashafter &&
72+
test_cmp roothash roothashafter
73+
'
74+
75+
test_expect_success "can put files into directory" '
76+
ipfs files cp /ipfs/$FILE1 /cats/file1
77+
'
78+
79+
test_expect_success "file shows up in directory" '
80+
verify_dir_contents /cats file1
81+
'
82+
83+
test_expect_success "can read file" '
84+
ipfs files read /cats/file1 > file1out
85+
'
86+
87+
test_expect_success "output looks good" '
88+
echo foo > expected &&
89+
test_cmp expected file1out
90+
'
91+
92+
test_expect_success "can put another file into root" '
93+
ipfs files cp /ipfs/$FILE2 /file2
94+
'
95+
96+
test_expect_success "file shows up in root" '
97+
verify_dir_contents / file2 cats
98+
'
99+
100+
test_expect_success "can read file" '
101+
ipfs files read /file2 > file2out
102+
'
103+
104+
test_expect_success "output looks good" '
105+
echo bar > expected &&
106+
test_cmp expected file2out
107+
'
108+
109+
test_expect_success "can make deep directory" '
110+
ipfs files mkdir -p /cats/this/is/a/dir
111+
'
112+
113+
test_expect_success "directory was created correctly" '
114+
verify_path_exists /cats/this/is/a/dir &&
115+
verify_dir_contents /cats this file1 &&
116+
verify_dir_contents /cats/this is &&
117+
verify_dir_contents /cats/this/is a &&
118+
verify_dir_contents /cats/this/is/a dir &&
119+
verify_dir_contents /cats/this/is/a/dir
120+
'
121+
122+
test_expect_success "can copy file into new dir" '
123+
ipfs files cp /ipfs/$FILE3 /cats/this/is/a/dir/file3
124+
'
125+
126+
test_expect_success "can read file" '
127+
ipfs files read /cats/this/is/a/dir/file3 > output
128+
'
129+
130+
test_expect_success "output looks good" '
131+
echo baz > expected &&
132+
test_cmp expected output
133+
'
134+
135+
test_expect_success "file shows up in dir" '
136+
verify_dir_contents /cats/this/is/a/dir file3
137+
'
138+
139+
test_expect_success "can remove file" '
140+
ipfs files rm /cats/this/is/a/dir/file3
141+
'
142+
143+
test_expect_success "file no longer appears" '
144+
verify_dir_contents /cats/this/is/a/dir
145+
'
146+
147+
test_expect_success "can remove dir" '
148+
ipfs files rm -r /cats/this/is/a/dir
149+
'
150+
151+
test_expect_success "dir no longer appears" '
152+
verify_dir_contents /cats/this/is/a
153+
'
154+
155+
test_expect_success "can remove file from root" '
156+
ipfs files rm /file2
157+
'
158+
159+
test_expect_success "file no longer appears" '
160+
verify_dir_contents / cats
161+
'
162+
163+
test_expect_success "check root hash" '
164+
ipfs files stat / | head -n1 > roothash
165+
'
166+
167+
test_expect_success "cannot remove root" '
168+
test_expect_code 1 ipfs files rm -r /
169+
'
170+
171+
test_expect_success "check root hash was not changed" '
172+
ipfs files stat / | head -n1 > roothashafter &&
173+
test_cmp roothash roothashafter
174+
'
175+
176+
# test read options
177+
178+
test_expect_success "read from offset works" '
179+
ipfs files read -o 1 /cats/file1 > output
180+
'
181+
182+
test_expect_success "output looks good" '
183+
echo oo > expected &&
184+
test_cmp expected output
185+
'
186+
187+
test_expect_success "read with size works" '
188+
ipfs files read -n 2 /cats/file1 > output
189+
'
190+
191+
test_expect_success "output looks good" '
192+
printf fo > expected &&
193+
test_cmp expected output
194+
'
195+
196+
test_expect_success "cannot read from negative offset" '
197+
test_expect_code 1 ipfs files read --offset -3 /cats/file1
198+
'
199+
200+
test_expect_success "read from offset 0 works" '
201+
ipfs files read --offset 0 /cats/file1 > output
202+
'
203+
204+
test_expect_success "output looks good" '
205+
echo foo > expected &&
206+
test_cmp expected output
207+
'
208+
209+
test_expect_success "read last byte works" '
210+
ipfs files read --offset 2 /cats/file1 > output
211+
'
212+
213+
test_expect_success "output looks good" '
214+
echo o > expected &&
215+
test_cmp expected output
216+
'
217+
218+
test_expect_success "offset past end of file fails" '
219+
test_expect_code 1 ipfs files read --offset 5 /cats/file1
220+
'
221+
222+
test_expect_success "cannot read negative count bytes" '
223+
test_expect_code 1 ipfs read --count -1 /cats/file1
224+
'
225+
226+
test_expect_success "reading zero bytes prints nothing" '
227+
ipfs files read --count 0 /cats/file1 > output
228+
'
229+
230+
test_expect_success "output looks good" '
231+
printf "" > expected &&
232+
test_cmp expected output
233+
'
234+
235+
test_expect_success "count > len(file) prints entire file" '
236+
ipfs files read --count 200 /cats/file1 > output
237+
'
238+
239+
test_expect_success "output looks good" '
240+
echo foo > expected &&
241+
test_cmp expected output
242+
'
243+
244+
# test write
245+
246+
test_expect_success "can write file" '
247+
echo "ipfs rocks" > tmpfile &&
248+
cat tmpfile | ipfs files write --create /cats/ipfs
249+
'
250+
251+
test_expect_success "file was created" '
252+
verify_dir_contents /cats ipfs file1 this
253+
'
254+
255+
test_expect_success "can read file we just wrote" '
256+
ipfs files read /cats/ipfs > output
257+
'
258+
259+
test_expect_success "can write to offset" '
260+
echo "is super cool" | ipfs files write -o 5 /cats/ipfs
261+
'
262+
263+
test_expect_success "file looks correct" '
264+
echo "ipfs is super cool" > expected &&
265+
ipfs files read /cats/ipfs > output &&
266+
test_cmp expected output
267+
'
268+
269+
test_expect_success "cant write to negative offset" '
270+
ipfs files stat /cats/ipfs | head -n1 > filehash &&
271+
test_expect_code 1 ipfs files write --offset -1 /cats/ipfs < output
272+
'
273+
274+
test_expect_success "verify file was not changed" '
275+
ipfs files stat /cats/ipfs | head -n1 > afterhash &&
276+
test_cmp filehash afterhash
277+
'
278+
279+
test_expect_success "write new file for testing" '
280+
echo foobar | ipfs files write --create /fun
281+
'
282+
283+
test_expect_success "write to offset past end works" '
284+
echo blah | ipfs files write --offset 50 /fun
285+
'
286+
287+
test_expect_success "can read file" '
288+
ipfs files read /fun > sparse_output
289+
'
290+
291+
test_expect_success "output looks good" '
292+
echo foobar > sparse_expected &&
293+
echo blah | dd of=sparse_expected bs=50 seek=1 &&
294+
test_cmp sparse_expected sparse_output
295+
'
296+
297+
test_expect_success "cleanup" '
298+
ipfs files rm /fun
299+
'
300+
301+
test_expect_success "cannot write to directory" '
302+
ipfs files stat /cats | head -n1 > dirhash &&
303+
test_expect_code 1 ipfs files write /cats < output
304+
'
305+
306+
test_expect_success "verify dir was not changed" '
307+
ipfs files stat /cats | head -n1 > afterdirhash &&
308+
test_cmp dirhash afterdirhash
309+
'
310+
311+
test_expect_success "cannot write to nonexistant path" '
312+
test_expect_code 1 ipfs files write /cats/bar/ < output
313+
'
314+
315+
test_expect_success "no new paths were created" '
316+
verify_dir_contents /cats file1 ipfs this
317+
'
318+
319+
# test mv
320+
test_expect_success "can mv dir" '
321+
ipfs files mv /cats/this/is /cats/
322+
'
323+
324+
test_expect_success "mv worked" '
325+
verify_dir_contents /cats file1 ipfs this is &&
326+
verify_dir_contents /cats/this
327+
'
328+
329+
test_expect_success "cleanup, remove 'cats'" '
330+
ipfs files rm -r /cats
331+
'
332+
333+
test_expect_success "cleanup looks good" '
334+
verify_dir_contents /
335+
'
336+
}
337+
338+
# test offline and online
339+
test_files_api
340+
test_launch_ipfs_daemon
341+
test_files_api
342+
test_kill_ipfs_daemon
343+
test_done

‎unixfs/mod/dagmodifier.go

+16-4
Original file line numberDiff line numberDiff line change
@@ -368,19 +368,31 @@ func (dm *DagModifier) Seek(offset int64, whence int) (int64, error) {
368368
return 0, err
369369
}
370370

371+
fisize, err := dm.Size()
372+
if err != nil {
373+
return 0, err
374+
}
375+
376+
var newoffset uint64
371377
switch whence {
372378
case os.SEEK_CUR:
373-
dm.curWrOff += uint64(offset)
374-
dm.writeStart = dm.curWrOff
379+
newoffset = dm.curWrOff + uint64(offset)
375380
case os.SEEK_SET:
376-
dm.curWrOff = uint64(offset)
377-
dm.writeStart = uint64(offset)
381+
newoffset = uint64(offset)
378382
case os.SEEK_END:
379383
return 0, ErrSeekEndNotImpl
380384
default:
381385
return 0, ErrUnrecognizedWhence
382386
}
383387

388+
if offset > fisize {
389+
if err := dm.expandSparse(offset - fisize); err != nil {
390+
return 0, err
391+
}
392+
}
393+
dm.curWrOff = newoffset
394+
dm.writeStart = newoffset
395+
384396
if dm.read != nil {
385397
_, err = dm.read.Seek(offset, whence)
386398
if err != nil {

‎unixfs/mod/dagmodifier_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,53 @@ func TestSparseWrite(t *testing.T) {
487487
}
488488
}
489489

490+
func TestSeekPastEndWrite(t *testing.T) {
491+
dserv := getMockDagServ(t)
492+
_, n := getNode(t, dserv, 0)
493+
ctx, cancel := context.WithCancel(context.Background())
494+
defer cancel()
495+
496+
dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
497+
if err != nil {
498+
t.Fatal(err)
499+
}
500+
501+
buf := make([]byte, 5000)
502+
u.NewTimeSeededRand().Read(buf[2500:])
503+
504+
nseek, err := dagmod.Seek(2500, os.SEEK_SET)
505+
if err != nil {
506+
t.Fatal(err)
507+
}
508+
509+
if nseek != 2500 {
510+
t.Fatal("failed to seek")
511+
}
512+
513+
wrote, err := dagmod.Write(buf[2500:])
514+
if err != nil {
515+
t.Fatal(err)
516+
}
517+
518+
if wrote != 2500 {
519+
t.Fatal("incorrect write amount")
520+
}
521+
522+
_, err = dagmod.Seek(0, os.SEEK_SET)
523+
if err != nil {
524+
t.Fatal(err)
525+
}
526+
527+
out, err := ioutil.ReadAll(dagmod)
528+
if err != nil {
529+
t.Fatal(err)
530+
}
531+
532+
if err = arrComp(out, buf); err != nil {
533+
t.Fatal(err)
534+
}
535+
}
536+
490537
func BenchmarkDagmodWrite(b *testing.B) {
491538
b.StopTimer()
492539
dserv := getMockDagServ(b)

0 commit comments

Comments
 (0)
Please sign in to comment.