coreapi: move tests to interface subpackage
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com> This commit was moved from ipfs/interface-go-ipfs-core@a479105a40eddefc84ca1de9aaaf12cbe2e13e56 This commit was moved from ipfs/boxo@3301b037c33fd42e0deb10965447a7e26e1e86fa
Łukasz Magiera committed
Dec 20, 2018 at 19:45 UTC
e60f2ba563c6a5708ba08c8140ac517b206dfda6
10 files changed
+3061
core/coreiface/tests/block_test.go
new
+183
@@ -0,0 +1,183 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "io/ioutil"
6
+ "strings"
7
+ "testing"
8
+
9
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
10
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11
+
12
+ mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash"
13
+)
14
+
15
+func TestBlockPut(t *testing.T) {
16
+ ctx := context.Background()
17
+ api, err := makeAPI(ctx)
18
+ if err != nil {
19
+ t.Error(err)
20
+ }
21
+
22
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`))
23
+ if err != nil {
24
+ t.Error(err)
25
+ }
26
+
27
+ if res.Path().Cid().String() != "QmPyo15ynbVrSTVdJL9th7JysHaAbXt9dM9tXk1bMHbRtk" {
28
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
29
+ }
30
+}
31
+
32
+func TestBlockPutFormat(t *testing.T) {
33
+ ctx := context.Background()
34
+ api, err := makeAPI(ctx)
35
+ if err != nil {
36
+ t.Error(err)
37
+ }
38
+
39
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Format("cbor"))
40
+ if err != nil {
41
+ t.Error(err)
42
+ }
43
+
44
+ if res.Path().Cid().String() != "zdpuAn4amuLWo8Widi5v6VQpuo2dnpnwbVE3oB6qqs7mDSeoa" {
45
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
46
+ }
47
+}
48
+
49
+func TestBlockPutHash(t *testing.T) {
50
+ ctx := context.Background()
51
+ api, err := makeAPI(ctx)
52
+ if err != nil {
53
+ t.Error(err)
54
+ }
55
+
56
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Hash(mh.KECCAK_512, -1))
57
+ if err != nil {
58
+ t.Fatal(err)
59
+ }
60
+
61
+ if res.Path().Cid().String() != "zBurKB9YZkcDf6xa53WBE8CFX4ydVqAyf9KPXBFZt5stJzEstaS8Hukkhu4gwpMtc1xHNDbzP7sPtQKyWsP3C8fbhkmrZ" {
62
+ t.Errorf("got wrong cid: %s", res.Path().Cid().String())
63
+ }
64
+}
65
+
66
+func TestBlockGet(t *testing.T) {
67
+ ctx := context.Background()
68
+ api, err := makeAPI(ctx)
69
+ if err != nil {
70
+ t.Error(err)
71
+ }
72
+
73
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`), opt.Block.Hash(mh.KECCAK_512, -1))
74
+ if err != nil {
75
+ t.Error(err)
76
+ }
77
+
78
+ r, err := api.Block().Get(ctx, res.Path())
79
+ if err != nil {
80
+ t.Error(err)
81
+ }
82
+
83
+ d, err := ioutil.ReadAll(r)
84
+ if err != nil {
85
+ t.Error(err)
86
+ }
87
+
88
+ if string(d) != "Hello" {
89
+ t.Error("didn't get correct data back")
90
+ }
91
+
92
+ p, err := coreiface.ParsePath("/ipfs/" + res.Path().Cid().String())
93
+ if err != nil {
94
+ t.Error(err)
95
+ }
96
+
97
+ rp, err := api.ResolvePath(ctx, p)
98
+ if err != nil {
99
+ t.Fatal(err)
100
+ }
101
+ if rp.Cid().String() != res.Path().Cid().String() {
102
+ t.Error("paths didn't match")
103
+ }
104
+}
105
+
106
+func TestBlockRm(t *testing.T) {
107
+ ctx := context.Background()
108
+ api, err := makeAPI(ctx)
109
+ if err != nil {
110
+ t.Error(err)
111
+ }
112
+
113
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`))
114
+ if err != nil {
115
+ t.Error(err)
116
+ }
117
+
118
+ r, err := api.Block().Get(ctx, res.Path())
119
+ if err != nil {
120
+ t.Error(err)
121
+ }
122
+
123
+ d, err := ioutil.ReadAll(r)
124
+ if err != nil {
125
+ t.Error(err)
126
+ }
127
+
128
+ if string(d) != "Hello" {
129
+ t.Error("didn't get correct data back")
130
+ }
131
+
132
+ err = api.Block().Rm(ctx, res.Path())
133
+ if err != nil {
134
+ t.Error(err)
135
+ }
136
+
137
+ _, err = api.Block().Get(ctx, res.Path())
138
+ if err == nil {
139
+ t.Error("expected err to exist")
140
+ }
141
+ if err.Error() != "blockservice: key not found" {
142
+ t.Errorf("unexpected error; %s", err.Error())
143
+ }
144
+
145
+ err = api.Block().Rm(ctx, res.Path())
146
+ if err == nil {
147
+ t.Error("expected err to exist")
148
+ }
149
+ if err.Error() != "blockstore: block not found" {
150
+ t.Errorf("unexpected error; %s", err.Error())
151
+ }
152
+
153
+ err = api.Block().Rm(ctx, res.Path(), opt.Block.Force(true))
154
+ if err != nil {
155
+ t.Error(err)
156
+ }
157
+}
158
+
159
+func TestBlockStat(t *testing.T) {
160
+ ctx := context.Background()
161
+ api, err := makeAPI(ctx)
162
+ if err != nil {
163
+ t.Error(err)
164
+ }
165
+
166
+ res, err := api.Block().Put(ctx, strings.NewReader(`Hello`))
167
+ if err != nil {
168
+ t.Error(err)
169
+ }
170
+
171
+ stat, err := api.Block().Stat(ctx, res.Path())
172
+ if err != nil {
173
+ t.Error(err)
174
+ }
175
+
176
+ if stat.Path().String() != res.Path().String() {
177
+ t.Error("paths don't match")
178
+ }
179
+
180
+ if stat.Size() != len("Hello") {
181
+ t.Error("length doesn't match")
182
+ }
183
+}
core/coreiface/tests/dag_test.go
new
+151
@@ -0,0 +1,151 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "path"
6
+ "strings"
7
+ "testing"
8
+
9
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
10
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11
+
12
+ mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash"
13
+)
14
+
15
+var (
16
+ treeExpected = map[string]struct{}{
17
+ "a": {},
18
+ "b": {},
19
+ "c": {},
20
+ "c/d": {},
21
+ "c/e": {},
22
+ }
23
+)
24
+
25
+func TestPut(t *testing.T) {
26
+ ctx := context.Background()
27
+ api, err := makeAPI(ctx)
28
+ if err != nil {
29
+ t.Error(err)
30
+ }
31
+
32
+ res, err := api.Dag().Put(ctx, strings.NewReader(`"Hello"`))
33
+ if err != nil {
34
+ t.Error(err)
35
+ }
36
+
37
+ if res.Cid().String() != "zdpuAqckYF3ToF3gcJNxPZXmnmGuXd3gxHCXhq81HGxBejEvv" {
38
+ t.Errorf("got wrong cid: %s", res.Cid().String())
39
+ }
40
+}
41
+
42
+func TestPutWithHash(t *testing.T) {
43
+ ctx := context.Background()
44
+ api, err := makeAPI(ctx)
45
+ if err != nil {
46
+ t.Error(err)
47
+ }
48
+
49
+ res, err := api.Dag().Put(ctx, strings.NewReader(`"Hello"`), opt.Dag.Hash(mh.ID, -1))
50
+ if err != nil {
51
+ t.Error(err)
52
+ }
53
+
54
+ if res.Cid().String() != "z5hRLNd2sv4z1c" {
55
+ t.Errorf("got wrong cid: %s", res.Cid().String())
56
+ }
57
+}
58
+
59
+func TestPath(t *testing.T) {
60
+ ctx := context.Background()
61
+ api, err := makeAPI(ctx)
62
+ if err != nil {
63
+ t.Error(err)
64
+ }
65
+
66
+ sub, err := api.Dag().Put(ctx, strings.NewReader(`"foo"`))
67
+ if err != nil {
68
+ t.Error(err)
69
+ }
70
+
71
+ res, err := api.Dag().Put(ctx, strings.NewReader(`{"lnk": {"/": "`+sub.Cid().String()+`"}}`))
72
+ if err != nil {
73
+ t.Error(err)
74
+ }
75
+
76
+ p, err := coreiface.ParsePath(path.Join(res.Cid().String(), "lnk"))
77
+ if err != nil {
78
+ t.Error(err)
79
+ }
80
+
81
+ nd, err := api.Dag().Get(ctx, p)
82
+ if err != nil {
83
+ t.Error(err)
84
+ }
85
+
86
+ if nd.Cid().String() != sub.Cid().String() {
87
+ t.Errorf("got unexpected cid %s, expected %s", nd.Cid().String(), sub.Cid().String())
88
+ }
89
+}
90
+
91
+func TestTree(t *testing.T) {
92
+ ctx := context.Background()
93
+ api, err := makeAPI(ctx)
94
+ if err != nil {
95
+ t.Error(err)
96
+ }
97
+
98
+ c, err := api.Dag().Put(ctx, strings.NewReader(`{"a": 123, "b": "foo", "c": {"d": 321, "e": 111}}`))
99
+ if err != nil {
100
+ t.Error(err)
101
+ }
102
+
103
+ res, err := api.Dag().Get(ctx, c)
104
+ if err != nil {
105
+ t.Error(err)
106
+ }
107
+
108
+ lst := res.Tree("", -1)
109
+ if len(lst) != len(treeExpected) {
110
+ t.Errorf("tree length of %d doesn't match expected %d", len(lst), len(treeExpected))
111
+ }
112
+
113
+ for _, ent := range lst {
114
+ if _, ok := treeExpected[ent]; !ok {
115
+ t.Errorf("unexpected tree entry %s", ent)
116
+ }
117
+ }
118
+}
119
+
120
+func TestBatch(t *testing.T) {
121
+ ctx := context.Background()
122
+ api, err := makeAPI(ctx)
123
+ if err != nil {
124
+ t.Error(err)
125
+ }
126
+
127
+ batch := api.Dag().Batch(ctx)
128
+
129
+ c, err := batch.Put(ctx, strings.NewReader(`"Hello"`))
130
+ if err != nil {
131
+ t.Error(err)
132
+ }
133
+
134
+ if c.Cid().String() != "zdpuAqckYF3ToF3gcJNxPZXmnmGuXd3gxHCXhq81HGxBejEvv" {
135
+ t.Errorf("got wrong cid: %s", c.Cid().String())
136
+ }
137
+
138
+ _, err = api.Dag().Get(ctx, c)
139
+ if err == nil || err.Error() != "merkledag: not found" {
140
+ t.Error(err)
141
+ }
142
+
143
+ if err := batch.Commit(ctx); err != nil {
144
+ t.Error(err)
145
+ }
146
+
147
+ _, err = api.Dag().Get(ctx, c)
148
+ if err != nil {
149
+ t.Error(err)
150
+ }
151
+}
core/coreiface/tests/dht_test.go
new
+126
@@ -0,0 +1,126 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "io"
6
+ "testing"
7
+
8
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
9
+)
10
+
11
+func TestDhtFindPeer(t *testing.T) {
12
+ ctx := context.Background()
13
+ apis, err := makeAPISwarm(ctx, true, 5)
14
+ if err != nil {
15
+ t.Fatal(err)
16
+ }
17
+
18
+ self0, err := apis[0].Key().Self(ctx)
19
+ if err != nil {
20
+ t.Fatal(err)
21
+ }
22
+
23
+ pi, err := apis[2].Dht().FindPeer(ctx, self0.ID())
24
+ if err != nil {
25
+ t.Fatal(err)
26
+ }
27
+
28
+ if pi.Addrs[0].String() != "/ip4/127.0.0.1/tcp/4001" {
29
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
30
+ }
31
+
32
+ self2, err := apis[2].Key().Self(ctx)
33
+ if err != nil {
34
+ t.Fatal(err)
35
+ }
36
+
37
+ pi, err = apis[1].Dht().FindPeer(ctx, self2.ID())
38
+ if err != nil {
39
+ t.Fatal(err)
40
+ }
41
+
42
+ if pi.Addrs[0].String() != "/ip4/127.0.2.1/tcp/4001" {
43
+ t.Errorf("got unexpected address from FindPeer: %s", pi.Addrs[0].String())
44
+ }
45
+}
46
+
47
+func TestDhtFindProviders(t *testing.T) {
48
+ ctx := context.Background()
49
+ apis, err := makeAPISwarm(ctx, true, 5)
50
+ if err != nil {
51
+ t.Fatal(err)
52
+ }
53
+
54
+ p, err := addTestObject(ctx, apis[0])
55
+ if err != nil {
56
+ t.Fatal(err)
57
+ }
58
+
59
+ out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
60
+ if err != nil {
61
+ t.Fatal(err)
62
+ }
63
+
64
+ provider := <-out
65
+
66
+ self0, err := apis[0].Key().Self(ctx)
67
+ if err != nil {
68
+ t.Fatal(err)
69
+ }
70
+
71
+ if provider.ID.String() != self0.ID().String() {
72
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
73
+ }
74
+}
75
+
76
+func TestDhtProvide(t *testing.T) {
77
+ ctx := context.Background()
78
+ apis, err := makeAPISwarm(ctx, true, 5)
79
+ if err != nil {
80
+ t.Fatal(err)
81
+ }
82
+
83
+ off0, err := apis[0].WithOptions(options.Api.Offline(true))
84
+ if err != nil {
85
+ t.Fatal(err)
86
+ }
87
+
88
+ s, err := off0.Block().Put(ctx, &io.LimitedReader{R: rnd, N: 4092})
89
+ if err != nil {
90
+ t.Fatal(err)
91
+ }
92
+
93
+ p := s.Path()
94
+
95
+ out, err := apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
96
+ if err != nil {
97
+ t.Fatal(err)
98
+ }
99
+
100
+ provider := <-out
101
+
102
+ self0, err := apis[0].Key().Self(ctx)
103
+ if err != nil {
104
+ t.Fatal(err)
105
+ }
106
+
107
+ if provider.ID.String() != "<peer.ID >" {
108
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
109
+ }
110
+
111
+ err = apis[0].Dht().Provide(ctx, p)
112
+ if err != nil {
113
+ t.Fatal(err)
114
+ }
115
+
116
+ out, err = apis[2].Dht().FindProviders(ctx, p, options.Dht.NumProviders(1))
117
+ if err != nil {
118
+ t.Fatal(err)
119
+ }
120
+
121
+ provider = <-out
122
+
123
+ if provider.ID.String() != self0.ID().String() {
124
+ t.Errorf("got wrong provider: %s != %s", provider.ID.String(), self0.ID().String())
125
+ }
126
+}
core/coreiface/tests/key_test.go
new
+475
@@ -0,0 +1,475 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "strings"
6
+ "testing"
7
+
8
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
9
+)
10
+
11
+func TestListSelf(t *testing.T) {
12
+ ctx := context.Background()
13
+ api, err := makeAPI(ctx)
14
+ if err != nil {
15
+ t.Fatal(err)
16
+ return
17
+ }
18
+
19
+ keys, err := api.Key().List(ctx)
20
+ if err != nil {
21
+ t.Fatalf("failed to list keys: %s", err)
22
+ return
23
+ }
24
+
25
+ if len(keys) != 1 {
26
+ t.Fatalf("there should be 1 key (self), got %d", len(keys))
27
+ return
28
+ }
29
+
30
+ if keys[0].Name() != "self" {
31
+ t.Errorf("expected the key to be called 'self', got '%s'", keys[0].Name())
32
+ }
33
+
34
+ if keys[0].Path().String() != "/ipns/"+testPeerID {
35
+ t.Errorf("expected the key to have path '/ipns/%s', got '%s'", testPeerID, keys[0].Path().String())
36
+ }
37
+}
38
+
39
+func TestRenameSelf(t *testing.T) {
40
+ ctx := context.Background()
41
+ api, err := makeAPI(ctx)
42
+ if err != nil {
43
+ t.Fatal(err)
44
+ return
45
+ }
46
+
47
+ _, _, err = api.Key().Rename(ctx, "self", "foo")
48
+ if err == nil {
49
+ t.Error("expected error to not be nil")
50
+ } else {
51
+ if err.Error() != "cannot rename key with name 'self'" {
52
+ t.Fatalf("expected error 'cannot rename key with name 'self'', got '%s'", err.Error())
53
+ }
54
+ }
55
+
56
+ _, _, err = api.Key().Rename(ctx, "self", "foo", opt.Key.Force(true))
57
+ if err == nil {
58
+ t.Error("expected error to not be nil")
59
+ } else {
60
+ if err.Error() != "cannot rename key with name 'self'" {
61
+ t.Fatalf("expected error 'cannot rename key with name 'self'', got '%s'", err.Error())
62
+ }
63
+ }
64
+}
65
+
66
+func TestRemoveSelf(t *testing.T) {
67
+ ctx := context.Background()
68
+ api, err := makeAPI(ctx)
69
+ if err != nil {
70
+ t.Fatal(err)
71
+ return
72
+ }
73
+
74
+ _, err = api.Key().Remove(ctx, "self")
75
+ if err == nil {
76
+ t.Error("expected error to not be nil")
77
+ } else {
78
+ if err.Error() != "cannot remove key with name 'self'" {
79
+ t.Fatalf("expected error 'cannot remove key with name 'self'', got '%s'", err.Error())
80
+ }
81
+ }
82
+}
83
+
84
+func TestGenerate(t *testing.T) {
85
+ ctx := context.Background()
86
+ api, err := makeAPI(ctx)
87
+ if err != nil {
88
+ t.Error(err)
89
+ }
90
+
91
+ k, err := api.Key().Generate(ctx, "foo")
92
+ if err != nil {
93
+ t.Fatal(err)
94
+ return
95
+ }
96
+
97
+ if k.Name() != "foo" {
98
+ t.Errorf("expected the key to be called 'foo', got '%s'", k.Name())
99
+ }
100
+
101
+ if !strings.HasPrefix(k.Path().String(), "/ipns/Qm") {
102
+ t.Errorf("expected the key to be prefixed with '/ipns/Qm', got '%s'", k.Path().String())
103
+ }
104
+}
105
+
106
+func TestGenerateSize(t *testing.T) {
107
+ ctx := context.Background()
108
+ api, err := makeAPI(ctx)
109
+ if err != nil {
110
+ t.Error(err)
111
+ }
112
+
113
+ k, err := api.Key().Generate(ctx, "foo", opt.Key.Size(1024))
114
+ if err != nil {
115
+ t.Fatal(err)
116
+ return
117
+ }
118
+
119
+ if k.Name() != "foo" {
120
+ t.Errorf("expected the key to be called 'foo', got '%s'", k.Name())
121
+ }
122
+
123
+ if !strings.HasPrefix(k.Path().String(), "/ipns/Qm") {
124
+ t.Errorf("expected the key to be prefixed with '/ipns/Qm', got '%s'", k.Path().String())
125
+ }
126
+}
127
+
128
+func TestGenerateType(t *testing.T) {
129
+ ctx := context.Background()
130
+ t.Skip("disabled until libp2p/specs#111 is fixed")
131
+
132
+ api, err := makeAPI(ctx)
133
+ if err != nil {
134
+ t.Error(err)
135
+ }
136
+
137
+ k, err := api.Key().Generate(ctx, "bar", opt.Key.Type(opt.Ed25519Key))
138
+ if err != nil {
139
+ t.Fatal(err)
140
+ return
141
+ }
142
+
143
+ if k.Name() != "bar" {
144
+ t.Errorf("expected the key to be called 'foo', got '%s'", k.Name())
145
+ }
146
+
147
+ // Expected to be an inlined identity hash.
148
+ if !strings.HasPrefix(k.Path().String(), "/ipns/12") {
149
+ t.Errorf("expected the key to be prefixed with '/ipns/12', got '%s'", k.Path().String())
150
+ }
151
+}
152
+
153
+func TestGenerateExisting(t *testing.T) {
154
+ ctx := context.Background()
155
+ api, err := makeAPI(ctx)
156
+ if err != nil {
157
+ t.Error(err)
158
+ }
159
+
160
+ _, err = api.Key().Generate(ctx, "foo")
161
+ if err != nil {
162
+ t.Fatal(err)
163
+ return
164
+ }
165
+
166
+ _, err = api.Key().Generate(ctx, "foo")
167
+ if err == nil {
168
+ t.Error("expected error to not be nil")
169
+ } else {
170
+ if err.Error() != "key with name 'foo' already exists" {
171
+ t.Fatalf("expected error 'key with name 'foo' already exists', got '%s'", err.Error())
172
+ }
173
+ }
174
+
175
+ _, err = api.Key().Generate(ctx, "self")
176
+ if err == nil {
177
+ t.Error("expected error to not be nil")
178
+ } else {
179
+ if err.Error() != "cannot create key with name 'self'" {
180
+ t.Fatalf("expected error 'cannot create key with name 'self'', got '%s'", err.Error())
181
+ }
182
+ }
183
+}
184
+
185
+func TestList(t *testing.T) {
186
+ ctx := context.Background()
187
+ api, err := makeAPI(ctx)
188
+ if err != nil {
189
+ t.Error(err)
190
+ }
191
+
192
+ _, err = api.Key().Generate(ctx, "foo")
193
+ if err != nil {
194
+ t.Fatal(err)
195
+ return
196
+ }
197
+
198
+ l, err := api.Key().List(ctx)
199
+ if err != nil {
200
+ t.Fatal(err)
201
+ return
202
+ }
203
+
204
+ if len(l) != 2 {
205
+ t.Fatalf("expected to get 2 keys, got %d", len(l))
206
+ return
207
+ }
208
+
209
+ if l[0].Name() != "self" {
210
+ t.Fatalf("expected key 0 to be called 'self', got '%s'", l[0].Name())
211
+ return
212
+ }
213
+
214
+ if l[1].Name() != "foo" {
215
+ t.Fatalf("expected key 1 to be called 'foo', got '%s'", l[1].Name())
216
+ return
217
+ }
218
+
219
+ if !strings.HasPrefix(l[0].Path().String(), "/ipns/Qm") {
220
+ t.Fatalf("expected key 0 to be prefixed with '/ipns/Qm', got '%s'", l[0].Name())
221
+ return
222
+ }
223
+
224
+ if !strings.HasPrefix(l[1].Path().String(), "/ipns/Qm") {
225
+ t.Fatalf("expected key 1 to be prefixed with '/ipns/Qm', got '%s'", l[1].Name())
226
+ return
227
+ }
228
+}
229
+
230
+func TestRename(t *testing.T) {
231
+ ctx := context.Background()
232
+ api, err := makeAPI(ctx)
233
+ if err != nil {
234
+ t.Error(err)
235
+ }
236
+
237
+ _, err = api.Key().Generate(ctx, "foo")
238
+ if err != nil {
239
+ t.Fatal(err)
240
+ return
241
+ }
242
+
243
+ k, overwrote, err := api.Key().Rename(ctx, "foo", "bar")
244
+ if err != nil {
245
+ t.Fatal(err)
246
+ return
247
+ }
248
+
249
+ if overwrote {
250
+ t.Error("overwrote should be false")
251
+ }
252
+
253
+ if k.Name() != "bar" {
254
+ t.Errorf("returned key should be called 'bar', got '%s'", k.Name())
255
+ }
256
+}
257
+
258
+func TestRenameToSelf(t *testing.T) {
259
+ ctx := context.Background()
260
+ api, err := makeAPI(ctx)
261
+ if err != nil {
262
+ t.Error(err)
263
+ }
264
+
265
+ _, err = api.Key().Generate(ctx, "foo")
266
+ if err != nil {
267
+ t.Fatal(err)
268
+ return
269
+ }
270
+
271
+ _, _, err = api.Key().Rename(ctx, "foo", "self")
272
+ if err == nil {
273
+ t.Error("expected error to not be nil")
274
+ } else {
275
+ if err.Error() != "cannot overwrite key with name 'self'" {
276
+ t.Fatalf("expected error 'cannot overwrite key with name 'self'', got '%s'", err.Error())
277
+ }
278
+ }
279
+}
280
+
281
+func TestRenameToSelfForce(t *testing.T) {
282
+ ctx := context.Background()
283
+ api, err := makeAPI(ctx)
284
+ if err != nil {
285
+ t.Error(err)
286
+ }
287
+
288
+ _, err = api.Key().Generate(ctx, "foo")
289
+ if err != nil {
290
+ t.Fatal(err)
291
+ return
292
+ }
293
+
294
+ _, _, err = api.Key().Rename(ctx, "foo", "self", opt.Key.Force(true))
295
+ if err == nil {
296
+ t.Error("expected error to not be nil")
297
+ } else {
298
+ if err.Error() != "cannot overwrite key with name 'self'" {
299
+ t.Fatalf("expected error 'cannot overwrite key with name 'self'', got '%s'", err.Error())
300
+ }
301
+ }
302
+}
303
+
304
+func TestRenameOverwriteNoForce(t *testing.T) {
305
+ ctx := context.Background()
306
+ api, err := makeAPI(ctx)
307
+ if err != nil {
308
+ t.Error(err)
309
+ }
310
+
311
+ _, err = api.Key().Generate(ctx, "foo")
312
+ if err != nil {
313
+ t.Fatal(err)
314
+ return
315
+ }
316
+
317
+ _, err = api.Key().Generate(ctx, "bar")
318
+ if err != nil {
319
+ t.Fatal(err)
320
+ return
321
+ }
322
+
323
+ _, _, err = api.Key().Rename(ctx, "foo", "bar")
324
+ if err == nil {
325
+ t.Error("expected error to not be nil")
326
+ } else {
327
+ if err.Error() != "key by that name already exists, refusing to overwrite" {
328
+ t.Fatalf("expected error 'key by that name already exists, refusing to overwrite', got '%s'", err.Error())
329
+ }
330
+ }
331
+}
332
+
333
+func TestRenameOverwrite(t *testing.T) {
334
+ ctx := context.Background()
335
+ api, err := makeAPI(ctx)
336
+ if err != nil {
337
+ t.Error(err)
338
+ }
339
+
340
+ kfoo, err := api.Key().Generate(ctx, "foo")
341
+ if err != nil {
342
+ t.Fatal(err)
343
+ return
344
+ }
345
+
346
+ _, err = api.Key().Generate(ctx, "bar")
347
+ if err != nil {
348
+ t.Fatal(err)
349
+ return
350
+ }
351
+
352
+ k, overwrote, err := api.Key().Rename(ctx, "foo", "bar", opt.Key.Force(true))
353
+ if err != nil {
354
+ t.Fatal(err)
355
+ return
356
+ }
357
+
358
+ if !overwrote {
359
+ t.Error("overwrote should be true")
360
+ }
361
+
362
+ if k.Name() != "bar" {
363
+ t.Errorf("returned key should be called 'bar', got '%s'", k.Name())
364
+ }
365
+
366
+ if k.Path().String() != kfoo.Path().String() {
367
+ t.Errorf("k and kfoo should have equal paths, '%s'!='%s'", k.Path().String(), kfoo.Path().String())
368
+ }
369
+}
370
+
371
+func TestRenameSameNameNoForce(t *testing.T) {
372
+ ctx := context.Background()
373
+ api, err := makeAPI(ctx)
374
+ if err != nil {
375
+ t.Error(err)
376
+ }
377
+
378
+ _, err = api.Key().Generate(ctx, "foo")
379
+ if err != nil {
380
+ t.Fatal(err)
381
+ return
382
+ }
383
+
384
+ k, overwrote, err := api.Key().Rename(ctx, "foo", "foo")
385
+ if err != nil {
386
+ t.Fatal(err)
387
+ return
388
+ }
389
+
390
+ if overwrote {
391
+ t.Error("overwrote should be false")
392
+ }
393
+
394
+ if k.Name() != "foo" {
395
+ t.Errorf("returned key should be called 'foo', got '%s'", k.Name())
396
+ }
397
+}
398
+
399
+func TestRenameSameName(t *testing.T) {
400
+ ctx := context.Background()
401
+ api, err := makeAPI(ctx)
402
+ if err != nil {
403
+ t.Error(err)
404
+ }
405
+
406
+ _, err = api.Key().Generate(ctx, "foo")
407
+ if err != nil {
408
+ t.Fatal(err)
409
+ return
410
+ }
411
+
412
+ k, overwrote, err := api.Key().Rename(ctx, "foo", "foo", opt.Key.Force(true))
413
+ if err != nil {
414
+ t.Fatal(err)
415
+ return
416
+ }
417
+
418
+ if overwrote {
419
+ t.Error("overwrote should be false")
420
+ }
421
+
422
+ if k.Name() != "foo" {
423
+ t.Errorf("returned key should be called 'foo', got '%s'", k.Name())
424
+ }
425
+}
426
+
427
+func TestRemove(t *testing.T) {
428
+ ctx := context.Background()
429
+ api, err := makeAPI(ctx)
430
+ if err != nil {
431
+ t.Error(err)
432
+ }
433
+
434
+ k, err := api.Key().Generate(ctx, "foo")
435
+ if err != nil {
436
+ t.Fatal(err)
437
+ return
438
+ }
439
+
440
+ l, err := api.Key().List(ctx)
441
+ if err != nil {
442
+ t.Fatal(err)
443
+ return
444
+ }
445
+
446
+ if len(l) != 2 {
447
+ t.Fatalf("expected to get 2 keys, got %d", len(l))
448
+ return
449
+ }
450
+
451
+ p, err := api.Key().Remove(ctx, "foo")
452
+ if err != nil {
453
+ t.Fatal(err)
454
+ return
455
+ }
456
+
457
+ if k.Path().String() != p.Path().String() {
458
+ t.Errorf("k and p should have equal paths, '%s'!='%s'", k.Path().String(), p.Path().String())
459
+ }
460
+
461
+ l, err = api.Key().List(ctx)
462
+ if err != nil {
463
+ t.Fatal(err)
464
+ return
465
+ }
466
+
467
+ if len(l) != 1 {
468
+ t.Fatalf("expected to get 1 key, got %d", len(l))
469
+ return
470
+ }
471
+
472
+ if l[0].Name() != "self" {
473
+ t.Errorf("expected the key to be called 'self', got '%s'", l[0].Name())
474
+ }
475
+}
core/coreiface/tests/name_test.go
new
+262
@@ -0,0 +1,262 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "io"
6
+ "math/rand"
7
+ "path"
8
+ "testing"
9
+ "time"
10
+
11
+ "gx/ipfs/QmXWZCd8jfaHmt4UDSnjKmGcrQMw95bDGWqEeVLVJjoANX/go-ipfs-files"
12
+ ipath "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path"
13
+
14
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
15
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
16
+)
17
+
18
+var rnd = rand.New(rand.NewSource(0x62796532303137))
19
+
20
+func addTestObject(ctx context.Context, api coreiface.CoreAPI) (coreiface.Path, error) {
21
+ return api.Unixfs().Add(ctx, files.NewReaderFile(&io.LimitedReader{R: rnd, N: 4092}))
22
+}
23
+
24
+func appendPath(p coreiface.Path, sub string) coreiface.Path {
25
+ p, err := coreiface.ParsePath(path.Join(p.String(), sub))
26
+ if err != nil {
27
+ panic(err)
28
+ }
29
+ return p
30
+}
31
+
32
+func TestPublishResolve(t *testing.T) {
33
+ ctx := context.Background()
34
+ init := func() (coreiface.CoreAPI, coreiface.Path) {
35
+ apis, err := makeAPISwarm(ctx, true, 5)
36
+ if err != nil {
37
+ t.Fatal(err)
38
+ return nil, nil
39
+ }
40
+ api := apis[0]
41
+
42
+ p, err := addTestObject(ctx, api)
43
+ if err != nil {
44
+ t.Fatal(err)
45
+ return nil, nil
46
+ }
47
+ return api, p
48
+ }
49
+
50
+ run := func(t *testing.T, ropts []opt.NameResolveOption) {
51
+ t.Run("basic", func(t *testing.T) {
52
+ api, p := init()
53
+ e, err := api.Name().Publish(ctx, p)
54
+ if err != nil {
55
+ t.Fatal(err)
56
+ }
57
+
58
+ self, err := api.Key().Self(ctx)
59
+ if err != nil {
60
+ t.Fatal(err)
61
+ }
62
+
63
+ if e.Name() != self.ID().Pretty() {
64
+ t.Errorf("expected e.Name to equal '%s', got '%s'", self.ID().Pretty(), e.Name())
65
+ }
66
+
67
+ if e.Value().String() != p.String() {
68
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
69
+ }
70
+
71
+ resPath, err := api.Name().Resolve(ctx, e.Name(), ropts...)
72
+ if err != nil {
73
+ t.Fatal(err)
74
+ }
75
+
76
+ if resPath.String() != p.String() {
77
+ t.Errorf("expected paths to match, '%s'!='%s'", resPath.String(), p.String())
78
+ }
79
+ })
80
+
81
+ t.Run("publishPath", func(t *testing.T) {
82
+ api, p := init()
83
+ e, err := api.Name().Publish(ctx, appendPath(p, "/test"))
84
+ if err != nil {
85
+ t.Fatal(err)
86
+ }
87
+
88
+ self, err := api.Key().Self(ctx)
89
+ if err != nil {
90
+ t.Fatal(err)
91
+ }
92
+
93
+ if e.Name() != self.ID().Pretty() {
94
+ t.Errorf("expected e.Name to equal '%s', got '%s'", self.ID().Pretty(), e.Name())
95
+ }
96
+
97
+ if e.Value().String() != p.String()+"/test" {
98
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
99
+ }
100
+
101
+ resPath, err := api.Name().Resolve(ctx, e.Name(), ropts...)
102
+ if err != nil {
103
+ t.Fatal(err)
104
+ }
105
+
106
+ if resPath.String() != p.String()+"/test" {
107
+ t.Errorf("expected paths to match, '%s'!='%s'", resPath.String(), p.String()+"/test")
108
+ }
109
+ })
110
+
111
+ t.Run("revolvePath", func(t *testing.T) {
112
+ api, p := init()
113
+ e, err := api.Name().Publish(ctx, p)
114
+ if err != nil {
115
+ t.Fatal(err)
116
+ }
117
+
118
+ self, err := api.Key().Self(ctx)
119
+ if err != nil {
120
+ t.Fatal(err)
121
+ }
122
+
123
+ if e.Name() != self.ID().Pretty() {
124
+ t.Errorf("expected e.Name to equal '%s', got '%s'", self.ID().Pretty(), e.Name())
125
+ }
126
+
127
+ if e.Value().String() != p.String() {
128
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
129
+ }
130
+
131
+ resPath, err := api.Name().Resolve(ctx, e.Name()+"/test", ropts...)
132
+ if err != nil {
133
+ t.Fatal(err)
134
+ }
135
+
136
+ if resPath.String() != p.String()+"/test" {
137
+ t.Errorf("expected paths to match, '%s'!='%s'", resPath.String(), p.String()+"/test")
138
+ }
139
+ })
140
+
141
+ t.Run("publishRevolvePath", func(t *testing.T) {
142
+ api, p := init()
143
+ e, err := api.Name().Publish(ctx, appendPath(p, "/a"))
144
+ if err != nil {
145
+ t.Fatal(err)
146
+ }
147
+
148
+ self, err := api.Key().Self(ctx)
149
+ if err != nil {
150
+ t.Fatal(err)
151
+ }
152
+
153
+ if e.Name() != self.ID().Pretty() {
154
+ t.Errorf("expected e.Name to equal '%s', got '%s'", self.ID().Pretty(), e.Name())
155
+ }
156
+
157
+ if e.Value().String() != p.String()+"/a" {
158
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
159
+ }
160
+
161
+ resPath, err := api.Name().Resolve(ctx, e.Name()+"/b", ropts...)
162
+ if err != nil {
163
+ t.Fatal(err)
164
+ }
165
+
166
+ if resPath.String() != p.String()+"/a/b" {
167
+ t.Errorf("expected paths to match, '%s'!='%s'", resPath.String(), p.String()+"/a/b")
168
+ }
169
+ })
170
+ }
171
+
172
+ t.Run("default", func(t *testing.T) {
173
+ run(t, []opt.NameResolveOption{})
174
+ })
175
+
176
+ t.Run("nocache", func(t *testing.T) {
177
+ run(t, []opt.NameResolveOption{opt.Name.Cache(false)})
178
+ })
179
+}
180
+
181
+func TestBasicPublishResolveKey(t *testing.T) {
182
+ ctx := context.Background()
183
+ apis, err := makeAPISwarm(ctx, true, 5)
184
+ if err != nil {
185
+ t.Fatal(err)
186
+ }
187
+ api := apis[0]
188
+
189
+ k, err := api.Key().Generate(ctx, "foo")
190
+ if err != nil {
191
+ t.Fatal(err)
192
+ }
193
+
194
+ p, err := addTestObject(ctx, api)
195
+ if err != nil {
196
+ t.Fatal(err)
197
+ }
198
+
199
+ e, err := api.Name().Publish(ctx, p, opt.Name.Key(k.Name()))
200
+ if err != nil {
201
+ t.Fatal(err)
202
+ }
203
+
204
+ if ipath.Join([]string{"/ipns", e.Name()}) != k.Path().String() {
205
+ t.Errorf("expected e.Name to equal '%s', got '%s'", e.Name(), k.Path().String())
206
+ }
207
+
208
+ if e.Value().String() != p.String() {
209
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
210
+ }
211
+
212
+ resPath, err := api.Name().Resolve(ctx, e.Name())
213
+ if err != nil {
214
+ t.Fatal(err)
215
+ }
216
+
217
+ if resPath.String() != p.String() {
218
+ t.Errorf("expected paths to match, '%s'!='%s'", resPath.String(), p.String())
219
+ }
220
+}
221
+
222
+func TestBasicPublishResolveTimeout(t *testing.T) {
223
+ t.Skip("ValidTime doesn't appear to work at this time resolution")
224
+
225
+ ctx := context.Background()
226
+ apis, err := makeAPISwarm(ctx, true, 5)
227
+ if err != nil {
228
+ t.Fatal(err)
229
+ }
230
+ api := apis[0]
231
+ p, err := addTestObject(ctx, api)
232
+ if err != nil {
233
+ t.Fatal(err)
234
+ }
235
+
236
+ e, err := api.Name().Publish(ctx, p, opt.Name.ValidTime(time.Millisecond*100))
237
+ if err != nil {
238
+ t.Fatal(err)
239
+ }
240
+
241
+ self, err := api.Key().Self(ctx)
242
+ if err != nil {
243
+ t.Fatal(err)
244
+ }
245
+
246
+ if e.Name() != self.ID().Pretty() {
247
+ t.Errorf("expected e.Name to equal '%s', got '%s'", self.ID().Pretty(), e.Name())
248
+ }
249
+
250
+ if e.Value().String() != p.String() {
251
+ t.Errorf("expected paths to match, '%s'!='%s'", e.Value().String(), p.String())
252
+ }
253
+
254
+ time.Sleep(time.Second)
255
+
256
+ _, err = api.Name().Resolve(ctx, e.Name())
257
+ if err == nil {
258
+ t.Fatal("Expected an error")
259
+ }
260
+}
261
+
262
+//TODO: When swarm api is created, add multinode tests
core/coreiface/tests/object_test.go
new
+427
@@ -0,0 +1,427 @@
1
+package tests_test
2
+
3
+import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/hex"
7
+ "io/ioutil"
8
+ "strings"
9
+ "testing"
10
+
11
+ "github.com/ipfs/go-ipfs/core/coreapi/interface"
12
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
13
+)
14
+
15
+func TestNew(t *testing.T) {
16
+ ctx := context.Background()
17
+ api, err := makeAPI(ctx)
18
+ if err != nil {
19
+ t.Fatal(err)
20
+ }
21
+
22
+ emptyNode, err := api.Object().New(ctx)
23
+ if err != nil {
24
+ t.Fatal(err)
25
+ }
26
+
27
+ dirNode, err := api.Object().New(ctx, opt.Object.Type("unixfs-dir"))
28
+ if err != nil {
29
+ t.Fatal(err)
30
+ }
31
+
32
+ if emptyNode.String() != "QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n" {
33
+ t.Errorf("Unexpected emptyNode path: %s", emptyNode.String())
34
+ }
35
+
36
+ if dirNode.String() != "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn" {
37
+ t.Errorf("Unexpected dirNode path: %s", dirNode.String())
38
+ }
39
+}
40
+
41
+func TestObjectPut(t *testing.T) {
42
+ ctx := context.Background()
43
+ api, err := makeAPI(ctx)
44
+ if err != nil {
45
+ t.Fatal(err)
46
+ }
47
+
48
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
49
+ if err != nil {
50
+ t.Fatal(err)
51
+ }
52
+
53
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"YmFy"}`), opt.Object.DataType("base64")) //bar
54
+ if err != nil {
55
+ t.Fatal(err)
56
+ }
57
+
58
+ pbBytes, err := hex.DecodeString("0a0362617a")
59
+ if err != nil {
60
+ t.Fatal(err)
61
+ }
62
+
63
+ p3, err := api.Object().Put(ctx, bytes.NewReader(pbBytes), opt.Object.InputEnc("protobuf"))
64
+ if err != nil {
65
+ t.Fatal(err)
66
+ }
67
+
68
+ if p1.String() != "/ipfs/QmQeGyS87nyijii7kFt1zbe4n2PsXTFimzsdxyE9qh9TST" {
69
+ t.Errorf("unexpected path: %s", p1.String())
70
+ }
71
+
72
+ if p2.String() != "/ipfs/QmNeYRbCibmaMMK6Du6ChfServcLqFvLJF76PzzF76SPrZ" {
73
+ t.Errorf("unexpected path: %s", p2.String())
74
+ }
75
+
76
+ if p3.String() != "/ipfs/QmZreR7M2t7bFXAdb1V5FtQhjk4t36GnrvueLJowJbQM9m" {
77
+ t.Errorf("unexpected path: %s", p3.String())
78
+ }
79
+}
80
+
81
+func TestObjectGet(t *testing.T) {
82
+ ctx := context.Background()
83
+ api, err := makeAPI(ctx)
84
+ if err != nil {
85
+ t.Fatal(err)
86
+ }
87
+
88
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
89
+ if err != nil {
90
+ t.Fatal(err)
91
+ }
92
+
93
+ nd, err := api.Object().Get(ctx, p1)
94
+ if err != nil {
95
+ t.Fatal(err)
96
+ }
97
+
98
+ if string(nd.RawData()[len(nd.RawData())-3:]) != "foo" {
99
+ t.Fatal("got non-matching data")
100
+ }
101
+}
102
+
103
+func TestObjectData(t *testing.T) {
104
+ ctx := context.Background()
105
+ api, err := makeAPI(ctx)
106
+ if err != nil {
107
+ t.Fatal(err)
108
+ }
109
+
110
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
111
+ if err != nil {
112
+ t.Fatal(err)
113
+ }
114
+
115
+ r, err := api.Object().Data(ctx, p1)
116
+ if err != nil {
117
+ t.Fatal(err)
118
+ }
119
+
120
+ data, err := ioutil.ReadAll(r)
121
+ if err != nil {
122
+ t.Fatal(err)
123
+ }
124
+
125
+ if string(data) != "foo" {
126
+ t.Fatal("got non-matching data")
127
+ }
128
+}
129
+
130
+func TestObjectLinks(t *testing.T) {
131
+ ctx := context.Background()
132
+ api, err := makeAPI(ctx)
133
+ if err != nil {
134
+ t.Fatal(err)
135
+ }
136
+
137
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
138
+ if err != nil {
139
+ t.Fatal(err)
140
+ }
141
+
142
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Links":[{"Name":"bar", "Hash":"`+p1.Cid().String()+`"}]}`))
143
+ if err != nil {
144
+ t.Fatal(err)
145
+ }
146
+
147
+ links, err := api.Object().Links(ctx, p2)
148
+ if err != nil {
149
+ t.Fatal(err)
150
+ }
151
+
152
+ if len(links) != 1 {
153
+ t.Errorf("unexpected number of links: %d", len(links))
154
+ }
155
+
156
+ if links[0].Cid.String() != p1.Cid().String() {
157
+ t.Fatal("cids didn't batch")
158
+ }
159
+
160
+ if links[0].Name != "bar" {
161
+ t.Fatal("unexpected link name")
162
+ }
163
+}
164
+
165
+func TestObjectStat(t *testing.T) {
166
+ ctx := context.Background()
167
+ api, err := makeAPI(ctx)
168
+ if err != nil {
169
+ t.Fatal(err)
170
+ }
171
+
172
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
173
+ if err != nil {
174
+ t.Fatal(err)
175
+ }
176
+
177
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.Cid().String()+`", "Size":3}]}`))
178
+ if err != nil {
179
+ t.Fatal(err)
180
+ }
181
+
182
+ stat, err := api.Object().Stat(ctx, p2)
183
+ if err != nil {
184
+ t.Fatal(err)
185
+ }
186
+
187
+ if stat.Cid.String() != p2.Cid().String() {
188
+ t.Error("unexpected stat.Cid")
189
+ }
190
+
191
+ if stat.NumLinks != 1 {
192
+ t.Errorf("unexpected stat.NumLinks")
193
+ }
194
+
195
+ if stat.BlockSize != 51 {
196
+ t.Error("unexpected stat.BlockSize")
197
+ }
198
+
199
+ if stat.LinksSize != 47 {
200
+ t.Errorf("unexpected stat.LinksSize: %d", stat.LinksSize)
201
+ }
202
+
203
+ if stat.DataSize != 4 {
204
+ t.Error("unexpected stat.DataSize")
205
+ }
206
+
207
+ if stat.CumulativeSize != 54 {
208
+ t.Error("unexpected stat.DataSize")
209
+ }
210
+}
211
+
212
+func TestObjectAddLink(t *testing.T) {
213
+ ctx := context.Background()
214
+ api, err := makeAPI(ctx)
215
+ if err != nil {
216
+ t.Fatal(err)
217
+ }
218
+
219
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
220
+ if err != nil {
221
+ t.Fatal(err)
222
+ }
223
+
224
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.Cid().String()+`", "Size":3}]}`))
225
+ if err != nil {
226
+ t.Fatal(err)
227
+ }
228
+
229
+ p3, err := api.Object().AddLink(ctx, p2, "abc", p2)
230
+ if err != nil {
231
+ t.Fatal(err)
232
+ }
233
+
234
+ links, err := api.Object().Links(ctx, p3)
235
+ if err != nil {
236
+ t.Fatal(err)
237
+ }
238
+
239
+ if len(links) != 2 {
240
+ t.Errorf("unexpected number of links: %d", len(links))
241
+ }
242
+
243
+ if links[0].Name != "abc" {
244
+ t.Errorf("unexpected link 0 name: %s", links[0].Name)
245
+ }
246
+
247
+ if links[1].Name != "bar" {
248
+ t.Errorf("unexpected link 1 name: %s", links[1].Name)
249
+ }
250
+}
251
+
252
+func TestObjectAddLinkCreate(t *testing.T) {
253
+ ctx := context.Background()
254
+ api, err := makeAPI(ctx)
255
+ if err != nil {
256
+ t.Fatal(err)
257
+ }
258
+
259
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
260
+ if err != nil {
261
+ t.Fatal(err)
262
+ }
263
+
264
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.Cid().String()+`", "Size":3}]}`))
265
+ if err != nil {
266
+ t.Fatal(err)
267
+ }
268
+
269
+ p3, err := api.Object().AddLink(ctx, p2, "abc/d", p2)
270
+ if err == nil {
271
+ t.Fatal("expected an error")
272
+ }
273
+ if err.Error() != "no link by that name" {
274
+ t.Fatalf("unexpected error: %s", err.Error())
275
+ }
276
+
277
+ p3, err = api.Object().AddLink(ctx, p2, "abc/d", p2, opt.Object.Create(true))
278
+ if err != nil {
279
+ t.Fatal(err)
280
+ }
281
+
282
+ links, err := api.Object().Links(ctx, p3)
283
+ if err != nil {
284
+ t.Fatal(err)
285
+ }
286
+
287
+ if len(links) != 2 {
288
+ t.Errorf("unexpected number of links: %d", len(links))
289
+ }
290
+
291
+ if links[0].Name != "abc" {
292
+ t.Errorf("unexpected link 0 name: %s", links[0].Name)
293
+ }
294
+
295
+ if links[1].Name != "bar" {
296
+ t.Errorf("unexpected link 1 name: %s", links[1].Name)
297
+ }
298
+}
299
+
300
+func TestObjectRmLink(t *testing.T) {
301
+ ctx := context.Background()
302
+ api, err := makeAPI(ctx)
303
+ if err != nil {
304
+ t.Fatal(err)
305
+ }
306
+
307
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
308
+ if err != nil {
309
+ t.Fatal(err)
310
+ }
311
+
312
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bazz", "Links":[{"Name":"bar", "Hash":"`+p1.Cid().String()+`", "Size":3}]}`))
313
+ if err != nil {
314
+ t.Fatal(err)
315
+ }
316
+
317
+ p3, err := api.Object().RmLink(ctx, p2, "bar")
318
+ if err != nil {
319
+ t.Fatal(err)
320
+ }
321
+
322
+ links, err := api.Object().Links(ctx, p3)
323
+ if err != nil {
324
+ t.Fatal(err)
325
+ }
326
+
327
+ if len(links) != 0 {
328
+ t.Errorf("unexpected number of links: %d", len(links))
329
+ }
330
+}
331
+
332
+func TestObjectAddData(t *testing.T) {
333
+ ctx := context.Background()
334
+ api, err := makeAPI(ctx)
335
+ if err != nil {
336
+ t.Fatal(err)
337
+ }
338
+
339
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
340
+ if err != nil {
341
+ t.Fatal(err)
342
+ }
343
+
344
+ p2, err := api.Object().AppendData(ctx, p1, strings.NewReader("bar"))
345
+ if err != nil {
346
+ t.Fatal(err)
347
+ }
348
+
349
+ r, err := api.Object().Data(ctx, p2)
350
+ if err != nil {
351
+ t.Fatal(err)
352
+ }
353
+
354
+ data, err := ioutil.ReadAll(r)
355
+
356
+ if string(data) != "foobar" {
357
+ t.Error("unexpected data")
358
+ }
359
+}
360
+
361
+func TestObjectSetData(t *testing.T) {
362
+ ctx := context.Background()
363
+ api, err := makeAPI(ctx)
364
+ if err != nil {
365
+ t.Fatal(err)
366
+ }
367
+
368
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
369
+ if err != nil {
370
+ t.Fatal(err)
371
+ }
372
+
373
+ p2, err := api.Object().SetData(ctx, p1, strings.NewReader("bar"))
374
+ if err != nil {
375
+ t.Fatal(err)
376
+ }
377
+
378
+ r, err := api.Object().Data(ctx, p2)
379
+ if err != nil {
380
+ t.Fatal(err)
381
+ }
382
+
383
+ data, err := ioutil.ReadAll(r)
384
+
385
+ if string(data) != "bar" {
386
+ t.Error("unexpected data")
387
+ }
388
+}
389
+
390
+func TestDiffTest(t *testing.T) {
391
+ ctx := context.Background()
392
+ api, err := makeAPI(ctx)
393
+ if err != nil {
394
+ t.Fatal(err)
395
+ }
396
+
397
+ p1, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"foo"}`))
398
+ if err != nil {
399
+ t.Fatal(err)
400
+ }
401
+
402
+ p2, err := api.Object().Put(ctx, strings.NewReader(`{"Data":"bar"}`))
403
+ if err != nil {
404
+ t.Fatal(err)
405
+ }
406
+
407
+ changes, err := api.Object().Diff(ctx, p1, p2)
408
+ if err != nil {
409
+ t.Fatal(err)
410
+ }
411
+
412
+ if len(changes) != 1 {
413
+ t.Fatal("unexpected changes len")
414
+ }
415
+
416
+ if changes[0].Type != iface.DiffMod {
417
+ t.Fatal("unexpected change type")
418
+ }
419
+
420
+ if changes[0].Before.String() != p1.String() {
421
+ t.Fatal("unexpected before path")
422
+ }
423
+
424
+ if changes[0].After.String() != p2.String() {
425
+ t.Fatal("unexpected before path")
426
+ }
427
+}
core/coreiface/tests/path_test.go
new
+154
@@ -0,0 +1,154 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "strings"
6
+ "testing"
7
+
8
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
9
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
10
+)
11
+
12
+func TestMutablePath(t *testing.T) {
13
+ ctx := context.Background()
14
+ api, err := makeAPI(ctx)
15
+ if err != nil {
16
+ t.Fatal(err)
17
+ }
18
+
19
+ // get self /ipns path
20
+ keys, err := api.Key().List(ctx)
21
+ if err != nil {
22
+ t.Fatal(err)
23
+ }
24
+
25
+ if !keys[0].Path().Mutable() {
26
+ t.Error("expected self /ipns path to be mutable")
27
+ }
28
+
29
+ blk, err := api.Block().Put(ctx, strings.NewReader(`foo`))
30
+ if err != nil {
31
+ t.Error(err)
32
+ }
33
+
34
+ if blk.Path().Mutable() {
35
+ t.Error("expected /ipld path to be immutable")
36
+ }
37
+}
38
+
39
+func TestPathRemainder(t *testing.T) {
40
+ ctx := context.Background()
41
+ api, err := makeAPI(ctx)
42
+ if err != nil {
43
+ t.Fatal(err)
44
+ }
45
+
46
+ obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`))
47
+ if err != nil {
48
+ t.Fatal(err)
49
+ }
50
+
51
+ p1, err := coreiface.ParsePath(obj.String() + "/foo/bar")
52
+ if err != nil {
53
+ t.Error(err)
54
+ }
55
+
56
+ rp1, err := api.ResolvePath(ctx, p1)
57
+ if err != nil {
58
+ t.Fatal(err)
59
+ }
60
+
61
+ if rp1.Remainder() != "foo/bar" {
62
+ t.Error("expected to get path remainder")
63
+ }
64
+}
65
+
66
+func TestEmptyPathRemainder(t *testing.T) {
67
+ ctx := context.Background()
68
+ api, err := makeAPI(ctx)
69
+ if err != nil {
70
+ t.Fatal(err)
71
+ }
72
+
73
+ obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`))
74
+ if err != nil {
75
+ t.Fatal(err)
76
+ }
77
+
78
+ if obj.Remainder() != "" {
79
+ t.Error("expected the resolved path to not have a remainder")
80
+ }
81
+
82
+ p1, err := coreiface.ParsePath(obj.String())
83
+ if err != nil {
84
+ t.Error(err)
85
+ }
86
+
87
+ rp1, err := api.ResolvePath(ctx, p1)
88
+ if err != nil {
89
+ t.Fatal(err)
90
+ }
91
+
92
+ if rp1.Remainder() != "" {
93
+ t.Error("expected the resolved path to not have a remainder")
94
+ }
95
+}
96
+
97
+func TestInvalidPathRemainder(t *testing.T) {
98
+ ctx := context.Background()
99
+ api, err := makeAPI(ctx)
100
+ if err != nil {
101
+ t.Fatal(err)
102
+ }
103
+
104
+ obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"bar": "baz"}}`))
105
+ if err != nil {
106
+ t.Fatal(err)
107
+ }
108
+
109
+ p1, err := coreiface.ParsePath(obj.String() + "/bar/baz")
110
+ if err != nil {
111
+ t.Error(err)
112
+ }
113
+
114
+ _, err = api.ResolvePath(ctx, p1)
115
+ if err == nil || err.Error() != "no such link found" {
116
+ t.Fatalf("unexpected error: %s", err)
117
+ }
118
+}
119
+
120
+func TestPathRoot(t *testing.T) {
121
+ ctx := context.Background()
122
+ api, err := makeAPI(ctx)
123
+ if err != nil {
124
+ t.Fatal(err)
125
+ }
126
+
127
+ blk, err := api.Block().Put(ctx, strings.NewReader(`foo`), options.Block.Format("raw"))
128
+ if err != nil {
129
+ t.Error(err)
130
+ }
131
+
132
+ obj, err := api.Dag().Put(ctx, strings.NewReader(`{"foo": {"/": "`+blk.Path().Cid().String()+`"}}`))
133
+ if err != nil {
134
+ t.Fatal(err)
135
+ }
136
+
137
+ p1, err := coreiface.ParsePath(obj.String() + "/foo")
138
+ if err != nil {
139
+ t.Error(err)
140
+ }
141
+
142
+ rp, err := api.ResolvePath(ctx, p1)
143
+ if err != nil {
144
+ t.Fatal(err)
145
+ }
146
+
147
+ if rp.Root().String() != obj.Cid().String() {
148
+ t.Error("unexpected path root")
149
+ }
150
+
151
+ if rp.Cid().String() != blk.Path().Cid().String() {
152
+ t.Error("unexpected path cid")
153
+ }
154
+}
core/coreiface/tests/pin_test.go
new
+214
@@ -0,0 +1,214 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "strings"
6
+ "testing"
7
+
8
+ opt "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
9
+)
10
+
11
+func TestPinAdd(t *testing.T) {
12
+ ctx := context.Background()
13
+ api, err := makeAPI(ctx)
14
+ if err != nil {
15
+ t.Error(err)
16
+ }
17
+
18
+ p, err := api.Unixfs().Add(ctx, strFile("foo")())
19
+ if err != nil {
20
+ t.Error(err)
21
+ }
22
+
23
+ err = api.Pin().Add(ctx, p)
24
+ if err != nil {
25
+ t.Error(err)
26
+ }
27
+}
28
+
29
+func TestPinSimple(t *testing.T) {
30
+ ctx := context.Background()
31
+ api, err := makeAPI(ctx)
32
+ if err != nil {
33
+ t.Error(err)
34
+ }
35
+
36
+ p, err := api.Unixfs().Add(ctx, strFile("foo")())
37
+ if err != nil {
38
+ t.Error(err)
39
+ }
40
+
41
+ err = api.Pin().Add(ctx, p)
42
+ if err != nil {
43
+ t.Error(err)
44
+ }
45
+
46
+ list, err := api.Pin().Ls(ctx)
47
+ if err != nil {
48
+ t.Fatal(err)
49
+ }
50
+
51
+ if len(list) != 1 {
52
+ t.Errorf("unexpected pin list len: %d", len(list))
53
+ }
54
+
55
+ if list[0].Path().Cid().String() != p.Cid().String() {
56
+ t.Error("paths don't match")
57
+ }
58
+
59
+ if list[0].Type() != "recursive" {
60
+ t.Error("unexpected pin type")
61
+ }
62
+
63
+ err = api.Pin().Rm(ctx, p)
64
+ if err != nil {
65
+ t.Fatal(err)
66
+ }
67
+
68
+ list, err = api.Pin().Ls(ctx)
69
+ if err != nil {
70
+ t.Fatal(err)
71
+ }
72
+
73
+ if len(list) != 0 {
74
+ t.Errorf("unexpected pin list len: %d", len(list))
75
+ }
76
+}
77
+
78
+func TestPinRecursive(t *testing.T) {
79
+ ctx := context.Background()
80
+ api, err := makeAPI(ctx)
81
+ if err != nil {
82
+ t.Error(err)
83
+ }
84
+
85
+ p0, err := api.Unixfs().Add(ctx, strFile("foo")())
86
+ if err != nil {
87
+ t.Error(err)
88
+ }
89
+
90
+ p1, err := api.Unixfs().Add(ctx, strFile("bar")())
91
+ if err != nil {
92
+ t.Error(err)
93
+ }
94
+
95
+ p2, err := api.Dag().Put(ctx, strings.NewReader(`{"lnk": {"/": "`+p0.Cid().String()+`"}}`))
96
+ if err != nil {
97
+ t.Error(err)
98
+ }
99
+
100
+ p3, err := api.Dag().Put(ctx, strings.NewReader(`{"lnk": {"/": "`+p1.Cid().String()+`"}}`))
101
+ if err != nil {
102
+ t.Error(err)
103
+ }
104
+
105
+ err = api.Pin().Add(ctx, p2)
106
+ if err != nil {
107
+ t.Error(err)
108
+ }
109
+
110
+ err = api.Pin().Add(ctx, p3, opt.Pin.Recursive(false))
111
+ if err != nil {
112
+ t.Error(err)
113
+ }
114
+
115
+ list, err := api.Pin().Ls(ctx)
116
+ if err != nil {
117
+ t.Fatal(err)
118
+ }
119
+
120
+ if len(list) != 3 {
121
+ t.Errorf("unexpected pin list len: %d", len(list))
122
+ }
123
+
124
+ list, err = api.Pin().Ls(ctx, opt.Pin.Type.Direct())
125
+ if err != nil {
126
+ t.Fatal(err)
127
+ }
128
+
129
+ if len(list) != 1 {
130
+ t.Errorf("unexpected pin list len: %d", len(list))
131
+ }
132
+
133
+ if list[0].Path().String() != p3.String() {
134
+ t.Error("unexpected path")
135
+ }
136
+
137
+ list, err = api.Pin().Ls(ctx, opt.Pin.Type.Recursive())
138
+ if err != nil {
139
+ t.Fatal(err)
140
+ }
141
+
142
+ if len(list) != 1 {
143
+ t.Errorf("unexpected pin list len: %d", len(list))
144
+ }
145
+
146
+ if list[0].Path().String() != p2.String() {
147
+ t.Error("unexpected path")
148
+ }
149
+
150
+ list, err = api.Pin().Ls(ctx, opt.Pin.Type.Indirect())
151
+ if err != nil {
152
+ t.Fatal(err)
153
+ }
154
+
155
+ if len(list) != 1 {
156
+ t.Errorf("unexpected pin list len: %d", len(list))
157
+ }
158
+
159
+ if list[0].Path().Cid().String() != p0.Cid().String() {
160
+ t.Error("unexpected path")
161
+ }
162
+
163
+ res, err := api.Pin().Verify(ctx)
164
+ if err != nil {
165
+ t.Fatal(err)
166
+ }
167
+ n := 0
168
+ for r := range res {
169
+ if !r.Ok() {
170
+ t.Error("expected pin to be ok")
171
+ }
172
+ n++
173
+ }
174
+
175
+ if n != 1 {
176
+ t.Errorf("unexpected verify result count: %d", n)
177
+ }
178
+
179
+ //TODO: figure out a way to test verify without touching IpfsNode
180
+ /*
181
+ err = api.Block().Rm(ctx, p0, opt.Block.Force(true))
182
+ if err != nil {
183
+ t.Fatal(err)
184
+ }
185
+
186
+ res, err = api.Pin().Verify(ctx)
187
+ if err != nil {
188
+ t.Fatal(err)
189
+ }
190
+ n = 0
191
+ for r := range res {
192
+ if r.Ok() {
193
+ t.Error("expected pin to not be ok")
194
+ }
195
+
196
+ if len(r.BadNodes()) != 1 {
197
+ t.Fatalf("unexpected badNodes len")
198
+ }
199
+
200
+ if r.BadNodes()[0].Path().Cid().String() != p0.Cid().String() {
201
+ t.Error("unexpected badNode path")
202
+ }
203
+
204
+ if r.BadNodes()[0].Err().Error() != "merkledag: not found" {
205
+ t.Errorf("unexpected badNode error: %s", r.BadNodes()[0].Err().Error())
206
+ }
207
+ n++
208
+ }
209
+
210
+ if n != 1 {
211
+ t.Errorf("unexpected verify result count: %d", n)
212
+ }
213
+ */
214
+}
core/coreiface/tests/pubsub_test.go
new
+106
@@ -0,0 +1,106 @@
1
+package tests_test
2
+
3
+import (
4
+ "context"
5
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
6
+ "testing"
7
+ "time"
8
+)
9
+
10
+func TestBasicPubSub(t *testing.T) {
11
+ ctx, cancel := context.WithCancel(context.Background())
12
+ defer cancel()
13
+
14
+ apis, err := makeAPISwarm(ctx, true, 2)
15
+ if err != nil {
16
+ t.Fatal(err)
17
+ }
18
+
19
+ sub, err := apis[0].PubSub().Subscribe(ctx, "testch")
20
+ if err != nil {
21
+ t.Fatal(err)
22
+ }
23
+
24
+ go func() {
25
+ tick := time.Tick(100 * time.Millisecond)
26
+
27
+ for {
28
+ err = apis[1].PubSub().Publish(ctx, "testch", []byte("hello world"))
29
+ if err != nil {
30
+ t.Fatal(err)
31
+ }
32
+ select {
33
+ case <-tick:
34
+ case <-ctx.Done():
35
+ return
36
+ }
37
+ }
38
+ }()
39
+
40
+ m, err := sub.Next(ctx)
41
+ if err != nil {
42
+ t.Fatal(err)
43
+ }
44
+
45
+ if string(m.Data()) != "hello world" {
46
+ t.Errorf("got invalid data: %s", string(m.Data()))
47
+ }
48
+
49
+ self1, err := apis[1].Key().Self(ctx)
50
+ if err != nil {
51
+ t.Fatal(err)
52
+ }
53
+
54
+ if m.From() != self1.ID() {
55
+ t.Errorf("m.From didn't match")
56
+ }
57
+
58
+ peers, err := apis[1].PubSub().Peers(ctx, options.PubSub.Topic("testch"))
59
+ if err != nil {
60
+ t.Fatal(err)
61
+ }
62
+
63
+ if len(peers) != 1 {
64
+ t.Fatalf("got incorrect number of peers: %d", len(peers))
65
+ }
66
+
67
+ self0, err := apis[0].Key().Self(ctx)
68
+ if err != nil {
69
+ t.Fatal(err)
70
+ }
71
+
72
+ if peers[0] != self0.ID() {
73
+ t.Errorf("peer didn't match")
74
+ }
75
+
76
+ peers, err = apis[1].PubSub().Peers(ctx, options.PubSub.Topic("nottestch"))
77
+ if err != nil {
78
+ t.Fatal(err)
79
+ }
80
+
81
+ if len(peers) != 0 {
82
+ t.Fatalf("got incorrect number of peers: %d", len(peers))
83
+ }
84
+
85
+ topics, err := apis[0].PubSub().Ls(ctx)
86
+ if err != nil {
87
+ t.Fatal(err)
88
+ }
89
+
90
+ if len(topics) != 1 {
91
+ t.Fatalf("got incorrect number of topics: %d", len(peers))
92
+ }
93
+
94
+ if topics[0] != "testch" {
95
+ t.Errorf("topic didn't match")
96
+ }
97
+
98
+ topics, err = apis[1].PubSub().Ls(ctx)
99
+ if err != nil {
100
+ t.Fatal(err)
101
+ }
102
+
103
+ if len(topics) != 0 {
104
+ t.Fatalf("got incorrect number of topics: %d", len(peers))
105
+ }
106
+}
core/coreiface/tests/unixfs_test.go
new
+963
@@ -0,0 +1,963 @@
1
+package tests_test
2
+
3
+import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/base64"
7
+ "fmt"
8
+ "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
9
+ "io"
10
+ "io/ioutil"
11
+ "math"
12
+ "os"
13
+ "strconv"
14
+ "strings"
15
+ "sync"
16
+ "testing"
17
+
18
+ "github.com/ipfs/go-ipfs/core"
19
+ "github.com/ipfs/go-ipfs/core/coreapi"
20
+ coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
21
+ "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
22
+ mock "github.com/ipfs/go-ipfs/core/mock"
23
+ "github.com/ipfs/go-ipfs/keystore"
24
+ "github.com/ipfs/go-ipfs/repo"
25
+
26
+ ci "gx/ipfs/QmNiJiXwWE3kRhZrC5ej3kSjWHm337pYfhjLGSCDNKJP2s/go-libp2p-crypto"
27
+ "gx/ipfs/QmRBaUEQEeFWywfrZJ64QgsmvcqgLSK3VbvGMR2NM2Edpf/go-libp2p/p2p/net/mock"
28
+ cbor "gx/ipfs/QmRoARq3nkUb13HSKZGepCZSWe5GrVPwx7xURJGZ7KWv9V/go-ipld-cbor"
29
+ "gx/ipfs/QmXWZCd8jfaHmt4UDSnjKmGcrQMw95bDGWqEeVLVJjoANX/go-ipfs-files"
30
+ "gx/ipfs/QmY5Grm8pJdiSSVsYxx4uNRgweY72EmYwuSDbRnbFok3iY/go-libp2p-peer"
31
+ pstore "gx/ipfs/QmZ9zH2FnLcxv1xyzFeUpDUeo55xEhZQHgveZijcxr7TLj/go-libp2p-peerstore"
32
+ "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs"
33
+ "gx/ipfs/QmcZfkbgwwwH5ZLTQRHkSQBDiDqd3skY2eU6MZRgWuXcse/go-ipfs-config"
34
+ mdag "gx/ipfs/QmdV35UHnL1FM52baPkeUo6u7Fxm2CRUkPTLRPxeF8a4Ap/go-merkledag"
35
+ mh "gx/ipfs/QmerPMzPk1mJVowm8KgmoknWa4yCYvvugMPsgWmDNUvDLW/go-multihash"
36
+ "gx/ipfs/Qmf4xQhNomPNhrtZc67qSnfJSjxjXs9LWvknJtSXwimPrM/go-datastore"
37
+ syncds "gx/ipfs/Qmf4xQhNomPNhrtZc67qSnfJSjxjXs9LWvknJtSXwimPrM/go-datastore/sync"
38
+)
39
+
40
+const testPeerID = "QmTFauExutTsy4XP6JbMFcw2Wa9645HJt2bTqL6qYDCKfe"
41
+
42
+// `echo -n 'hello, world!' | ipfs add`
43
+var hello = "/ipfs/QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk"
44
+var helloStr = "hello, world!"
45
+
46
+// `echo -n | ipfs add`
47
+var emptyFile = "/ipfs/QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH"
48
+
49
+func makeAPISwarm(ctx context.Context, fullIdentity bool, n int) ([]coreiface.CoreAPI, error) {
50
+ mn := mocknet.New(ctx)
51
+
52
+ nodes := make([]*core.IpfsNode, n)
53
+ apis := make([]coreiface.CoreAPI, n)
54
+
55
+ for i := 0; i < n; i++ {
56
+ var ident config.Identity
57
+ if fullIdentity {
58
+ sk, pk, err := ci.GenerateKeyPair(ci.RSA, 512)
59
+ if err != nil {
60
+ return nil, err
61
+ }
62
+
63
+ id, err := peer.IDFromPublicKey(pk)
64
+ if err != nil {
65
+ return nil, err
66
+ }
67
+
68
+ kbytes, err := sk.Bytes()
69
+ if err != nil {
70
+ return nil, err
71
+ }
72
+
73
+ ident = config.Identity{
74
+ PeerID: id.Pretty(),
75
+ PrivKey: base64.StdEncoding.EncodeToString(kbytes),
76
+ }
77
+ } else {
78
+ ident = config.Identity{
79
+ PeerID: testPeerID,
80
+ }
81
+ }
82
+
83
+ c := config.Config{}
84
+ c.Addresses.Swarm = []string{fmt.Sprintf("/ip4/127.0.%d.1/tcp/4001", i)}
85
+ c.Identity = ident
86
+
87
+ r := &repo.Mock{
88
+ C: c,
89
+ D: syncds.MutexWrap(datastore.NewMapDatastore()),
90
+ K: keystore.NewMemKeystore(),
91
+ }
92
+
93
+ node, err := core.NewNode(ctx, &core.BuildCfg{
94
+ Repo: r,
95
+ Host: mock.MockHostOption(mn),
96
+ Online: fullIdentity,
97
+ ExtraOpts: map[string]bool{
98
+ "pubsub": true,
99
+ },
100
+ })
101
+ if err != nil {
102
+ return nil, err
103
+ }
104
+ nodes[i] = node
105
+ apis[i], err = coreapi.NewCoreAPI(node)
106
+ if err != nil {
107
+ return nil, err
108
+ }
109
+ }
110
+
111
+ err := mn.LinkAll()
112
+ if err != nil {
113
+ return nil, err
114
+ }
115
+
116
+ bsinf := core.BootstrapConfigWithPeers(
117
+ []pstore.PeerInfo{
118
+ nodes[0].Peerstore.PeerInfo(nodes[0].Identity),
119
+ },
120
+ )
121
+
122
+ for _, n := range nodes[1:] {
123
+ if err := n.Bootstrap(bsinf); err != nil {
124
+ return nil, err
125
+ }
126
+ }
127
+
128
+ return apis, nil
129
+}
130
+
131
+func makeAPI(ctx context.Context) (coreiface.CoreAPI, error) {
132
+ api, err := makeAPISwarm(ctx, false, 1)
133
+ if err != nil {
134
+ return nil, err
135
+ }
136
+
137
+ return api[0], nil
138
+}
139
+
140
+func strFile(data string) func() files.Node {
141
+ return func() files.Node {
142
+ return files.NewBytesFile([]byte(data))
143
+ }
144
+}
145
+
146
+func twoLevelDir() func() files.Node {
147
+ return func() files.Node {
148
+ return files.NewMapDirectory(map[string]files.Node{
149
+ "abc": files.NewMapDirectory(map[string]files.Node{
150
+ "def": files.NewBytesFile([]byte("world")),
151
+ }),
152
+
153
+ "bar": files.NewBytesFile([]byte("hello2")),
154
+ "foo": files.NewBytesFile([]byte("hello1")),
155
+ })
156
+ }
157
+}
158
+
159
+func flatDir() files.Node {
160
+ return files.NewMapDirectory(map[string]files.Node{
161
+ "bar": files.NewBytesFile([]byte("hello2")),
162
+ "foo": files.NewBytesFile([]byte("hello1")),
163
+ })
164
+}
165
+
166
+func wrapped(name string) func(f files.Node) files.Node {
167
+ return func(f files.Node) files.Node {
168
+ return files.NewMapDirectory(map[string]files.Node{
169
+ name: f,
170
+ })
171
+ }
172
+}
173
+
174
+func TestAdd(t *testing.T) {
175
+ ctx := context.Background()
176
+ api, err := makeAPI(ctx)
177
+ if err != nil {
178
+ t.Error(err)
179
+ }
180
+
181
+ p := func(h string) coreiface.ResolvedPath {
182
+ c, err := cid.Parse(h)
183
+ if err != nil {
184
+ t.Fatal(err)
185
+ }
186
+ return coreiface.IpfsPath(c)
187
+ }
188
+
189
+ cases := []struct {
190
+ name string
191
+ data func() files.Node
192
+ expect func(files.Node) files.Node
193
+
194
+ apiOpts []options.ApiOption
195
+
196
+ path string
197
+ err string
198
+
199
+ wrap string
200
+
201
+ events []coreiface.AddEvent
202
+
203
+ opts []options.UnixfsAddOption
204
+ }{
205
+ // Simple cases
206
+ {
207
+ name: "simpleAdd",
208
+ data: strFile(helloStr),
209
+ path: hello,
210
+ opts: []options.UnixfsAddOption{},
211
+ },
212
+ {
213
+ name: "addEmpty",
214
+ data: strFile(""),
215
+ path: emptyFile,
216
+ },
217
+ // CIDv1 version / rawLeaves
218
+ {
219
+ name: "addCidV1",
220
+ data: strFile(helloStr),
221
+ path: "/ipfs/zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd",
222
+ opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(1)},
223
+ },
224
+ {
225
+ name: "addCidV1NoLeaves",
226
+ data: strFile(helloStr),
227
+ path: "/ipfs/zdj7WY4GbN8NDbTW1dfCShAQNVovams2xhq9hVCx5vXcjvT8g",
228
+ opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(1), options.Unixfs.RawLeaves(false)},
229
+ },
230
+ // Non sha256 hash vs CID
231
+ {
232
+ name: "addCidSha3",
233
+ data: strFile(helloStr),
234
+ path: "/ipfs/zb2wwnYtXBxpndNABjtYxWAPt3cwWNRnc11iT63fvkYV78iRb",
235
+ opts: []options.UnixfsAddOption{options.Unixfs.Hash(mh.SHA3_256)},
236
+ },
237
+ {
238
+ name: "addCidSha3Cid0",
239
+ data: strFile(helloStr),
240
+ err: "CIDv0 only supports sha2-256",
241
+ opts: []options.UnixfsAddOption{options.Unixfs.CidVersion(0), options.Unixfs.Hash(mh.SHA3_256)},
242
+ },
243
+ // Inline
244
+ {
245
+ name: "addInline",
246
+ data: strFile(helloStr),
247
+ path: "/ipfs/zaYomJdLndMku8P9LHngHB5w2CQ7NenLbv",
248
+ opts: []options.UnixfsAddOption{options.Unixfs.Inline(true)},
249
+ },
250
+ {
251
+ name: "addInlineLimit",
252
+ data: strFile(helloStr),
253
+ path: "/ipfs/zaYomJdLndMku8P9LHngHB5w2CQ7NenLbv",
254
+ opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(32), options.Unixfs.Inline(true)},
255
+ },
256
+ {
257
+ name: "addInlineZero",
258
+ data: strFile(""),
259
+ path: "/ipfs/z2yYDV",
260
+ opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(0), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true)},
261
+ },
262
+ { //TODO: after coreapi add is used in `ipfs add`, consider making this default for inline
263
+ name: "addInlineRaw",
264
+ data: strFile(helloStr),
265
+ path: "/ipfs/zj7Gr8AcBreqGEfrnR5kPFe",
266
+ opts: []options.UnixfsAddOption{options.Unixfs.InlineLimit(32), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true)},
267
+ },
268
+ // Chunker / Layout
269
+ {
270
+ name: "addChunks",
271
+ data: strFile(strings.Repeat("aoeuidhtns", 200)),
272
+ path: "/ipfs/QmRo11d4QJrST47aaiGVJYwPhoNA4ihRpJ5WaxBWjWDwbX",
273
+ opts: []options.UnixfsAddOption{options.Unixfs.Chunker("size-4")},
274
+ },
275
+ {
276
+ name: "addChunksTrickle",
277
+ data: strFile(strings.Repeat("aoeuidhtns", 200)),
278
+ path: "/ipfs/QmNNhDGttafX3M1wKWixGre6PrLFGjnoPEDXjBYpTv93HP",
279
+ opts: []options.UnixfsAddOption{options.Unixfs.Chunker("size-4"), options.Unixfs.Layout(options.TrickleLayout)},
280
+ },
281
+ // Local
282
+ {
283
+ name: "addLocal", // better cases in sharness
284
+ data: strFile(helloStr),
285
+ path: hello,
286
+ apiOpts: []options.ApiOption{options.Api.Offline(true)},
287
+ },
288
+ {
289
+ name: "hashOnly", // test (non)fetchability
290
+ data: strFile(helloStr),
291
+ path: hello,
292
+ opts: []options.UnixfsAddOption{options.Unixfs.HashOnly(true)},
293
+ },
294
+ // multi file
295
+ {
296
+ name: "simpleDir",
297
+ data: flatDir,
298
+ wrap: "t",
299
+ path: "/ipfs/QmRKGpFfR32FVXdvJiHfo4WJ5TDYBsM1P9raAp1p6APWSp",
300
+ },
301
+ {
302
+ name: "twoLevelDir",
303
+ data: twoLevelDir(),
304
+ wrap: "t",
305
+ path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr",
306
+ },
307
+ // wrapped
308
+ {
309
+ name: "addWrapped",
310
+ path: "/ipfs/QmVE9rNpj5doj7XHzp5zMUxD7BJgXEqx4pe3xZ3JBReWHE",
311
+ data: func() files.Node {
312
+ return files.NewBytesFile([]byte(helloStr))
313
+ },
314
+ wrap: "foo",
315
+ expect: wrapped("foo"),
316
+ opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)},
317
+ },
318
+ {
319
+ name: "addNotWrappedDirFile",
320
+ path: hello,
321
+ data: func() files.Node {
322
+ return files.NewBytesFile([]byte(helloStr))
323
+ },
324
+ wrap: "foo",
325
+ },
326
+ {
327
+ name: "stdinWrapped",
328
+ path: "/ipfs/QmU3r81oZycjHS9oaSHw37ootMFuFUw1DvMLKXPsezdtqU",
329
+ data: func() files.Node {
330
+ return files.NewBytesFile([]byte(helloStr))
331
+ },
332
+ expect: func(files.Node) files.Node {
333
+ return files.NewMapDirectory(map[string]files.Node{
334
+ "QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk": files.NewBytesFile([]byte(helloStr)),
335
+ })
336
+ },
337
+ opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)},
338
+ },
339
+ {
340
+ name: "stdinNamed",
341
+ path: "/ipfs/QmQ6cGBmb3ZbdrQW1MRm1RJnYnaxCqfssz7CrTa9NEhQyS",
342
+ data: func() files.Node {
343
+ rf, err := files.NewReaderPathFile(os.Stdin.Name(), ioutil.NopCloser(strings.NewReader(helloStr)), nil)
344
+ if err != nil {
345
+ panic(err)
346
+ }
347
+
348
+ return rf
349
+ },
350
+ expect: func(files.Node) files.Node {
351
+ return files.NewMapDirectory(map[string]files.Node{
352
+ "test": files.NewBytesFile([]byte(helloStr)),
353
+ })
354
+ },
355
+ opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true), options.Unixfs.StdinName("test")},
356
+ },
357
+ {
358
+ name: "twoLevelDirWrapped",
359
+ data: twoLevelDir(),
360
+ wrap: "t",
361
+ expect: wrapped("t"),
362
+ path: "/ipfs/QmPwsL3T5sWhDmmAWZHAzyjKtMVDS9a11aHNRqb3xoVnmg",
363
+ opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true)},
364
+ },
365
+ {
366
+ name: "twoLevelInlineHash",
367
+ data: twoLevelDir(),
368
+ wrap: "t",
369
+ expect: wrapped("t"),
370
+ path: "/ipfs/zBunoruKoyCHKkALNSWxDvj4L7yuQnMgQ4hUa9j1Z64tVcDEcu6Zdetyu7eeFCxMPfxb7YJvHeFHoFoHMkBUQf6vfdhmi",
371
+ opts: []options.UnixfsAddOption{options.Unixfs.Wrap(true), options.Unixfs.Inline(true), options.Unixfs.RawLeaves(true), options.Unixfs.Hash(mh.SHA3)},
372
+ },
373
+ // hidden
374
+ {
375
+ name: "hiddenFiles",
376
+ data: func() files.Node {
377
+ return files.NewMapDirectory(map[string]files.Node{
378
+ ".bar": files.NewBytesFile([]byte("hello2")),
379
+ "bar": files.NewBytesFile([]byte("hello2")),
380
+ "foo": files.NewBytesFile([]byte("hello1")),
381
+ })
382
+ },
383
+ wrap: "t",
384
+ path: "/ipfs/QmehGvpf2hY196MzDFmjL8Wy27S4jbgGDUAhBJyvXAwr3g",
385
+ opts: []options.UnixfsAddOption{options.Unixfs.Hidden(true)},
386
+ },
387
+ {
388
+ name: "hiddenFileAlwaysAdded",
389
+ data: func() files.Node {
390
+ return files.NewBytesFile([]byte(helloStr))
391
+ },
392
+ wrap: ".foo",
393
+ path: hello,
394
+ },
395
+ {
396
+ name: "hiddenFilesNotAdded",
397
+ data: func() files.Node {
398
+ return files.NewMapDirectory(map[string]files.Node{
399
+ ".bar": files.NewBytesFile([]byte("hello2")),
400
+ "bar": files.NewBytesFile([]byte("hello2")),
401
+ "foo": files.NewBytesFile([]byte("hello1")),
402
+ })
403
+ },
404
+ expect: func(files.Node) files.Node {
405
+ return flatDir()
406
+ },
407
+ wrap: "t",
408
+ path: "/ipfs/QmRKGpFfR32FVXdvJiHfo4WJ5TDYBsM1P9raAp1p6APWSp",
409
+ opts: []options.UnixfsAddOption{options.Unixfs.Hidden(false)},
410
+ },
411
+ // Events / Progress
412
+ {
413
+ name: "simpleAddEvent",
414
+ data: strFile(helloStr),
415
+ path: "/ipfs/zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd",
416
+ events: []coreiface.AddEvent{
417
+ {Name: "zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd", Path: p("zb2rhdhmJjJZs9qkhQCpCQ7VREFkqWw3h1r8utjVvQugwHPFd"), Size: strconv.Itoa(len(helloStr))},
418
+ },
419
+ opts: []options.UnixfsAddOption{options.Unixfs.RawLeaves(true)},
420
+ },
421
+ {
422
+ name: "silentAddEvent",
423
+ data: twoLevelDir(),
424
+ path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr",
425
+ events: []coreiface.AddEvent{
426
+ {Name: "t/abc", Path: p("QmU7nuGs2djqK99UNsNgEPGh6GV4662p6WtsgccBNGTDxt"), Size: "62"},
427
+ {Name: "t", Path: p("QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr"), Size: "229"},
428
+ },
429
+ wrap: "t",
430
+ opts: []options.UnixfsAddOption{options.Unixfs.Silent(true)},
431
+ },
432
+ {
433
+ name: "dirAddEvents",
434
+ data: twoLevelDir(),
435
+ path: "/ipfs/QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr",
436
+ events: []coreiface.AddEvent{
437
+ {Name: "t/abc/def", Path: p("QmNyJpQkU1cEkBwMDhDNFstr42q55mqG5GE5Mgwug4xyGk"), Size: "13"},
438
+ {Name: "t/bar", Path: p("QmS21GuXiRMvJKHos4ZkEmQDmRBqRaF5tQS2CQCu2ne9sY"), Size: "14"},
439
+ {Name: "t/foo", Path: p("QmfAjGiVpTN56TXi6SBQtstit5BEw3sijKj1Qkxn6EXKzJ"), Size: "14"},
440
+ {Name: "t/abc", Path: p("QmU7nuGs2djqK99UNsNgEPGh6GV4662p6WtsgccBNGTDxt"), Size: "62"},
441
+ {Name: "t", Path: p("QmVG2ZYCkV1S4TK8URA3a4RupBF17A8yAr4FqsRDXVJASr"), Size: "229"},
442
+ },
443
+ wrap: "t",
444
+ },
445
+ {
446
+ name: "progress1M",
447
+ data: func() files.Node {
448
+ return files.NewReaderFile(bytes.NewReader(bytes.Repeat([]byte{0}, 1000000)))
449
+ },
450
+ path: "/ipfs/QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD",
451
+ events: []coreiface.AddEvent{
452
+ {Name: "", Bytes: 262144},
453
+ {Name: "", Bytes: 524288},
454
+ {Name: "", Bytes: 786432},
455
+ {Name: "", Bytes: 1000000},
456
+ {Name: "QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD", Path: p("QmXXNNbwe4zzpdMg62ZXvnX1oU7MwSrQ3vAEtuwFKCm1oD"), Size: "1000256"},
457
+ },
458
+ wrap: "",
459
+ opts: []options.UnixfsAddOption{options.Unixfs.Progress(true)},
460
+ },
461
+ }
462
+
463
+ for _, testCase := range cases {
464
+ t.Run(testCase.name, func(t *testing.T) {
465
+ ctx, cancel := context.WithCancel(ctx)
466
+ defer cancel()
467
+
468
+ // recursive logic
469
+
470
+ data := testCase.data()
471
+ if testCase.wrap != "" {
472
+ data = files.NewMapDirectory(map[string]files.Node{
473
+ testCase.wrap: data,
474
+ })
475
+ }
476
+
477
+ // handle events if relevant to test case
478
+
479
+ opts := testCase.opts
480
+ eventOut := make(chan interface{})
481
+ var evtWg sync.WaitGroup
482
+ if len(testCase.events) > 0 {
483
+ opts = append(opts, options.Unixfs.Events(eventOut))
484
+ evtWg.Add(1)
485
+
486
+ go func() {
487
+ defer evtWg.Done()
488
+ expected := testCase.events
489
+
490
+ for evt := range eventOut {
491
+ event, ok := evt.(*coreiface.AddEvent)
492
+ if !ok {
493
+ t.Fatal("unexpected event type")
494
+ }
495
+
496
+ if len(expected) < 1 {
497
+ t.Fatal("got more events than expected")
498
+ }
499
+
500
+ if expected[0].Size != event.Size {
501
+ t.Errorf("Event.Size didn't match, %s != %s", expected[0].Size, event.Size)
502
+ }
503
+
504
+ if expected[0].Name != event.Name {
505
+ t.Errorf("Event.Name didn't match, %s != %s", expected[0].Name, event.Name)
506
+ }
507
+
508
+ if expected[0].Path != nil && event.Path != nil {
509
+ if expected[0].Path.Cid().String() != event.Path.Cid().String() {
510
+ t.Errorf("Event.Hash didn't match, %s != %s", expected[0].Path, event.Path)
511
+ }
512
+ } else if event.Path != expected[0].Path {
513
+ t.Errorf("Event.Hash didn't match, %s != %s", expected[0].Path, event.Path)
514
+ }
515
+ if expected[0].Bytes != event.Bytes {
516
+ t.Errorf("Event.Bytes didn't match, %d != %d", expected[0].Bytes, event.Bytes)
517
+ }
518
+
519
+ expected = expected[1:]
520
+ }
521
+
522
+ if len(expected) > 0 {
523
+ t.Fatalf("%d event(s) didn't arrive", len(expected))
524
+ }
525
+ }()
526
+ }
527
+
528
+ tapi, err := api.WithOptions(testCase.apiOpts...)
529
+ if err != nil {
530
+ t.Fatal(err)
531
+ }
532
+
533
+ // Add!
534
+
535
+ p, err := tapi.Unixfs().Add(ctx, data, opts...)
536
+ close(eventOut)
537
+ evtWg.Wait()
538
+ if testCase.err != "" {
539
+ if err == nil {
540
+ t.Fatalf("expected an error: %s", testCase.err)
541
+ }
542
+ if err.Error() != testCase.err {
543
+ t.Fatalf("expected an error: '%s' != '%s'", err.Error(), testCase.err)
544
+ }
545
+ return
546
+ }
547
+ if err != nil {
548
+ t.Fatal(err)
549
+ }
550
+
551
+ if p.String() != testCase.path {
552
+ t.Errorf("expected path %s, got: %s", testCase.path, p)
553
+ }
554
+
555
+ // compare file structure with Unixfs().Get
556
+
557
+ var cmpFile func(origName string, orig files.Node, gotName string, got files.Node)
558
+ cmpFile = func(origName string, orig files.Node, gotName string, got files.Node) {
559
+ _, origDir := orig.(files.Directory)
560
+ _, gotDir := got.(files.Directory)
561
+
562
+ if origDir != gotDir {
563
+ t.Fatal("file type mismatch")
564
+ }
565
+
566
+ if origName != gotName {
567
+ t.Errorf("file name mismatch, orig='%s', got='%s'", origName, gotName)
568
+ }
569
+
570
+ if !gotDir {
571
+ defer orig.Close()
572
+ defer got.Close()
573
+
574
+ do, err := ioutil.ReadAll(orig.(files.File))
575
+ if err != nil {
576
+ t.Fatal(err)
577
+ }
578
+
579
+ dg, err := ioutil.ReadAll(got.(files.File))
580
+ if err != nil {
581
+ t.Fatal(err)
582
+ }
583
+
584
+ if !bytes.Equal(do, dg) {
585
+ t.Fatal("data not equal")
586
+ }
587
+
588
+ return
589
+ }
590
+
591
+ origIt := orig.(files.Directory).Entries()
592
+ gotIt := got.(files.Directory).Entries()
593
+
594
+ for {
595
+ if origIt.Next() {
596
+ if !gotIt.Next() {
597
+ t.Fatal("gotIt out of entries before origIt")
598
+ }
599
+ } else {
600
+ if gotIt.Next() {
601
+ t.Fatal("origIt out of entries before gotIt")
602
+ }
603
+ break
604
+ }
605
+
606
+ cmpFile(origIt.Name(), origIt.Node(), gotIt.Name(), gotIt.Node())
607
+ }
608
+ if origIt.Err() != nil {
609
+ t.Fatal(origIt.Err())
610
+ }
611
+ if gotIt.Err() != nil {
612
+ t.Fatal(gotIt.Err())
613
+ }
614
+ }
615
+
616
+ f, err := tapi.Unixfs().Get(ctx, p)
617
+ if err != nil {
618
+ t.Fatal(err)
619
+ }
620
+
621
+ orig := testCase.data()
622
+ if testCase.expect != nil {
623
+ orig = testCase.expect(orig)
624
+ }
625
+
626
+ cmpFile("", orig, "", f)
627
+ })
628
+ }
629
+}
630
+
631
+func TestAddPinned(t *testing.T) {
632
+ ctx := context.Background()
633
+ api, err := makeAPI(ctx)
634
+ if err != nil {
635
+ t.Error(err)
636
+ }
637
+
638
+ _, err = api.Unixfs().Add(ctx, strFile(helloStr)(), options.Unixfs.Pin(true))
639
+ if err != nil {
640
+ t.Error(err)
641
+ }
642
+
643
+ pins, err := api.Pin().Ls(ctx)
644
+ if len(pins) != 1 {
645
+ t.Fatalf("expected 1 pin, got %d", len(pins))
646
+ }
647
+
648
+ if pins[0].Path().String() != "/ipld/QmQy2Dw4Wk7rdJKjThjYXzfFJNaRKRHhHP5gHHXroJMYxk" {
649
+ t.Fatalf("got unexpected pin: %s", pins[0].Path().String())
650
+ }
651
+}
652
+
653
+func TestAddHashOnly(t *testing.T) {
654
+ ctx := context.Background()
655
+ api, err := makeAPI(ctx)
656
+ if err != nil {
657
+ t.Error(err)
658
+ }
659
+
660
+ p, err := api.Unixfs().Add(ctx, strFile(helloStr)(), options.Unixfs.HashOnly(true))
661
+ if err != nil {
662
+ t.Error(err)
663
+ }
664
+
665
+ if p.String() != hello {
666
+ t.Errorf("unxepected path: %s", p.String())
667
+ }
668
+
669
+ _, err = api.Block().Get(ctx, p)
670
+ if err == nil {
671
+ t.Fatal("expected an error")
672
+ }
673
+ if err.Error() != "blockservice: key not found" {
674
+ t.Errorf("unxepected error: %s", err.Error())
675
+ }
676
+}
677
+
678
+func TestGetEmptyFile(t *testing.T) {
679
+ ctx := context.Background()
680
+ api, err := makeAPI(ctx)
681
+ if err != nil {
682
+ t.Fatal(err)
683
+ }
684
+
685
+ _, err = api.Unixfs().Add(ctx, files.NewBytesFile([]byte{}))
686
+ if err != nil {
687
+ t.Fatal(err)
688
+ }
689
+
690
+ emptyFilePath, err := coreiface.ParsePath(emptyFile)
691
+ if err != nil {
692
+ t.Fatal(err)
693
+ }
694
+
695
+ r, err := api.Unixfs().Get(ctx, emptyFilePath)
696
+ if err != nil {
697
+ t.Fatal(err)
698
+ }
699
+
700
+ buf := make([]byte, 1) // non-zero so that Read() actually tries to read
701
+ n, err := io.ReadFull(r.(files.File), buf)
702
+ if err != nil && err != io.EOF {
703
+ t.Error(err)
704
+ }
705
+ if !bytes.HasPrefix(buf, []byte{0x00}) {
706
+ t.Fatalf("expected empty data, got [%s] [read=%d]", buf, n)
707
+ }
708
+}
709
+
710
+func TestGetDir(t *testing.T) {
711
+ ctx := context.Background()
712
+ api, err := makeAPI(ctx)
713
+ if err != nil {
714
+ t.Error(err)
715
+ }
716
+ edir := unixfs.EmptyDirNode()
717
+ _, err = api.Dag().Put(ctx, bytes.NewReader(edir.RawData()), options.Dag.Codec(cid.DagProtobuf), options.Dag.InputEnc("raw"))
718
+ if err != nil {
719
+ t.Error(err)
720
+ }
721
+ p := coreiface.IpfsPath(edir.Cid())
722
+
723
+ emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
724
+ if err != nil {
725
+ t.Error(err)
726
+ }
727
+
728
+ if p.String() != coreiface.IpfsPath(emptyDir.Cid()).String() {
729
+ t.Fatalf("expected path %s, got: %s", emptyDir.Cid(), p.String())
730
+ }
731
+
732
+ r, err := api.Unixfs().Get(ctx, coreiface.IpfsPath(emptyDir.Cid()))
733
+ if err != nil {
734
+ t.Error(err)
735
+ }
736
+
737
+ if _, ok := r.(files.Directory); !ok {
738
+ t.Fatalf("expected a directory")
739
+ }
740
+}
741
+
742
+func TestGetNonUnixfs(t *testing.T) {
743
+ ctx := context.Background()
744
+ api, err := makeAPI(ctx)
745
+ if err != nil {
746
+ t.Error(err)
747
+ }
748
+
749
+ nd := new(mdag.ProtoNode)
750
+ _, err = api.Dag().Put(ctx, bytes.NewReader(nd.RawData()), options.Dag.Codec(nd.CidBuilder().GetCodec()), options.Dag.InputEnc("raw"))
751
+ if err != nil {
752
+ t.Error(err)
753
+ }
754
+
755
+ _, err = api.Unixfs().Get(ctx, coreiface.IpfsPath(nd.Cid()))
756
+ if !strings.Contains(err.Error(), "proto: required field") {
757
+ t.Fatalf("expected protobuf error, got: %s", err)
758
+ }
759
+}
760
+
761
+func TestLs(t *testing.T) {
762
+ ctx := context.Background()
763
+ api, err := makeAPI(ctx)
764
+ if err != nil {
765
+ t.Error(err)
766
+ }
767
+
768
+ r := strings.NewReader("content-of-file")
769
+ p, err := api.Unixfs().Add(ctx, files.NewMapDirectory(map[string]files.Node{
770
+ "0": files.NewMapDirectory(map[string]files.Node{
771
+ "name-of-file": files.NewReaderFile(r),
772
+ }),
773
+ }))
774
+ if err != nil {
775
+ t.Error(err)
776
+ }
777
+
778
+ links, err := api.Unixfs().Ls(ctx, p)
779
+ if err != nil {
780
+ t.Error(err)
781
+ }
782
+
783
+ if len(links) != 1 {
784
+ t.Fatalf("expected 1 link, got %d", len(links))
785
+ }
786
+ if links[0].Size != 23 {
787
+ t.Fatalf("expected size = 23, got %d", links[0].Size)
788
+ }
789
+ if links[0].Name != "name-of-file" {
790
+ t.Fatalf("expected name = name-of-file, got %s", links[0].Name)
791
+ }
792
+ if links[0].Cid.String() != "QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr" {
793
+ t.Fatalf("expected cid = QmX3qQVKxDGz3URVC3861Z3CKtQKGBn6ffXRBBWGMFz9Lr, got %s", links[0].Cid)
794
+ }
795
+}
796
+
797
+func TestEntriesExpired(t *testing.T) {
798
+ ctx := context.Background()
799
+ api, err := makeAPI(ctx)
800
+ if err != nil {
801
+ t.Error(err)
802
+ }
803
+
804
+ r := strings.NewReader("content-of-file")
805
+ p, err := api.Unixfs().Add(ctx, files.NewMapDirectory(map[string]files.Node{
806
+ "0": files.NewMapDirectory(map[string]files.Node{
807
+ "name-of-file": files.NewReaderFile(r),
808
+ }),
809
+ }))
810
+ if err != nil {
811
+ t.Error(err)
812
+ }
813
+
814
+ ctx, cancel := context.WithCancel(ctx)
815
+
816
+ nd, err := api.Unixfs().Get(ctx, p)
817
+ if err != nil {
818
+ t.Error(err)
819
+ }
820
+ cancel()
821
+
822
+ it := files.ToDir(nd).Entries()
823
+ if it == nil {
824
+ t.Fatal("it was nil")
825
+ }
826
+
827
+ if it.Next() {
828
+ t.Fatal("Next succeeded")
829
+ }
830
+
831
+ if it.Err() != context.Canceled {
832
+ t.Fatalf("unexpected error %s", it.Err())
833
+ }
834
+
835
+ if it.Next() {
836
+ t.Fatal("Next succeeded")
837
+ }
838
+}
839
+
840
+func TestLsEmptyDir(t *testing.T) {
841
+ ctx := context.Background()
842
+ api, err := makeAPI(ctx)
843
+ if err != nil {
844
+ t.Error(err)
845
+ }
846
+
847
+ _, err = api.Unixfs().Add(ctx, files.NewMapDirectory(map[string]files.Node{"0": files.NewSliceDirectory([]files.DirEntry{})}))
848
+ if err != nil {
849
+ t.Error(err)
850
+ }
851
+
852
+ emptyDir, err := api.Object().New(ctx, options.Object.Type("unixfs-dir"))
853
+ if err != nil {
854
+ t.Error(err)
855
+ }
856
+
857
+ links, err := api.Unixfs().Ls(ctx, coreiface.IpfsPath(emptyDir.Cid()))
858
+ if err != nil {
859
+ t.Error(err)
860
+ }
861
+
862
+ if len(links) != 0 {
863
+ t.Fatalf("expected 0 links, got %d", len(links))
864
+ }
865
+}
866
+
867
+// TODO(lgierth) this should test properly, with len(links) > 0
868
+func TestLsNonUnixfs(t *testing.T) {
869
+ ctx := context.Background()
870
+ api, err := makeAPI(ctx)
871
+ if err != nil {
872
+ t.Error(err)
873
+ }
874
+
875
+ nd, err := cbor.WrapObject(map[string]interface{}{"foo": "bar"}, math.MaxUint64, -1)
876
+ if err != nil {
877
+ t.Fatal(err)
878
+ }
879
+
880
+ _, err = api.Dag().Put(ctx, bytes.NewReader(nd.RawData()), options.Dag.Codec(cid.DagCBOR), options.Dag.InputEnc("raw"))
881
+ if err != nil {
882
+ t.Error(err)
883
+ }
884
+
885
+ links, err := api.Unixfs().Ls(ctx, coreiface.IpfsPath(nd.Cid()))
886
+ if err != nil {
887
+ t.Error(err)
888
+ }
889
+
890
+ if len(links) != 0 {
891
+ t.Fatalf("expected 0 links, got %d", len(links))
892
+ }
893
+}
894
+
895
+type closeTestF struct {
896
+ files.File
897
+ closed bool
898
+
899
+ t *testing.T
900
+}
901
+
902
+type closeTestD struct {
903
+ files.Directory
904
+ closed bool
905
+
906
+ t *testing.T
907
+}
908
+
909
+func (f *closeTestD) Close() error {
910
+ if f.closed {
911
+ f.t.Fatal("already closed")
912
+ }
913
+ f.closed = true
914
+ return nil
915
+}
916
+
917
+func (f *closeTestF) Close() error {
918
+ if f.closed {
919
+ f.t.Fatal("already closed")
920
+ }
921
+ f.closed = true
922
+ return nil
923
+}
924
+
925
+func TestAddCloses(t *testing.T) {
926
+ ctx := context.Background()
927
+ api, err := makeAPI(ctx)
928
+ if err != nil {
929
+ t.Error(err)
930
+ }
931
+
932
+ n4 := &closeTestF{files.NewBytesFile([]byte("foo")), false, t}
933
+ d3 := &closeTestD{files.NewMapDirectory(map[string]files.Node{
934
+ "sub": n4,
935
+ }), false, t}
936
+ n2 := &closeTestF{files.NewBytesFile([]byte("bar")), false, t}
937
+ n1 := &closeTestF{files.NewBytesFile([]byte("baz")), false, t}
938
+ d0 := &closeTestD{files.NewMapDirectory(map[string]files.Node{
939
+ "a": d3,
940
+ "b": n1,
941
+ "c": n2,
942
+ }), false, t}
943
+
944
+ _, err = api.Unixfs().Add(ctx, d0)
945
+ if err != nil {
946
+ t.Error(err)
947
+ }
948
+
949
+ d0.Close() // Adder doesn't close top-level file
950
+
951
+ for i, n := range []*closeTestF{n1, n2, n4} {
952
+ if !n.closed {
953
+ t.Errorf("file %d not closed!", i)
954
+ }
955
+ }
956
+
957
+ for i, n := range []*closeTestD{d0, d3} {
958
+ if !n.closed {
959
+ t.Errorf("dir %d not closed!", i)
960
+ }
961
+ }
962
+
963
+}