Commit 88a9bf04 authored by Brian Tiger Chow's avatar Brian Tiger Chow

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: default avatarBrian Tiger Chow <brian@perfmode.com>
parent 07e7f9a2
...@@ -67,6 +67,8 @@ func (c *client) FindProvidersAsync(ctx context.Context, k u.Key, max int) <-cha ...@@ -67,6 +67,8 @@ func (c *client) FindProvidersAsync(ctx context.Context, k u.Key, max int) <-cha
return out return out
} }
// Provide returns once the message is on the network. Value is not necessarily
// visible yet.
func (c *client) Provide(_ context.Context, key u.Key) error { func (c *client) Provide(_ context.Context, key u.Key) error {
return c.server.Announce(c.peer, key) return c.server.Announce(c.peer, key)
} }
......
...@@ -28,13 +28,25 @@ type Client interface { ...@@ -28,13 +28,25 @@ type Client interface {
// NewServer returns a mockrouting Server // NewServer returns a mockrouting Server
func NewServer() Server { func NewServer() Server {
return NewServerWithDelay(delay.Fixed(0)) return NewServerWithDelay(DelayConfig{
ValueVisibility: delay.Fixed(0),
Query: delay.Fixed(0),
})
} }
// NewServerWithDelay returns a mockrouting Server with a delay! // NewServerWithDelay returns a mockrouting Server with a delay!
func NewServerWithDelay(d delay.D) Server { func NewServerWithDelay(conf DelayConfig) Server {
return &s{ return &s{
providers: make(map[u.Key]peer.Map), providers: make(map[u.Key]map[u.Key]providerRecord),
delay: d, delayConf: conf,
} }
} }
type DelayConfig struct {
// ValueVisibility is the time it takes for a value to be visible in the network
// FIXME there _must_ be a better term for this
ValueVisibility delay.D
// Query is the time it takes to receive a response from a routing query
Query delay.D
}
...@@ -3,10 +3,12 @@ package mockrouting ...@@ -3,10 +3,12 @@ package mockrouting
import ( import (
"bytes" "bytes"
"testing" "testing"
"time"
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
"github.com/jbenet/go-ipfs/peer" peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
delay "github.com/jbenet/go-ipfs/util/delay"
testutil "github.com/jbenet/go-ipfs/util/testutil" testutil "github.com/jbenet/go-ipfs/util/testutil"
) )
...@@ -129,3 +131,36 @@ func TestCanceledContext(t *testing.T) { ...@@ -129,3 +131,36 @@ func TestCanceledContext(t *testing.T) {
t.Fatal("Context cancel had no effect") t.Fatal("Context cancel had no effect")
} }
} }
func TestValidAfter(t *testing.T) {
var p = testutil.NewPeerWithID(peer.ID([]byte("the peer id")))
var key = u.Key("mock key")
var ctx = context.Background()
conf := DelayConfig{
ValueVisibility: delay.Fixed(1 * time.Hour),
Query: delay.Fixed(0),
}
rs := NewServerWithDelay(conf)
rs.Client(p).Provide(ctx, key)
var providers []peer.Peer
providers, err := rs.Client(p).FindProviders(ctx, key)
if err != nil {
t.Fatal(err)
}
if len(providers) > 0 {
t.Fail()
}
conf.ValueVisibility.Set(0)
providers, err = rs.Client(p).FindProviders(ctx, key)
if err != nil {
t.Fatal(err)
}
if len(providers) != 1 {
t.Fail()
}
}
...@@ -3,11 +3,11 @@ package mockrouting ...@@ -3,11 +3,11 @@ package mockrouting
import ( import (
"math/rand" "math/rand"
"sync" "sync"
"time"
ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore" ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
peer "github.com/jbenet/go-ipfs/peer" peer "github.com/jbenet/go-ipfs/peer"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
delay "github.com/jbenet/go-ipfs/util/delay"
) )
// server is the mockrouting.Client's private interface to the routing server // server is the mockrouting.Client's private interface to the routing server
...@@ -20,39 +20,47 @@ type server interface { ...@@ -20,39 +20,47 @@ type server interface {
// s is an implementation of the private server interface // s is an implementation of the private server interface
type s struct { type s struct {
delay delay.D delayConf DelayConfig
lock sync.RWMutex lock sync.RWMutex
providers map[u.Key]peer.Map providers map[u.Key]map[u.Key]providerRecord
} }
func (rs *s) Announce(p peer.Peer, k u.Key) error { type providerRecord struct {
rs.delay.Wait() // before locking Peer peer.Peer
Created time.Time
}
func (rs *s) Announce(p peer.Peer, k u.Key) error {
rs.lock.Lock() rs.lock.Lock()
defer rs.lock.Unlock() defer rs.lock.Unlock()
_, ok := rs.providers[k] _, ok := rs.providers[k]
if !ok { if !ok {
rs.providers[k] = make(peer.Map) rs.providers[k] = make(map[u.Key]providerRecord)
}
rs.providers[k][p.Key()] = providerRecord{
Created: time.Now(),
Peer: p,
} }
rs.providers[k][p.Key()] = p
return nil return nil
} }
func (rs *s) Providers(k u.Key) []peer.Peer { func (rs *s) Providers(k u.Key) []peer.Peer {
rs.delay.Wait() // before locking rs.delayConf.Query.Wait() // before locking
rs.lock.RLock() rs.lock.RLock()
defer rs.lock.RUnlock() defer rs.lock.RUnlock()
var ret []peer.Peer var ret []peer.Peer
peerset, ok := rs.providers[k] records, ok := rs.providers[k]
if !ok { if !ok {
return ret return ret
} }
for _, peer := range peerset { for _, r := range records {
ret = append(ret, peer) if time.Now().Sub(r.Created) > rs.delayConf.ValueVisibility.Get() {
ret = append(ret, r.Peer)
}
} }
for i := range ret { for i := range ret {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment