master
go 147 lines 3.5 KB
Raw
1 package integrationtest
2
3 import (
4 "bytes"
5 "context"
6 "errors"
7 "io"
8 "math"
9 "testing"
10 "time"
11
12 bootstrap2 "github.com/ipfs/boxo/bootstrap"
13 "github.com/ipfs/kubo/core/coreapi"
14 mock "github.com/ipfs/kubo/core/mock"
15 "github.com/ipfs/kubo/thirdparty/unit"
16
17 "github.com/ipfs/boxo/files"
18 testutil "github.com/libp2p/go-libp2p-testing/net"
19 "github.com/libp2p/go-libp2p/core/peer"
20 mocknet "github.com/libp2p/go-libp2p/p2p/net/mock"
21 )
22
23 func TestThreeLeggedCatTransfer(t *testing.T) {
24 conf := testutil.LatencyConfig{
25 NetworkLatency: 0,
26 RoutingLatency: 0,
27 BlockstoreLatency: 0,
28 }
29 if err := RunThreeLeggedCat(RandomBytes(1*unit.MB), conf); err != nil {
30 t.Fatal(err)
31 }
32 }
33
34 func TestThreeLeggedCatDegenerateSlowBlockstore(t *testing.T) {
35 SkipUnlessEpic(t)
36 conf := testutil.LatencyConfig{BlockstoreLatency: 50 * time.Millisecond}
37 if err := RunThreeLeggedCat(RandomBytes(1*unit.KB), conf); err != nil {
38 t.Fatal(err)
39 }
40 }
41
42 func TestThreeLeggedCatDegenerateSlowNetwork(t *testing.T) {
43 SkipUnlessEpic(t)
44 conf := testutil.LatencyConfig{NetworkLatency: 400 * time.Millisecond}
45 if err := RunThreeLeggedCat(RandomBytes(1*unit.KB), conf); err != nil {
46 t.Fatal(err)
47 }
48 }
49
50 func TestThreeLeggedCatDegenerateSlowRouting(t *testing.T) {
51 SkipUnlessEpic(t)
52 conf := testutil.LatencyConfig{RoutingLatency: 400 * time.Millisecond}
53 if err := RunThreeLeggedCat(RandomBytes(1*unit.KB), conf); err != nil {
54 t.Fatal(err)
55 }
56 }
57
58 func TestThreeLeggedCat100MBMacbookCoastToCoast(t *testing.T) {
59 SkipUnlessEpic(t)
60 conf := testutil.LatencyConfig{}.NetworkNYtoSF().BlockstoreSlowSSD2014().RoutingSlow()
61 if err := RunThreeLeggedCat(RandomBytes(100*unit.MB), conf); err != nil {
62 t.Fatal(err)
63 }
64 }
65
66 func RunThreeLeggedCat(data []byte, conf testutil.LatencyConfig) error {
67 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
68 defer cancel()
69
70 // create network
71 mn := mocknet.New()
72 mn.SetLinkDefaults(mocknet.LinkOptions{
73 Latency: conf.NetworkLatency,
74 // TODO add to conf. This is tricky because we want 0 values to be functional.
75 Bandwidth: math.MaxInt32,
76 })
77
78 bootstrap, err := mock.MockPublicNode(ctx, mn)
79 if err != nil {
80 return err
81 }
82 defer bootstrap.Close()
83
84 adder, err := mock.MockPublicNode(ctx, mn)
85 if err != nil {
86 return err
87 }
88 defer adder.Close()
89
90 catter, err := mock.MockPublicNode(ctx, mn)
91 if err != nil {
92 return err
93 }
94 defer catter.Close()
95
96 adderAPI, err := coreapi.NewCoreAPI(adder)
97 if err != nil {
98 return err
99 }
100
101 catterAPI, err := coreapi.NewCoreAPI(catter)
102 if err != nil {
103 return err
104 }
105
106 err = mn.LinkAll()
107 if err != nil {
108 return err
109 }
110
111 bis := bootstrap.Peerstore.PeerInfo(bootstrap.PeerHost.ID())
112 bcfg := bootstrap2.BootstrapConfigWithPeers([]peer.AddrInfo{bis})
113 if err := adder.Bootstrap(bcfg); err != nil {
114 return err
115 }
116 if err := catter.Bootstrap(bcfg); err != nil {
117 return err
118 }
119
120 added, err := adderAPI.Unixfs().Add(ctx, files.NewBytesFile(data))
121 if err != nil {
122 return err
123 }
124
125 // Explicitly provide the root CID to the DHT so the catter can discover
126 // the adder. Without this, the async reprovider may not have propagated
127 // the record before the catter queries.
128 if err := adder.Routing.Provide(ctx, added.RootCid(), true); err != nil {
129 return err
130 }
131
132 readerCatted, err := catterAPI.Unixfs().Get(ctx, added)
133 if err != nil {
134 return err
135 }
136
137 // verify
138 var bufout bytes.Buffer
139 _, err = io.Copy(&bufout, readerCatted.(io.Reader))
140 if err != nil {
141 return err
142 }
143 if !bytes.Equal(bufout.Bytes(), data) {
144 return errors.New("catted data does not match added data")
145 }
146 return nil
147 }