test: refactor some utities out of mod package
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
Jakub Sztandera committed
Aug 18, 2016 at 22:34 UTC
452a1d28a31142166beac73f5f4f7d69f7fe3a49
3 files changed
+154
-184
unixfs/io/dagserv_test.go
+5
-51
@@ -1,63 +1,17 @@
1
package io
2
3
import (
4
- "bytes"
5
- "fmt"
6
- "io"
4
"io/ioutil"
5
"testing"
6
10
- imp "github.com/ipfs/go-ipfs/importer"
11
- "github.com/ipfs/go-ipfs/importer/chunk"
12
- mdag "github.com/ipfs/go-ipfs/merkledag"
13
- mdagmock "github.com/ipfs/go-ipfs/merkledag/test"
14
-
15
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
7
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
17
-)
18
-
19
-func sizeSplitterGen(size int64) chunk.SplitterGen {
20
- return func(r io.Reader) chunk.Splitter {
21
- return chunk.NewSizeSplitter(r, size)
22
- }
23
-}
24
-
25
-func getNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
26
- in := bytes.NewReader(data)
27
- node, err := imp.BuildTrickleDagFromReader(dserv, sizeSplitterGen(500)(in))
28
- if err != nil {
29
- t.Fatal(err)
30
- }
31
-
32
- return node
33
-}
8
35
-func getRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.Node) {
36
- in := io.LimitReader(u.NewTimeSeededRand(), size)
37
- buf, err := ioutil.ReadAll(in)
38
- if err != nil {
39
- t.Fatal(err)
40
- }
41
-
42
- node := getNode(t, dserv, buf)
43
- return buf, node
44
-}
45
-
46
-func arrComp(a, b []byte) error {
47
- if len(a) != len(b) {
48
- return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b))
49
- }
50
- for i, v := range a {
51
- if v != b[i] {
52
- return fmt.Errorf("Arrays differ at index: %d", i)
53
- }
54
- }
55
- return nil
56
-}
9
+ testu "github.com/ipfs/go-ipfs/unixfs/test"
10
+)
11
12
func TestBasicRead(t *testing.T) {
59
- dserv := mdagmock.Mock()
60
- inbuf, node := getRandomNode(t, dserv, 1024)
13
+ dserv := testu.GetDAGServ()
14
+ inbuf, node := testu.GetRandomNode(t, dserv, 1024)
15
ctx, closer := context.WithCancel(context.Background())
16
defer closer()
17
@@ -71,7 +25,7 @@ func TestBasicRead(t *testing.T) {
25
t.Fatal(err)
26
}
27
74
- err = arrComp(inbuf, outbuf)
28
+ err = testu.ArrComp(inbuf, outbuf)
29
if err != nil {
30
t.Fatal(err)
31
}
unixfs/mod/dagmodifier_test.go
+56
-133
@@ -2,7 +2,6 @@ package mod
2
3
import (
4
"fmt"
5
- "io"
5
"io/ioutil"
6
"os"
7
"testing"
@@ -10,13 +9,12 @@ import (
9
"github.com/ipfs/go-ipfs/blocks/blockstore"
10
bs "github.com/ipfs/go-ipfs/blockservice"
11
"github.com/ipfs/go-ipfs/exchange/offline"
13
- imp "github.com/ipfs/go-ipfs/importer"
14
- "github.com/ipfs/go-ipfs/importer/chunk"
12
h "github.com/ipfs/go-ipfs/importer/helpers"
13
trickle "github.com/ipfs/go-ipfs/importer/trickle"
14
mdag "github.com/ipfs/go-ipfs/merkledag"
15
ft "github.com/ipfs/go-ipfs/unixfs"
16
uio "github.com/ipfs/go-ipfs/unixfs/io"
17
+ testu "github.com/ipfs/go-ipfs/unixfs/test"
18
19
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
20
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
@@ -24,14 +22,6 @@ import (
22
"gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
23
)
24
27
-func getMockDagServ(t testing.TB) mdag.DAGService {
28
- dstore := ds.NewMapDatastore()
29
- tsds := sync.MutexWrap(dstore)
30
- bstore := blockstore.NewBlockstore(tsds)
31
- bserv := bs.New(bstore, offline.Exchange(bstore))
32
- return mdag.NewDAGService(bserv)
33
-}
34
-
25
func getMockDagServAndBstore(t testing.TB) (mdag.DAGService, blockstore.GCBlockstore) {
26
dstore := ds.NewMapDatastore()
27
tsds := sync.MutexWrap(dstore)
@@ -41,26 +31,6 @@ func getMockDagServAndBstore(t testing.TB) (mdag.DAGService, blockstore.GCBlocks
31
return dserv, bstore
32
}
33
44
-func getNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.Node) {
45
- in := io.LimitReader(u.NewTimeSeededRand(), size)
46
- node, err := imp.BuildTrickleDagFromReader(dserv, sizeSplitterGen(500)(in))
47
- if err != nil {
48
- t.Fatal(err)
49
- }
50
-
51
- dr, err := uio.NewDagReader(context.Background(), node, dserv)
52
- if err != nil {
53
- t.Fatal(err)
54
- }
55
-
56
- b, err := ioutil.ReadAll(dr)
57
- if err != nil {
58
- t.Fatal(err)
59
- }
60
-
61
- return b, node
62
-}
63
-
34
func testModWrite(t *testing.T, beg, size uint64, orig []byte, dm *DagModifier) []byte {
35
newdata := make([]byte, size)
36
r := u.NewTimeSeededRand()
@@ -100,26 +70,20 @@ func testModWrite(t *testing.T, beg, size uint64, orig []byte, dm *DagModifier)
70
t.Fatal(err)
71
}
72
103
- err = arrComp(after, orig)
73
+ err = testu.ArrComp(after, orig)
74
if err != nil {
75
t.Fatal(err)
76
}
77
return orig
78
}
79
110
-func sizeSplitterGen(size int64) chunk.SplitterGen {
111
- return func(r io.Reader) chunk.Splitter {
112
- return chunk.NewSizeSplitter(r, size)
113
- }
114
-}
115
-
80
func TestDagModifierBasic(t *testing.T) {
117
- dserv := getMockDagServ(t)
118
- b, n := getNode(t, dserv, 50000)
81
+ dserv := testu.GetDAGServ()
82
+ b, n := testu.GetRandomNode(t, dserv, 50000)
83
ctx, cancel := context.WithCancel(context.Background())
84
defer cancel()
85
122
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
86
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
87
if err != nil {
88
t.Fatal(err)
89
}
@@ -168,13 +132,13 @@ func TestDagModifierBasic(t *testing.T) {
132
}
133
134
func TestMultiWrite(t *testing.T) {
171
- dserv := getMockDagServ(t)
172
- _, n := getNode(t, dserv, 0)
135
+ dserv := testu.GetDAGServ()
136
+ n := testu.GetEmptyNode(t, dserv)
137
138
ctx, cancel := context.WithCancel(context.Background())
139
defer cancel()
140
177
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
141
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
142
if err != nil {
143
t.Fatal(err)
144
}
@@ -214,20 +178,20 @@ func TestMultiWrite(t *testing.T) {
178
t.Fatal(err)
179
}
180
217
- err = arrComp(rbuf, data)
181
+ err = testu.ArrComp(rbuf, data)
182
if err != nil {
183
t.Fatal(err)
184
}
185
}
186
187
func TestMultiWriteAndFlush(t *testing.T) {
224
- dserv := getMockDagServ(t)
225
- _, n := getNode(t, dserv, 0)
188
+ dserv := testu.GetDAGServ()
189
+ n := testu.GetEmptyNode(t, dserv)
190
191
ctx, cancel := context.WithCancel(context.Background())
192
defer cancel()
193
230
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
194
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
195
if err != nil {
196
t.Fatal(err)
197
}
@@ -262,20 +226,20 @@ func TestMultiWriteAndFlush(t *testing.T) {
226
t.Fatal(err)
227
}
228
265
- err = arrComp(rbuf, data)
229
+ err = testu.ArrComp(rbuf, data)
230
if err != nil {
231
t.Fatal(err)
232
}
233
}
234
235
func TestWriteNewFile(t *testing.T) {
272
- dserv := getMockDagServ(t)
273
- _, n := getNode(t, dserv, 0)
236
+ dserv := testu.GetDAGServ()
237
+ n := testu.GetEmptyNode(t, dserv)
238
239
ctx, cancel := context.WithCancel(context.Background())
240
defer cancel()
241
278
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
242
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
243
if err != nil {
244
t.Fatal(err)
245
}
@@ -306,19 +270,19 @@ func TestWriteNewFile(t *testing.T) {
270
t.Fatal(err)
271
}
272
309
- if err := arrComp(data, towrite); err != nil {
273
+ if err := testu.ArrComp(data, towrite); err != nil {
274
t.Fatal(err)
275
}
276
}
277
278
func TestMultiWriteCoal(t *testing.T) {
315
- dserv := getMockDagServ(t)
316
- _, n := getNode(t, dserv, 0)
279
+ dserv := testu.GetDAGServ()
280
+ n := testu.GetEmptyNode(t, dserv)
281
282
ctx, cancel := context.WithCancel(context.Background())
283
defer cancel()
284
321
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
285
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
286
if err != nil {
287
t.Fatal(err)
288
}
@@ -351,20 +315,20 @@ func TestMultiWriteCoal(t *testing.T) {
315
t.Fatal(err)
316
}
317
354
- err = arrComp(rbuf, data)
318
+ err = testu.ArrComp(rbuf, data)
319
if err != nil {
320
t.Fatal(err)
321
}
322
}
323
324
func TestLargeWriteChunks(t *testing.T) {
361
- dserv := getMockDagServ(t)
362
- _, n := getNode(t, dserv, 0)
325
+ dserv := testu.GetDAGServ()
326
+ n := testu.GetEmptyNode(t, dserv)
327
328
ctx, cancel := context.WithCancel(context.Background())
329
defer cancel()
330
367
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
331
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
332
if err != nil {
333
t.Fatal(err)
334
}
@@ -390,19 +354,19 @@ func TestLargeWriteChunks(t *testing.T) {
354
t.Fatal(err)
355
}
356
393
- if err = arrComp(out, data); err != nil {
357
+ if err = testu.ArrComp(out, data); err != nil {
358
t.Fatal(err)
359
}
360
361
}
362
363
func TestDagTruncate(t *testing.T) {
400
- dserv := getMockDagServ(t)
401
- b, n := getNode(t, dserv, 50000)
364
+ dserv := testu.GetDAGServ()
365
+ b, n := testu.GetRandomNode(t, dserv, 50000)
366
ctx, cancel := context.WithCancel(context.Background())
367
defer cancel()
368
405
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
369
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
370
if err != nil {
371
t.Fatal(err)
372
}
@@ -430,7 +394,7 @@ func TestDagTruncate(t *testing.T) {
394
t.Fatal(err)
395
}
396
433
- if err = arrComp(out, b[:12345]); err != nil {
397
+ if err = testu.ArrComp(out, b[:12345]); err != nil {
398
t.Fatal(err)
399
}
400
@@ -464,12 +428,12 @@ func TestDagTruncate(t *testing.T) {
428
}
429
430
func TestSparseWrite(t *testing.T) {
467
- dserv := getMockDagServ(t)
468
- _, n := getNode(t, dserv, 0)
431
+ dserv := testu.GetDAGServ()
432
+ n := testu.GetEmptyNode(t, dserv)
433
ctx, cancel := context.WithCancel(context.Background())
434
defer cancel()
435
472
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
436
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
437
if err != nil {
438
t.Fatal(err)
439
}
@@ -496,18 +460,18 @@ func TestSparseWrite(t *testing.T) {
460
t.Fatal(err)
461
}
462
499
- if err = arrComp(out, buf); err != nil {
463
+ if err = testu.ArrComp(out, buf); err != nil {
464
t.Fatal(err)
465
}
466
}
467
468
func TestSeekPastEndWrite(t *testing.T) {
505
- dserv := getMockDagServ(t)
506
- _, n := getNode(t, dserv, 0)
469
+ dserv := testu.GetDAGServ()
470
+ n := testu.GetEmptyNode(t, dserv)
471
ctx, cancel := context.WithCancel(context.Background())
472
defer cancel()
473
510
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
474
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
475
if err != nil {
476
t.Fatal(err)
477
}
@@ -543,18 +507,18 @@ func TestSeekPastEndWrite(t *testing.T) {
507
t.Fatal(err)
508
}
509
546
- if err = arrComp(out, buf); err != nil {
510
+ if err = testu.ArrComp(out, buf); err != nil {
511
t.Fatal(err)
512
}
513
}
514
515
func TestRelativeSeek(t *testing.T) {
552
- dserv := getMockDagServ(t)
553
- _, n := getNode(t, dserv, 0)
516
+ dserv := testu.GetDAGServ()
517
+ n := testu.GetEmptyNode(t, dserv)
518
ctx, cancel := context.WithCancel(context.Background())
519
defer cancel()
520
557
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
521
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
522
if err != nil {
523
t.Fatal(err)
524
}
@@ -579,13 +543,12 @@ func TestRelativeSeek(t *testing.T) {
543
}
544
545
func TestInvalidSeek(t *testing.T) {
582
- dserv := getMockDagServ(t)
583
-
584
- _, n := getNode(t, dserv, 0)
546
+ dserv := testu.GetDAGServ()
547
+ n := testu.GetEmptyNode(t, dserv)
548
ctx, cancel := context.WithCancel(context.Background())
549
defer cancel()
550
588
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
551
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
552
if err != nil {
553
t.Fatal(err)
554
}
@@ -597,13 +560,13 @@ func TestInvalidSeek(t *testing.T) {
560
}
561
562
func TestEndSeek(t *testing.T) {
600
- dserv := getMockDagServ(t)
563
+ dserv := testu.GetDAGServ()
564
602
- _, n := getNode(t, dserv, 0)
565
+ n := testu.GetEmptyNode(t, dserv)
566
ctx, cancel := context.WithCancel(context.Background())
567
defer cancel()
568
606
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
569
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
570
if err != nil {
571
t.Fatal(err)
572
}
@@ -630,13 +593,13 @@ func TestEndSeek(t *testing.T) {
593
}
594
595
func TestReadAndSeek(t *testing.T) {
633
- dserv := getMockDagServ(t)
596
+ dserv := testu.GetDAGServ()
597
635
- _, n := getNode(t, dserv, 0)
598
+ n := testu.GetEmptyNode(t, dserv)
599
ctx, cancel := context.WithCancel(context.Background())
600
defer cancel()
601
639
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
602
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
603
if err != nil {
604
t.Fatal(err)
605
}
@@ -698,13 +661,13 @@ func TestReadAndSeek(t *testing.T) {
661
}
662
663
func TestCtxRead(t *testing.T) {
701
- dserv := getMockDagServ(t)
664
+ dserv := testu.GetDAGServ()
665
703
- _, n := getNode(t, dserv, 0)
666
+ n := testu.GetEmptyNode(t, dserv)
667
ctx, cancel := context.WithCancel(context.Background())
668
defer cancel()
669
707
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
670
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
671
if err != nil {
672
t.Fatal(err)
673
}
@@ -720,7 +683,7 @@ func TestCtxRead(t *testing.T) {
683
if err != nil {
684
t.Fatal(err)
685
}
723
- err = arrComp(readBuf, []byte{0, 1, 2, 3})
686
+ err = testu.ArrComp(readBuf, []byte{0, 1, 2, 3})
687
if err != nil {
688
t.Fatal(err)
689
}
@@ -730,14 +693,14 @@ func TestCtxRead(t *testing.T) {
693
694
func BenchmarkDagmodWrite(b *testing.B) {
695
b.StopTimer()
733
- dserv := getMockDagServ(b)
734
- _, n := getNode(b, dserv, 0)
696
+ dserv := testu.GetDAGServ()
697
+ n := testu.GetEmptyNode(b, dserv)
698
ctx, cancel := context.WithCancel(context.Background())
699
defer cancel()
700
701
wrsize := 4096
702
740
- dagmod, err := NewDagModifier(ctx, n, dserv, sizeSplitterGen(512))
703
+ dagmod, err := NewDagModifier(ctx, n, dserv, testu.SizeSplitterGen(512))
704
if err != nil {
705
b.Fatal(err)
706
}
@@ -756,43 +719,3 @@ func BenchmarkDagmodWrite(b *testing.B) {
719
}
720
}
721
}
759
-
760
-func arrComp(a, b []byte) error {
761
- if len(a) != len(b) {
762
- return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b))
763
- }
764
- for i, v := range a {
765
- if v != b[i] {
766
- return fmt.Errorf("Arrays differ at index: %d", i)
767
- }
768
- }
769
- return nil
770
-}
771
-
772
-func printDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
773
- pbd, err := ft.FromBytes(nd.Data())
774
- if err != nil {
775
- panic(err)
776
- }
777
-
778
- for i := 0; i < indent; i++ {
779
- fmt.Print(" ")
780
- }
781
- fmt.Printf("{size = %d, type = %s, children = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
782
- if len(nd.Links) > 0 {
783
- fmt.Println()
784
- }
785
- for _, lnk := range nd.Links {
786
- child, err := lnk.GetNode(context.Background(), ds)
787
- if err != nil {
788
- panic(err)
789
- }
790
- printDag(child, ds, indent+1)
791
- }
792
- if len(nd.Links) > 0 {
793
- for i := 0; i < indent; i++ {
794
- fmt.Print(" ")
795
- }
796
- }
797
- fmt.Println("}")
798
-}
unixfs/test/utils.go
new
+93
@@ -0,0 +1,93 @@
1
+package testu
2
+
3
+import (
4
+ "bytes"
5
+ "fmt"
6
+ "io"
7
+ "io/ioutil"
8
+ "testing"
9
+
10
+ imp "github.com/ipfs/go-ipfs/importer"
11
+ "github.com/ipfs/go-ipfs/importer/chunk"
12
+ mdag "github.com/ipfs/go-ipfs/merkledag"
13
+ mdagmock "github.com/ipfs/go-ipfs/merkledag/test"
14
+ ft "github.com/ipfs/go-ipfs/unixfs"
15
+
16
+ u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
17
+ context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
18
+)
19
+
20
+func SizeSplitterGen(size int64) chunk.SplitterGen {
21
+ return func(r io.Reader) chunk.Splitter {
22
+ return chunk.NewSizeSplitter(r, size)
23
+ }
24
+}
25
+
26
+func GetDAGServ() mdag.DAGService {
27
+ return mdagmock.Mock()
28
+}
29
+
30
+func GetNode(t testing.TB, dserv mdag.DAGService, data []byte) *mdag.Node {
31
+ in := bytes.NewReader(data)
32
+ node, err := imp.BuildTrickleDagFromReader(dserv, SizeSplitterGen(500)(in))
33
+ if err != nil {
34
+ t.Fatal(err)
35
+ }
36
+
37
+ return node
38
+}
39
+
40
+func GetEmptyNode(t testing.TB, dserv mdag.DAGService) *mdag.Node {
41
+ return GetNode(t, dserv, []byte{})
42
+}
43
+
44
+func GetRandomNode(t testing.TB, dserv mdag.DAGService, size int64) ([]byte, *mdag.Node) {
45
+ in := io.LimitReader(u.NewTimeSeededRand(), size)
46
+ buf, err := ioutil.ReadAll(in)
47
+ if err != nil {
48
+ t.Fatal(err)
49
+ }
50
+
51
+ node := GetNode(t, dserv, buf)
52
+ return buf, node
53
+}
54
+
55
+func ArrComp(a, b []byte) error {
56
+ if len(a) != len(b) {
57
+ return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b))
58
+ }
59
+ for i, v := range a {
60
+ if v != b[i] {
61
+ return fmt.Errorf("Arrays differ at index: %d", i)
62
+ }
63
+ }
64
+ return nil
65
+}
66
+
67
+func PrintDag(nd *mdag.Node, ds mdag.DAGService, indent int) {
68
+ pbd, err := ft.FromBytes(nd.Data())
69
+ if err != nil {
70
+ panic(err)
71
+ }
72
+
73
+ for i := 0; i < indent; i++ {
74
+ fmt.Print(" ")
75
+ }
76
+ fmt.Printf("{size = %d, type = %s, children = %d", pbd.GetFilesize(), pbd.GetType().String(), len(pbd.GetBlocksizes()))
77
+ if len(nd.Links) > 0 {
78
+ fmt.Println()
79
+ }
80
+ for _, lnk := range nd.Links {
81
+ child, err := lnk.GetNode(context.Background(), ds)
82
+ if err != nil {
83
+ panic(err)
84
+ }
85
+ PrintDag(child, ds, indent+1)
86
+ }
87
+ if len(nd.Links) > 0 {
88
+ for i := 0; i < indent; i++ {
89
+ fmt.Print(" ")
90
+ }
91
+ }
92
+ fmt.Println("}")
93
+}