@@ -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,97 @@ func TestPubkeyGoodKeyFromDHTGoodKeyDirect(t *testing.T) {
305311 t .Fatal ("got incorrect public key" )
306312 }
307313}
314+
315+ func TestExpireNonProviderRecords (t * testing.T ) {
316+ sVal := defaultRecordsSweepInterval
317+ defer func () { defaultRecordsSweepInterval = sVal }()
318+
319+ defaultRecordsSweepInterval = 20 * time .Millisecond
320+
321+ // create dht
322+ ctx , cancel := context .WithCancel (context .Background ())
323+ defer cancel ()
324+ d := setupDHT (ctx , t , false )
325+
326+ putRecord := func (key string , value []byte ) error {
327+ rec := record .MakePutRecord (key , value )
328+ pmes := pb .NewMessage (pb .Message_PUT_VALUE , rec .Key , 0 )
329+ pmes .Record = rec
330+ _ , err := d .handlePutValue (ctx , "testpeer" , pmes )
331+ return err
332+ }
333+
334+ addProv := func (c cid.Cid ) error {
335+ msg , err := d .makeProvRecord (c )
336+ pi := peer.AddrInfo {
337+ ID : "testpeer" ,
338+ Addrs : d .host .Addrs (),
339+ }
340+ msg .ProviderPeers = pb .RawPeerInfosToPBPeers ([]peer.AddrInfo {pi })
341+ assert .NoError (t , err )
342+
343+ _ , err = d .handleAddProvider (ctx , "testpeer" , msg )
344+ return err
345+ }
346+
347+ getProv := func (c cid.Cid ) (* pb.Message , error ) {
348+ pmes := pb .NewMessage (pb .Message_GET_PROVIDERS , c .Bytes (), 0 )
349+ m , err := d .handleGetProviders (ctx , "test peer" , pmes )
350+ return m , err
351+ }
352+
353+ // put non-provider record 1 with current time
354+ key1 := "/v/key1"
355+ value1 := []byte ("v1" )
356+ assert .NoError (t , putRecord (key1 , value1 ))
357+
358+ // put non-provider record 2 with current time
359+ key2 := "/v/key2"
360+ value2 := []byte ("v2" )
361+ assert .NoError (t , putRecord (key2 , value2 ))
362+
363+ // add provider with current time
364+ mh , err := multihash .Sum ([]byte ("data" ), multihash .SHA2_256 , - 1 )
365+ assert .NoError (t , err )
366+ c := cid .NewCidV0 (mh )
367+ assert .NoError (t , addProv (c ))
368+
369+ // sweep will not delete any of them
370+ time .Sleep (100 * time .Millisecond )
371+
372+ // get & verify all are present
373+
374+ // we need to check the datastore for non-provider records to test the expiry Proc
375+ // because a side-effect of handle get value is also that it deletes records which are beyond MaxAge
376+ // & we do not want to hit that path
377+ _ , err = d .datastore .Get (convertToDsKey ([]byte (key1 )))
378+ assert .NoError (t , err )
379+
380+ _ , err = d .datastore .Get (convertToDsKey ([]byte (key2 )))
381+ assert .NoError (t , err )
382+
383+ // ensure provider record is still available
384+ m , err := getProv (c )
385+ assert .NoError (t , err )
386+ assert .NotEmpty (t , m .ProviderPeers )
387+
388+ // change max age to 100 millisecond
389+ mVal := maxNonProviderRecordAge
390+ maxNonProviderRecordAge = 100 * time .Millisecond
391+ defer func () { maxNonProviderRecordAge = mVal }()
392+
393+ // sweep will remove non-provider both records now
394+ time .Sleep (100 * time .Millisecond )
395+
396+ // verify both non-provider records are absent
397+ _ , err = d .datastore .Get (convertToDsKey ([]byte (key1 )))
398+ assert .Equal (t , ds .ErrNotFound , err )
399+
400+ _ , err = d .datastore .Get (convertToDsKey ([]byte (key2 )))
401+ assert .Equal (t , ds .ErrNotFound , err )
402+
403+ // but, provider record will still be available
404+ m , err = getProv (c )
405+ assert .NoError (t , err )
406+ assert .NotEmpty (t , m .ProviderPeers )
407+ }
0 commit comments