1
package decision
2
3
import (
4
+ "math"
5
"strings"
6
+ "sync"
7
"testing"
8
9
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
10
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
9
- sync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
10
-
11
+ dssync "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore/sync"
12
blocks "github.com/jbenet/go-ipfs/blocks"
13
blockstore "github.com/jbenet/go-ipfs/blocks/blockstore"
14
message "github.com/jbenet/go-ipfs/exchange/bitswap/message"
15
peer "github.com/jbenet/go-ipfs/p2p/peer"
16
+ testutil "github.com/jbenet/go-ipfs/util/testutil"
17
)
18
19
type peerAndEngine struct {
21
Engine *Engine
22
}
23
22
-func newPeerAndLedgermanager(idStr string) peerAndEngine {
24
+func newEngine(ctx context.Context, idStr string) peerAndEngine {
25
return peerAndEngine{
26
Peer: peer.ID(idStr),
27
//Strategy: New(true),
26
- Engine: NewEngine(context.TODO(),
27
- blockstore.NewBlockstore(sync.MutexWrap(ds.NewMapDatastore()))),
28
+ Engine: NewEngine(ctx,
29
+ blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore()))),
30
}
31
}
32
33
func TestConsistentAccounting(t *testing.T) {
32
- sender := newPeerAndLedgermanager("Ernie")
33
- receiver := newPeerAndLedgermanager("Bert")
34
+ ctx, cancel := context.WithCancel(context.Background())
35
+ defer cancel()
36
+ sender := newEngine(ctx, "Ernie")
37
+ receiver := newEngine(ctx, "Bert")
38
39
// Send messages from Ernie to Bert
40
for i := 0; i < 1000; i++ {
66
67
func TestPeerIsAddedToPeersWhenMessageReceivedOrSent(t *testing.T) {
68
65
- sanfrancisco := newPeerAndLedgermanager("sf")
66
- seattle := newPeerAndLedgermanager("sea")
69
+ ctx, cancel := context.WithCancel(context.Background())
70
+ defer cancel()
71
+ sanfrancisco := newEngine(ctx, "sf")
72
+ seattle := newEngine(ctx, "sea")
73
74
m := message.New()
75
97
}
98
return false
99
}
100
+
101
+func TestOutboxClosedWhenEngineClosed(t *testing.T) {
102
+ t.SkipNow() // TODO implement *Engine.Close
103
+ e := NewEngine(context.Background(), blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())))
104
+ var wg sync.WaitGroup
105
+ wg.Add(1)
106
+ go func() {
107
+ for _ = range e.Outbox() {
108
+ }
109
+ wg.Done()
110
+ }()
111
+ // e.Close()
112
+ wg.Wait()
113
+ if _, ok := <-e.Outbox(); ok {
114
+ t.Fatal("channel should be closed")
115
+ }
116
+}
117
+
118
+func TestPartnerWantsThenCancels(t *testing.T) {
119
+ alphabet := strings.Split("abcdefghijklmnopqrstuvwxyz", "")
120
+ vowels := strings.Split("aeiou", "")
121
+
122
+ type testCase [][]string
123
+ testcases := []testCase{
124
+ testCase{
125
+ alphabet, vowels,
126
+ },
127
+ testCase{
128
+ alphabet, stringsComplement(alphabet, vowels),
129
+ },
130
+ }
131
+
132
+ for _, testcase := range testcases {
133
+ set := testcase[0]
134
+ cancels := testcase[1]
135
+ keeps := stringsComplement(set, cancels)
136
+
137
+ bs := blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore()))
138
+ e := NewEngine(context.Background(), bs)
139
+ partner := testutil.RandPeerIDFatal(t)
140
+ for _, letter := range set {
141
+ block := blocks.NewBlock([]byte(letter))
142
+ bs.Put(block)
143
+ }
144
+ partnerWants(e, set, partner)
145
+ partnerCancels(e, cancels, partner)
146
+ assertPoppedInOrder(t, e, keeps)
147
+ }
148
+
149
+}
150
+
151
+func partnerWants(e *Engine, keys []string, partner peer.ID) {
152
+ add := message.New()
153
+ for i, letter := range keys {
154
+ block := blocks.NewBlock([]byte(letter))
155
+ add.AddEntry(block.Key(), math.MaxInt32-i)
156
+ }
157
+ e.MessageReceived(partner, add)
158
+}
159
+
160
+func partnerCancels(e *Engine, keys []string, partner peer.ID) {
161
+ cancels := message.New()
162
+ for _, k := range keys {
163
+ block := blocks.NewBlock([]byte(k))
164
+ cancels.Cancel(block.Key())
165
+ }
166
+ e.MessageReceived(partner, cancels)
167
+}
168
+
169
+func assertPoppedInOrder(t *testing.T, e *Engine, keys []string) {
170
+ for _, k := range keys {
171
+ envelope := <-e.Outbox()
172
+ received := envelope.Message.Blocks()[0]
173
+ expected := blocks.NewBlock([]byte(k))
174
+ if received.Key() != expected.Key() {
175
+ t.Fatal("received", string(received.Data), "expected", string(expected.Data))
176
+ }
177
+ }
178
+}
179
+
180
+func stringsComplement(set, subset []string) []string {
181
+ m := make(map[string]struct{})
182
+ for _, letter := range subset {
183
+ m[letter] = struct{}{}
184
+ }
185
+ var complement []string
186
+ for _, letter := range set {
187
+ if _, exists := m[letter]; !exists {
188
+ complement = append(complement, letter)
189
+ }
190
+ }
191
+ return complement
192
+}