@cryptotaxi247 / kubo / commits / 34b11a3b0

fix: routing mock accuracy

routing interface doesn't wait for value to appear in network, but value doesn't appear in network until time as passed License: MIT Signed-off-by: Brian Tiger Chow <brian@perfmode.com>

Brian Tiger Chow committed Dec 15, 2014 at 20:30 UTC 34b11a3b070d931963e4c307ff97ef74ba1e3343
6 files changed +84 -17
epictest/addcat_test.go
+4 -1
@@ -104,7 +104,10 @@ func AddCatBytes(data []byte, conf Config) error {
104
105 sessionGenerator := bitswap.NewSessionGenerator(
106 tn.VirtualNetwork(delay.Fixed(conf.NetworkLatency)), // TODO rename VirtualNetwork
107 - mockrouting.NewServerWithDelay(delay.Fixed(conf.RoutingLatency)),
107 + mockrouting.NewServerWithDelay(mockrouting.DelayConfig{
108 + Query: delay.Fixed(conf.RoutingLatency),
109 + ValueVisibility: delay.Fixed(conf.RoutingLatency),
110 + }),
111 )
112 defer sessionGenerator.Close()
113
routing/mock/client.go
+2
@@ -67,6 +67,8 @@ func (c *client) FindProvidersAsync(ctx context.Context, k u.Key, max int) <-cha
67 return out
68 }
69
70 +// Provide returns once the message is on the network. Value is not necessarily
71 +// visible yet.
72 func (c *client) Provide(_ context.Context, key u.Key) error {
73 return c.server.Announce(c.peer, key)
74 }
routing/mock/interface.go
+16 -4
@@ -28,13 +28,25 @@ type Client interface {
28
29 // NewServer returns a mockrouting Server
30 func NewServer() Server {
31 - return NewServerWithDelay(delay.Fixed(0))
31 + return NewServerWithDelay(DelayConfig{
32 + ValueVisibility: delay.Fixed(0),
33 + Query: delay.Fixed(0),
34 + })
35 }
36
37 // NewServerWithDelay returns a mockrouting Server with a delay!
35 -func NewServerWithDelay(d delay.D) Server {
38 +func NewServerWithDelay(conf DelayConfig) Server {
39 return &s{
37 - providers: make(map[u.Key]peer.Map),
38 - delay: d,
40 + providers: make(map[u.Key]map[u.Key]providerRecord),
41 + delayConf: conf,
42 }
43 }
44 +
45 +type DelayConfig struct {
46 + // ValueVisibility is the time it takes for a value to be visible in the network
47 + // FIXME there _must_ be a better term for this
48 + ValueVisibility delay.D
49 +
50 + // Query is the time it takes to receive a response from a routing query
51 + Query delay.D
52 +}
routing/mock/mockrouting_test.go
+36 -1
@@ -3,10 +3,12 @@ package mockrouting
3 import (
4 "bytes"
5 "testing"
6 + "time"
7
8 context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
8 - "github.com/jbenet/go-ipfs/peer"
9 + peer "github.com/jbenet/go-ipfs/peer"
10 u "github.com/jbenet/go-ipfs/util"
11 + delay "github.com/jbenet/go-ipfs/util/delay"
12 testutil "github.com/jbenet/go-ipfs/util/testutil"
13 )
14
@@ -129,3 +131,36 @@ func TestCanceledContext(t *testing.T) {
131 t.Fatal("Context cancel had no effect")
132 }
133 }
134 +
135 +func TestValidAfter(t *testing.T) {
136 +
137 + var p = testutil.NewPeerWithID(peer.ID([]byte("the peer id")))
138 + var key = u.Key("mock key")
139 + var ctx = context.Background()
140 + conf := DelayConfig{
141 + ValueVisibility: delay.Fixed(1 * time.Hour),
142 + Query: delay.Fixed(0),
143 + }
144 +
145 + rs := NewServerWithDelay(conf)
146 +
147 + rs.Client(p).Provide(ctx, key)
148 +
149 + var providers []peer.Peer
150 + providers, err := rs.Client(p).FindProviders(ctx, key)
151 + if err != nil {
152 + t.Fatal(err)
153 + }
154 + if len(providers) > 0 {
155 + t.Fail()
156 + }
157 +
158 + conf.ValueVisibility.Set(0)
159 + providers, err = rs.Client(p).FindProviders(ctx, key)
160 + if err != nil {
161 + t.Fatal(err)
162 + }
163 + if len(providers) != 1 {
164 + t.Fail()
165 + }
166 +}
routing/mock/server.go
+19 -11
@@ -3,11 +3,11 @@ package mockrouting
3 import (
4 "math/rand"
5 "sync"
6 + "time"
7
8 ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
9 peer "github.com/jbenet/go-ipfs/peer"
10 u "github.com/jbenet/go-ipfs/util"
10 - delay "github.com/jbenet/go-ipfs/util/delay"
11 )
12
13 // server is the mockrouting.Client's private interface to the routing server
@@ -20,39 +20,47 @@ type server interface {
20
21 // s is an implementation of the private server interface
22 type s struct {
23 - delay delay.D
23 + delayConf DelayConfig
24
25 lock sync.RWMutex
26 - providers map[u.Key]peer.Map
26 + providers map[u.Key]map[u.Key]providerRecord
27 }
28
29 -func (rs *s) Announce(p peer.Peer, k u.Key) error {
30 - rs.delay.Wait() // before locking
29 +type providerRecord struct {
30 + Peer peer.Peer
31 + Created time.Time
32 +}
33
34 +func (rs *s) Announce(p peer.Peer, k u.Key) error {
35 rs.lock.Lock()
36 defer rs.lock.Unlock()
37
38 _, ok := rs.providers[k]
39 if !ok {
37 - rs.providers[k] = make(peer.Map)
40 + rs.providers[k] = make(map[u.Key]providerRecord)
41 + }
42 + rs.providers[k][p.Key()] = providerRecord{
43 + Created: time.Now(),
44 + Peer: p,
45 }
39 - rs.providers[k][p.Key()] = p
46 return nil
47 }
48
49 func (rs *s) Providers(k u.Key) []peer.Peer {
44 - rs.delay.Wait() // before locking
50 + rs.delayConf.Query.Wait() // before locking
51
52 rs.lock.RLock()
53 defer rs.lock.RUnlock()
54
55 var ret []peer.Peer
50 - peerset, ok := rs.providers[k]
56 + records, ok := rs.providers[k]
57 if !ok {
58 return ret
59 }
54 - for _, peer := range peerset {
55 - ret = append(ret, peer)
60 + for _, r := range records {
61 + if time.Now().Sub(r.Created) > rs.delayConf.ValueVisibility.Get() {
62 + ret = append(ret, r.Peer)
63 + }
64 }
65
66 for i := range ret {
util/delay/delay.go
+7
@@ -10,6 +10,7 @@ import (
10 type D interface {
11 Set(time.Duration) time.Duration
12 Wait()
13 + Get() time.Duration
14 }
15
16 // Fixed returns a delay with fixed latency
@@ -37,3 +38,9 @@ func (d *delay) Wait() {
38 defer d.l.RUnlock()
39 time.Sleep(d.t)
40 }
41 +
42 +func (d *delay) Get() time.Duration {
43 + d.l.Lock()
44 + defer d.l.Unlock()
45 + return d.t
46 +}