func TestClientFindProviders(t *testing.T) { pi := testutil.RandIdentityOrFatal(t) rs := NewServer() client := rs.Client(pi) k := key.Key("hello") err := client.Provide(context.Background(), k) if err != nil { t.Fatal(err) } // This is bad... but simulating networks is hard time.Sleep(time.Millisecond * 300) max := 100 providersFromClient := client.FindProvidersAsync(context.Background(), key.Key("hello"), max) isInClient := false for pi := range providersFromClient { if pi.ID == pi.ID { isInClient = true } } if !isInClient { t.Fatal("Despite client providing key, client didn't receive peer when finding providers") } }
func TestToNetFromNetPreservesWantList(t *testing.T) { original := New(true) original.AddEntry(key.Key("M"), 1) original.AddEntry(key.Key("B"), 1) original.AddEntry(key.Key("D"), 1) original.AddEntry(key.Key("T"), 1) original.AddEntry(key.Key("F"), 1) buf := new(bytes.Buffer) if err := original.ToNet(buf); err != nil { t.Fatal(err) } copied, err := FromNet(buf) if err != nil { t.Fatal(err) } keys := make(map[key.Key]bool) for _, k := range copied.Wantlist() { keys[k.Key] = true } for _, k := range original.Wantlist() { if _, ok := keys[k.Key]; !ok { t.Fatalf("Key Missing: \"%v\"", k) } } }
func TestPushPop(t *testing.T) { prq := newPRQ() partner := testutil.RandPeerIDFatal(t) alphabet := strings.Split("abcdefghijklmnopqrstuvwxyz", "") vowels := strings.Split("aeiou", "") consonants := func() []string { var out []string for _, letter := range alphabet { skip := false for _, vowel := range vowels { if letter == vowel { skip = true } } if !skip { out = append(out, letter) } } return out }() sort.Strings(alphabet) sort.Strings(vowels) sort.Strings(consonants) // add a bunch of blocks. cancel some. drain the queue. the queue should only have the kept entries for _, index := range rand.Perm(len(alphabet)) { // add blocks for all letters letter := alphabet[index] t.Log(partner.String()) prq.Push(wantlist.Entry{Key: key.Key(letter), Priority: math.MaxInt32 - index}, partner) } for _, consonant := range consonants { prq.Remove(key.Key(consonant), partner) } var out []string for { received := prq.Pop() if received == nil { break } out = append(out, string(received.Entry.Key)) } // Entries popped should already be in correct order for i, expected := range vowels { if out[i] != expected { t.Fatal("received", out[i], "expected", expected) } } }
// This test checks that peers wont starve out other peers func TestPeerRepeats(t *testing.T) { prq := newPRQ() a := testutil.RandPeerIDFatal(t) b := testutil.RandPeerIDFatal(t) c := testutil.RandPeerIDFatal(t) d := testutil.RandPeerIDFatal(t) // Have each push some blocks for i := 0; i < 5; i++ { prq.Push(wantlist.Entry{Key: key.Key(i)}, a) prq.Push(wantlist.Entry{Key: key.Key(i)}, b) prq.Push(wantlist.Entry{Key: key.Key(i)}, c) prq.Push(wantlist.Entry{Key: key.Key(i)}, d) } // now, pop off four entries, there should be one from each var targets []string var tasks []*peerRequestTask for i := 0; i < 4; i++ { t := prq.Pop() targets = append(targets, t.Target.Pretty()) tasks = append(tasks, t) } expected := []string{a.Pretty(), b.Pretty(), c.Pretty(), d.Pretty()} sort.Strings(expected) sort.Strings(targets) t.Log(targets) t.Log(expected) for i, s := range targets { if expected[i] != s { t.Fatal("unexpected peer", s, expected[i]) } } // Now, if one of the tasks gets finished, the next task off the queue should // be for the same peer for blockI := 0; blockI < 4; blockI++ { for i := 0; i < 4; i++ { // its okay to mark the same task done multiple times here (JUST FOR TESTING) tasks[i].Done() ntask := prq.Pop() if ntask.Target != tasks[i].Target { t.Fatal("Expected task from peer with lowest active count") } } } }
// GetNode returns the MDAG Node that this link points to func (l *Link) GetNode(ctx context.Context, serv DAGService) (*Node, error) { if l.Node != nil { return l.Node, nil } return serv.Get(ctx, key.Key(l.Hash)) }
// VerifyRecord checks a record and ensures it is still valid. // It runs needed validators func (v Validator) VerifyRecord(r *pb.Record) error { // Now, check validity func parts := strings.Split(r.GetKey(), "/") if len(parts) < 3 { log.Infof("Record key does not have validator: %s", key.Key(r.GetKey())) return nil } val, ok := v[parts[1]] if !ok { log.Infof("Unrecognized key prefix: %s", parts[1]) return ErrInvalidRecordType } return val.Func(key.Key(r.GetKey()), r.GetValue()) }
// putProvider sends a message to peer 'p' saying that the local node // can provide the value of 'key' func (dht *IpfsDHT) putProvider(ctx context.Context, p peer.ID, skey string) error { // add self as the provider pi := peer.PeerInfo{ ID: dht.self, Addrs: dht.host.Addrs(), } // // only share WAN-friendly addresses ?? // pi.Addrs = addrutil.WANShareableAddrs(pi.Addrs) if len(pi.Addrs) < 1 { // log.Infof("%s putProvider: %s for %s error: no wan-friendly addresses", dht.self, p, key.Key(key), pi.Addrs) return fmt.Errorf("no known addresses for self. cannot put provider.") } pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, skey, 0) pmes.ProviderPeers = pb.RawPeerInfosToPBPeers([]peer.PeerInfo{pi}) err := dht.sendMessage(ctx, p, pmes) if err != nil { return err } log.Debugf("%s putProvider: %s for %s (%s)", dht.self, p, key.Key(skey), pi.Addrs) return nil }
// betterPeerToQuery returns nearestPeersToQuery, but iff closer than self. func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, p peer.ID, count int) []peer.ID { closer := dht.nearestPeersToQuery(pmes, count) // no node? nil if closer == nil { return nil } // == to self? thats bad for _, p := range closer { if p == dht.self { log.Debug("Attempted to return self! this shouldnt happen...") return nil } } var filtered []peer.ID for _, clp := range closer { // Dont send a peer back themselves if p == clp { continue } // must all be closer than self key := key.Key(pmes.GetKey()) if !kb.Closer(dht.self, clp, key) { filtered = append(filtered, clp) } } // ok seems like closer nodes return filtered }
func TestValidAfter(t *testing.T) { pi := testutil.RandIdentityOrFatal(t) var key = key.Key("mock key") var ctx = context.Background() conf := DelayConfig{ ValueVisibility: delay.Fixed(1 * time.Hour), Query: delay.Fixed(0), } rs := NewServerWithDelay(conf) rs.Client(pi).Provide(ctx, key) var providers []peer.PeerInfo providers, err := rs.Client(pi).FindProviders(ctx, key) if err != nil { t.Fatal(err) } if len(providers) > 0 { t.Fail() } conf.ValueVisibility.Set(0) providers, err = rs.Client(pi).FindProviders(ctx, key) if err != nil { t.Fatal(err) } t.Log("providers", providers) if len(providers) != 1 { t.Fail() } }
func TestClientOverMax(t *testing.T) { rs := NewServer() k := key.Key("hello") numProvidersForHelloKey := 100 for i := 0; i < numProvidersForHelloKey; i++ { pi := testutil.RandIdentityOrFatal(t) err := rs.Client(pi).Provide(context.Background(), k) if err != nil { t.Fatal(err) } } max := 10 pi := testutil.RandIdentityOrFatal(t) client := rs.Client(pi) providersFromClient := client.FindProvidersAsync(context.Background(), k, max) i := 0 for _ = range providersFromClient { i++ } if i != max { t.Fatal("Too many providers returned") } }
func (dht *IpfsDHT) handleAddProvider(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) { lm := make(lgbl.DeferredMap) lm["peer"] = func() interface{} { return p.Pretty() } defer log.EventBegin(ctx, "handleAddProvider", lm).Done() key := key.Key(pmes.GetKey()) lm["key"] = func() interface{} { return key.Pretty() } log.Debugf("%s adding %s as a provider for '%s'\n", dht.self, p, key) // add provider should use the address given in the message pinfos := pb.PBPeersToPeerInfos(pmes.GetProviderPeers()) for _, pi := range pinfos { if pi.ID != p { // we should ignore this provider reccord! not from originator. // (we chould sign them and check signature later...) log.Debugf("handleAddProvider received provider %s from %s. Ignore.", pi.ID, p) continue } if len(pi.Addrs) < 1 { log.Debugf("%s got no valid addresses for provider %s. Ignore.", dht.self, p) continue } log.Infof("received provider %s for %s (addrs: %s)", p, key, pi.Addrs) if pi.ID != dht.self { // dont add own addrs. // add the received addresses to our peerstore. dht.peerstore.AddAddrs(pi.ID, pi.Addrs, peer.ProviderAddrTTL) } dht.providers.AddProvider(ctx, key, p) } return nil, nil }
func TestBlockReturnsErr(t *testing.T) { off := Exchange(bstore()) _, err := off.GetBlock(context.Background(), key.Key("foo")) if err != nil { return // as desired } t.Fail() }
// Loggable turns a Message into machine-readable log output func (m *Message) Loggable() map[string]interface{} { return map[string]interface{}{ "message": map[string]string{ "type": m.Type.String(), "key": key.Key(m.GetKey()).Pretty(), }, } }
func init() { testCaseValues["hello"] = []byte("world") for i := 0; i < 100; i++ { k := fmt.Sprintf("%d -- key", i) v := fmt.Sprintf("%d -- value", i) testCaseValues[key.Key(k)] = []byte(v) } }
func TestCopyProtoByValue(t *testing.T) { const str = "foo" m := New(true) protoBeforeAppend := m.ToProto() m.AddEntry(key.Key(str), 1) if wantlistContains(protoBeforeAppend.GetWantlist(), str) { t.Fail() } }
// Store a value in this peer local storage func (dht *IpfsDHT) handlePutValue(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) { defer log.EventBegin(ctx, "handlePutValue", p).Done() dskey := key.Key(pmes.GetKey()).DsKey() if err := dht.verifyRecordLocally(pmes.GetRecord()); err != nil { log.Debugf("Bad dht record in PUT from: %s. %s", key.Key(pmes.GetRecord().GetAuthor()), err) return nil, err } data, err := proto.Marshal(pmes.GetRecord()) if err != nil { return nil, err } err = dht.datastore.Put(dskey, data) log.Debugf("%s handlePutValue %v", dht.self, dskey) return pmes, err }
// TODO does dht ensure won't receive self as a provider? probably not. func TestCanceledContext(t *testing.T) { rs := NewServer() k := key.Key("hello") // avoid leaking goroutine, without using the context to signal // (we want the goroutine to keep trying to publish on a // cancelled context until we've tested it doesnt do anything.) done := make(chan struct{}) defer func() { done <- struct{}{} }() t.Log("async'ly announce infinite stream of providers for key") i := 0 go func() { // infinite stream for { select { case <-done: t.Log("exiting async worker") return default: } pi, err := testutil.RandIdentity() if err != nil { t.Error(err) } err = rs.Client(pi).Provide(context.Background(), k) if err != nil { t.Error(err) } i++ } }() local := testutil.RandIdentityOrFatal(t) client := rs.Client(local) t.Log("warning: max is finite so this test is non-deterministic") t.Log("context cancellation could simply take lower priority") t.Log("and result in receiving the max number of results") max := 1000 t.Log("cancel the context before consuming") ctx, cancelFunc := context.WithCancel(context.Background()) cancelFunc() providers := client.FindProvidersAsync(ctx, k, max) numProvidersReturned := 0 for _ = range providers { numProvidersReturned++ } t.Log(numProvidersReturned) if numProvidersReturned == max { t.Fatal("Context cancel had no effect") } }
func TestAppendWanted(t *testing.T) { const str = "foo" m := New(true) m.AddEntry(key.Key(str), 1) if !wantlistContains(m.ToProto().GetWantlist(), str) { t.Fail() } m.ToProto().GetWantlist().GetEntries() }
func newMessageFromProto(pbm pb.Message) BitSwapMessage { m := newMsg(pbm.GetWantlist().GetFull()) for _, e := range pbm.GetWantlist().GetEntries() { m.addEntry(key.Key(e.GetBlock()), int(e.GetPriority()), e.GetCancel()) } for _, d := range pbm.GetBlocks() { b := blocks.NewBlock(d) m.AddBlock(b) } return m }
func TestProviderManager(t *testing.T) { ctx := context.Background() mid := peer.ID("testing") p := NewProviderManager(ctx, mid) a := key.Key("test") p.AddProvider(ctx, a, peer.ID("testingprovider")) resp := p.GetProviders(ctx, a) if len(resp) != 1 { t.Fatal("Could not retrieve provider.") } p.proc.Close() }
func TestLayeredGet(t *testing.T) { // t.Skip("skipping test to debug another") if testing.Short() { t.SkipNow() } ctx := context.Background() _, _, dhts := setupDHTS(ctx, 4, t) defer func() { for i := 0; i < 4; i++ { dhts[i].Close() defer dhts[i].host.Close() } }() connect(t, ctx, dhts[0], dhts[1]) connect(t, ctx, dhts[1], dhts[2]) connect(t, ctx, dhts[1], dhts[3]) err := dhts[3].Provide(ctx, key.Key("/v/hello")) if err != nil { t.Fatal(err) } time.Sleep(time.Millisecond * 6) t.Log("interface was changed. GetValue should not use providers.") ctxT, _ := context.WithTimeout(ctx, time.Second) val, err := dhts[0].GetValue(ctxT, key.Key("/v/hello")) if err != routing.ErrNotFound { t.Error(err) } if string(val) == "world" { t.Error("should not get value.") } if len(val) > 0 && string(val) != "world" { t.Error("worse, there's a value and its not even the right one.") } }
func TestKeyNotFound(t *testing.T) { var pi = testutil.RandIdentityOrFatal(t) var key = key.Key("mock key") var ctx = context.Background() rs := NewServer() providers := rs.Client(pi).FindProvidersAsync(ctx, key, 10) _, ok := <-providers if ok { t.Fatal("should be closed") } }
func TestNode(t *testing.T) { n1 := &Node{Data: []byte("beep")} n2 := &Node{Data: []byte("boop")} n3 := &Node{Data: []byte("beep boop")} if err := n3.AddNodeLink("beep-link", n1); err != nil { t.Error(err) } if err := n3.AddNodeLink("boop-link", n2); err != nil { t.Error(err) } printn := func(name string, n *Node) { fmt.Println(">", name) fmt.Println("data:", string(n.Data)) fmt.Println("links:") for _, l := range n.Links { fmt.Println("-", l.Name, l.Size, l.Hash) } e, err := n.Encoded(false) if err != nil { t.Error(err) } else { fmt.Println("encoded:", e) } h, err := n.Multihash() if err != nil { t.Error(err) } else { fmt.Println("hash:", h) } k, err := n.Key() if err != nil { t.Error(err) } else if k != key.Key(h) { t.Error("Key is not equivalent to multihash") } else { fmt.Println("key: ", k) } SubtestNodeStat(t, n) } printn("beep", n1) printn("boop", n2) printn("beep boop", n3) }
func TestQueue(t *testing.T) { p1 := peer.ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31") // these aren't valid, because need to hex-decode. p2 := peer.ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a32") // these aren't valid, because need to hex-decode. p3 := peer.ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33") // these aren't valid, because need to hex-decode. p4 := peer.ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a34") // these aren't valid, because need to hex-decode. p5 := peer.ID("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31") // these aren't valid, because need to hex-decode. // but they work. // these are the peer.IDs' XORKeySpace Key values: // [228 47 151 130 156 102 222 232 218 31 132 94 170 208 80 253 120 103 55 35 91 237 48 157 81 245 57 247 66 150 9 40] // [26 249 85 75 54 49 25 30 21 86 117 62 85 145 48 175 155 194 210 216 58 14 241 143 28 209 129 144 122 28 163 6] // [78 135 26 216 178 181 224 181 234 117 2 248 152 115 255 103 244 34 4 152 193 88 9 225 8 127 216 158 226 8 236 246] // [125 135 124 6 226 160 101 94 192 57 39 12 18 79 121 140 190 154 147 55 44 83 101 151 63 255 94 179 51 203 241 51] pq := NewXORDistancePQ(key.Key("11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a31")) pq.Enqueue(p3) pq.Enqueue(p1) pq.Enqueue(p2) pq.Enqueue(p4) pq.Enqueue(p5) pq.Enqueue(p1) // should come out as: p1, p4, p3, p2 if d := pq.Dequeue(); d != p1 && d != p5 { t.Error("ordering failed") } if d := pq.Dequeue(); d != p1 && d != p5 { t.Error("ordering failed") } if d := pq.Dequeue(); d != p1 && d != p5 { t.Error("ordering failed") } if pq.Dequeue() != p4 { t.Error("ordering failed") } if pq.Dequeue() != p3 { t.Error("ordering failed") } if pq.Dequeue() != p2 { t.Error("ordering failed") } }
func GetPublicKey(r IpfsRouting, ctx context.Context, pkhash []byte) (ci.PubKey, error) { if dht, ok := r.(PubKeyFetcher); ok { // If we have a DHT as our routing system, use optimized fetcher return dht.GetPublicKey(ctx, peer.ID(pkhash)) } else { key := key.Key("/pk/" + string(pkhash)) pkval, err := r.GetValue(ctx, key) if err != nil { return nil, err } // get PublicKey from node.Data return ci.UnmarshalPublicKey(pkval) } }
func TestBlocks(t *testing.T) { bstore := blockstore.NewBlockstore(dssync.MutexWrap(ds.NewMapDatastore())) bs, err := New(bstore, offline.Exchange(bstore)) if err != nil { t.Error("failed to construct block service", err) return } defer bs.Close() b := blocks.NewBlock([]byte("beep boop")) h := u.Hash([]byte("beep boop")) if !bytes.Equal(b.Multihash, h) { t.Error("Block Multihash and data multihash not equal") } if b.Key() != key.Key(h) { t.Error("Block key and data multihash key not equal") } k, err := bs.AddBlock(b) if err != nil { t.Error("failed to add block to BlockService", err) return } if k != b.Key() { t.Error("returned key is not equal to block key", err) } ctx, _ := context.WithTimeout(context.TODO(), time.Second*5) b2, err := bs.GetBlock(ctx, b.Key()) if err != nil { t.Error("failed to retrieve block from BlockService", err) return } if b.Key() != b2.Key() { t.Error("Block keys not equal.") } if !bytes.Equal(b.Data, b2.Data) { t.Error("Block data is not equal.") } }
func (dht *IpfsDHT) handleGetProviders(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) { lm := make(lgbl.DeferredMap) lm["peer"] = func() interface{} { return p.Pretty() } defer log.EventBegin(ctx, "handleGetProviders", lm).Done() resp := pb.NewMessage(pmes.GetType(), pmes.GetKey(), pmes.GetClusterLevel()) key := key.Key(pmes.GetKey()) lm["key"] = func() interface{} { return key.Pretty() } // debug logging niceness. reqDesc := fmt.Sprintf("%s handleGetProviders(%s, %s): ", dht.self, p, key) log.Debugf("%s begin", reqDesc) defer log.Debugf("%s end", reqDesc) // check if we have this value, to add ourselves as provider. has, err := dht.datastore.Has(key.DsKey()) if err != nil && err != ds.ErrNotFound { log.Debugf("unexpected datastore error: %v\n", err) has = false } // setup providers providers := dht.providers.GetProviders(ctx, key) if has { providers = append(providers, dht.self) log.Debugf("%s have the value. added self as provider", reqDesc) } if providers != nil && len(providers) > 0 { infos := peer.PeerInfos(dht.peerstore, providers) resp.ProviderPeers = pb.PeerInfosToPBPeers(dht.host.Network(), infos) log.Debugf("%s have %d providers: %s", reqDesc, len(providers), infos) } // Also send closer peers. closer := dht.betterPeersToQuery(pmes, p, CloserPeerCount) if closer != nil { infos := peer.PeerInfos(dht.peerstore, closer) resp.CloserPeers = pb.PeerInfosToPBPeers(dht.host.Network(), infos) log.Debugf("%s have %d closer peers: %s", reqDesc, len(closer), infos) } return resp, nil }
func TestWantlist(t *testing.T) { keystrs := []string{"foo", "bar", "baz", "bat"} m := New(true) for _, s := range keystrs { m.AddEntry(key.Key(s), 1) } exported := m.Wantlist() for _, k := range exported { present := false for _, s := range keystrs { if s == string(k.Key) { present = true } } if !present { t.Logf("%v isn't in original list", k.Key) t.Fail() } } }
func TestPutProviderDoesntResultInDuplicates(t *testing.T) { routingBackend := datastore.NewMapDatastore() k := key.Key("foo") put := []*dhtpb.Message_Peer{ convPeer("bob", "127.0.0.1/tcp/4001"), convPeer("alice", "10.0.0.10/tcp/4001"), } if err := putRoutingProviders(routingBackend, k, put); err != nil { t.Fatal(err) } if err := putRoutingProviders(routingBackend, k, put); err != nil { t.Fatal(err) } got, err := getRoutingProviders(routingBackend, k) if err != nil { t.Fatal(err) } if len(got) != 2 { t.Fatal("should be 2 values, but there are", len(got)) } }
func TestGetFailures(t *testing.T) { if testing.Short() { t.SkipNow() } ctx := context.Background() mn, err := mocknet.FullMeshConnected(ctx, 2) if err != nil { t.Fatal(err) } hosts := mn.Hosts() tsds := dssync.MutexWrap(ds.NewMapDatastore()) d := NewDHT(ctx, hosts[0], tsds) d.Update(ctx, hosts[1].ID()) // Reply with failures to every message hosts[1].SetStreamHandler(ProtocolDHT, func(s inet.Stream) { defer s.Close() io.Copy(ioutil.Discard, s) }) // This one should time out ctx1, _ := context.WithTimeout(context.Background(), 200*time.Millisecond) if _, err := d.GetValue(ctx1, key.Key("test")); err != nil { if merr, ok := err.(u.MultiErr); ok && len(merr) > 0 { err = merr[0] } if err != context.DeadlineExceeded && err != context.Canceled { t.Fatal("Got different error than we expected", err) } } else { t.Fatal("Did not get expected error!") } t.Log("Timeout test passed.") // Reply with failures to every message hosts[1].SetStreamHandler(ProtocolDHT, func(s inet.Stream) { defer s.Close() pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax) pbw := ggio.NewDelimitedWriter(s) pmes := new(pb.Message) if err := pbr.ReadMsg(pmes); err != nil { panic(err) } resp := &pb.Message{ Type: pmes.Type, } if err := pbw.WriteMsg(resp); err != nil { panic(err) } }) // This one should fail with NotFound. // long context timeout to ensure we dont end too early. // the dht should be exhausting its query and returning not found. // (was 3 seconds before which should be _plenty_ of time, but maybe // travis machines really have a hard time...) ctx2, _ := context.WithTimeout(context.Background(), 20*time.Second) _, err = d.GetValue(ctx2, key.Key("test")) if err != nil { if merr, ok := err.(u.MultiErr); ok && len(merr) > 0 { err = merr[0] } if err != routing.ErrNotFound { t.Fatalf("Expected ErrNotFound, got: %s", err) } } else { t.Fatal("expected error, got none.") } t.Log("ErrNotFound check passed!") // Now we test this DHT's handleGetValue failure { typ := pb.Message_GET_VALUE str := "hello" sk, err := d.getOwnPrivateKey() if err != nil { t.Fatal(err) } rec, err := record.MakePutRecord(sk, key.Key(str), []byte("blah"), true) if err != nil { t.Fatal(err) } req := pb.Message{ Type: &typ, Key: &str, Record: rec, } s, err := hosts[1].NewStream(ProtocolDHT, hosts[0].ID()) if err != nil { t.Fatal(err) } defer s.Close() pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax) pbw := ggio.NewDelimitedWriter(s) if err := pbw.WriteMsg(&req); err != nil { t.Fatal(err) } pmes := new(pb.Message) if err := pbr.ReadMsg(pmes); err != nil { t.Fatal(err) } if pmes.GetRecord() != nil { t.Fatal("shouldnt have value") } if pmes.GetProviderPeers() != nil { t.Fatal("shouldnt have provider peers") } } }