@@ -3,16 +3,22 @@ package dht
33import (
44 "context"
55 "crypto/rand"
6- "github.com/libp2p/go-libp2p-core/test"
76 "testing"
87 "time"
98
9+ "github.com/ipfs/go-cid"
10+ "github.com/libp2p/go-libp2p-core/test"
11+ "github.com/multiformats/go-multihash"
12+ "github.com/stretchr/testify/assert"
13+
14+ ds "github.com/ipfs/go-datastore"
1015 u "github.com/ipfs/go-ipfs-util"
1116 ci "github.com/libp2p/go-libp2p-core/crypto"
1217 "github.com/libp2p/go-libp2p-core/peer"
1318 "github.com/libp2p/go-libp2p-core/routing"
14- record "github.com/libp2p/go-libp2p-record"
15- tnet "github.com/libp2p/go-libp2p-testing/net"
19+ pb "github.com/libp2p/go-libp2p-kad-dht/pb"
20+ "github.com/libp2p/go-libp2p-record"
21+ "github.com/libp2p/go-libp2p-testing/net"
1622)
1723
1824// Check that GetPublicKey() correctly extracts a public key
@@ -305,3 +311,93 @@ func TestPubkeyGoodKeyFromDHTGoodKeyDirect(t *testing.T) {
305311 t .Fatal ("got incorrect public key" )
306312 }
307313}
314+
315+ func TestExpireNonProviderRecords (t * testing.T ) {
316+ // short sweep duration for testing
317+ sVal := nonProvRecordsCleanupInterval
318+ defer func () { nonProvRecordsCleanupInterval = sVal }()
319+ nonProvRecordsCleanupInterval = 10 * time .Millisecond
320+
321+ ctx , cancel := context .WithCancel (context .Background ())
322+ defer cancel ()
323+
324+ // helper functions
325+ putRecord := func (d * IpfsDHT , key string , value []byte ) error {
326+ rec := record .MakePutRecord (key , value )
327+ pmes := pb .NewMessage (pb .Message_PUT_VALUE , rec .Key , 0 )
328+ pmes .Record = rec
329+ _ , err := d .handlePutValue (ctx , "testpeer" , pmes )
330+ return err
331+ }
332+
333+ addProv := func (d * IpfsDHT , c cid.Cid ) error {
334+ msg , err := d .makeProvRecord (c )
335+ pi := peer.AddrInfo {
336+ ID : "testpeer" ,
337+ Addrs : d .host .Addrs (),
338+ }
339+ msg .ProviderPeers = pb .RawPeerInfosToPBPeers ([]peer.AddrInfo {pi })
340+ assert .NoError (t , err )
341+
342+ _ , err = d .handleAddProvider (ctx , "testpeer" , msg )
343+ return err
344+ }
345+
346+ getProv := func (d * IpfsDHT , c cid.Cid ) (* pb.Message , error ) {
347+ pmes := pb .NewMessage (pb .Message_GET_PROVIDERS , c .Bytes (), 0 )
348+ m , err := d .handleGetProviders (ctx , "test peer" , pmes )
349+ return m , err
350+ }
351+
352+ // TEST expiry does not happen if age(record) < MaxAge
353+ d := setupDHT (ctx , t , false )
354+
355+ // put non-provider record with current time
356+ key1 := "/v/key1"
357+ value1 := []byte ("v1" )
358+ assert .NoError (t , putRecord (d , key1 , value1 ))
359+
360+ // sweep will not delete it
361+ time .Sleep (100 * time .Millisecond )
362+
363+ // get & verify it's present
364+
365+ // we need to check the datastore for non-provider records to test the expiry Proc
366+ // because a side-effect of handle get value is also that it deletes records which are beyond MaxAge
367+ // & we do not want to hit that path
368+ _ , err := d .datastore .Get (convertToDsKey ([]byte (key1 )))
369+ assert .NoError (t , err )
370+ d .Close ()
371+ d .host .Close ()
372+
373+ // TEST expiry happens if age(record) > MaxAge
374+ mVal := maxNonProviderRecordAge
375+ maxNonProviderRecordAge = 50 * time .Millisecond
376+ defer func () { maxNonProviderRecordAge = mVal }()
377+
378+ d = setupDHT (ctx , t , false )
379+
380+ // put non-provider record with current time
381+ assert .NoError (t , putRecord (d , key1 , value1 ))
382+
383+ // add provider record with current time
384+ mh , err := multihash .Sum ([]byte ("data" ), multihash .SHA2_256 , - 1 )
385+ assert .NoError (t , err )
386+ c := cid .NewCidV0 (mh )
387+ assert .NoError (t , addProv (d , c ))
388+
389+ // sweep will remove non-provider record now
390+ time .Sleep (100 * time .Millisecond )
391+
392+ // verify non-provider record is absent
393+ _ , err = d .datastore .Get (convertToDsKey ([]byte (key1 )))
394+ assert .Equal (t , ds .ErrNotFound , err )
395+
396+ // but.... provider record is still available
397+ m , err := getProv (d , c )
398+ assert .NoError (t , err )
399+ assert .NotEmpty (t , m .ProviderPeers )
400+
401+ d .Close ()
402+ d .host .Close ()
403+ }
0 commit comments