func TestPeriodicBootstrap(t *testing.T) { // t.Skip("skipping test to debug another") if ci.IsRunning() { t.Skip("skipping on CI. highly timing dependent") } if testing.Short() { t.SkipNow() } ctx := context.Background() nDHTs := 30 _, _, dhts := setupDHTS(ctx, nDHTs, t) defer func() { for i := 0; i < nDHTs; i++ { dhts[i].Close() defer dhts[i].host.Close() } }() // signal amplifier amplify := func(signal chan time.Time, other []chan time.Time) { for t := range signal { for _, s := range other { s <- t } } for _, s := range other { close(s) } } signal := make(chan time.Time) allSignals := []chan time.Time{} var cfg BootstrapConfig cfg = DefaultBootstrapConfig cfg.Queries = 5 // kick off periodic bootstrappers with instrumented signals. for _, dht := range dhts { s := make(chan time.Time) allSignals = append(allSignals, s) dht.BootstrapOnSignal(cfg, s) } go amplify(signal, allSignals) t.Logf("dhts are not connected.", nDHTs) for _, dht := range dhts { rtlen := dht.routingTable.Size() if rtlen > 0 { t.Errorf("routing table for %s should have 0 peers. has %d", dht.self, rtlen) } } for i := 0; i < nDHTs; i++ { connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)]) } t.Logf("DHTs are now connected to 1-2 others.", nDHTs) for _, dht := range dhts { rtlen := dht.routingTable.Size() if rtlen > 2 { t.Errorf("routing table for %s should have at most 2 peers. has %d", dht.self, rtlen) } } if u.Debug { printRoutingTables(dhts) } t.Logf("bootstrapping them so they find each other", nDHTs) signal <- time.Now() // this is async, and we dont know when it's finished with one cycle, so keep checking // until the routing tables look better, or some long timeout for the failure case. waitForWellFormedTables(t, dhts, 7, 10, 20*time.Second) if u.Debug { printRoutingTables(dhts) } }
func TestRepublisher(t *testing.T) { if ci.IsRunning() { t.Skip("dont run timing tests in CI") } ctx := context.TODO() pub := make(chan struct{}) pf := func(ctx context.Context, c *cid.Cid) error { pub <- struct{}{} return nil } tshort := time.Millisecond * 50 tlong := time.Second / 2 rp := NewRepublisher(ctx, pf, tshort, tlong) go rp.Run() rp.Update(nil) // should hit short timeout select { case <-time.After(tshort * 2): t.Fatal("publish didnt happen in time") case <-pub: } cctx, cancel := context.WithCancel(context.Background()) go func() { for { rp.Update(nil) time.Sleep(time.Millisecond * 10) select { case <-cctx.Done(): return default: } } }() select { case <-pub: t.Fatal("shouldnt have received publish yet!") case <-time.After((tlong * 9) / 10): } select { case <-pub: case <-time.After(tlong / 2): t.Fatal("waited too long for pub!") } cancel() go func() { err := rp.Close() if err != nil { t.Fatal(err) } }() // final pub from closing <-pub }