// TestStoresGossipStorage verifies reading and writing of bootstrap info. func TestStoresGossipStorage(t *testing.T) { defer leaktest.AfterTest(t)() manual, stores, ls, stopper := createStores(2, t) defer stopper.Stop() ls.AddStore(stores[0]) manual.Set(1) // Verify initial read is empty. var bi gossip.BootstrapInfo if err := ls.ReadBootstrapInfo(&bi); err != nil { t.Fatal(err) } if len(bi.Addresses) != 0 { t.Errorf("expected empty bootstrap info: %+v", bi) } // Add a fake address and write. manual.Increment(1) bi.Addresses = append(bi.Addresses, util.MakeUnresolvedAddr("tcp", "127.0.0.1:8001")) if err := ls.WriteBootstrapInfo(&bi); err != nil { t.Fatal(err) } // Verify on read. manual.Increment(1) var newBI gossip.BootstrapInfo if err := ls.ReadBootstrapInfo(&newBI); err != nil { t.Fatal(err) } if len(newBI.Addresses) != 1 { t.Errorf("expected single bootstrap info address: %+v", newBI) } // Add another store and verify it has bootstrap info written. ls.AddStore(stores[1]) // Create a new stores object to verify read. ls2 := NewStores(log.AmbientContext{}, ls.clock) ls2.AddStore(stores[1]) var verifyBI gossip.BootstrapInfo if err := ls2.ReadBootstrapInfo(&verifyBI); err != nil { t.Fatal(err) } if !reflect.DeepEqual(bi, verifyBI) { t.Errorf("bootstrap info %+v not equal to expected %+v", verifyBI, bi) } }
// WriteBootstrapInfo implements the gossip.Storage interface. Write // persists the supplied bootstrap info to every known store. Returns // nil on success; otherwise returns first error encountered writing // to the stores. func (ls *Stores) WriteBootstrapInfo(bi *gossip.BootstrapInfo) error { ls.mu.RLock() defer ls.mu.RUnlock() bi.Timestamp = ls.clock.Now() if err := ls.updateBootstrapInfo(bi); err != nil { return err } ctx := ls.AnnotateCtx(context.TODO()) log.Infof(ctx, "wrote %d node addresses to persistent storage", len(bi.Addresses)) return nil }
// TestStoresGossipStorageReadLatest verifies that the latest // bootstrap info from multiple stores is returned on Read. func TestStoresGossipStorageReadLatest(t *testing.T) { defer leaktest.AfterTest(t)() manual, stores, ls, stopper := createStores(2, t) defer stopper.Stop() ls.AddStore(stores[0]) // Set clock to 1. manual.Set(1) // Add a fake address and write. var bi gossip.BootstrapInfo bi.Addresses = append(bi.Addresses, util.MakeUnresolvedAddr("tcp", "127.0.0.1:8001")) if err := ls.WriteBootstrapInfo(&bi); err != nil { t.Fatal(err) } // Now remove store 0 and add store 1. ls.RemoveStore(stores[0]) ls.AddStore(stores[1]) // Increment clock, add another address and write. manual.Increment(1) bi.Addresses = append(bi.Addresses, util.MakeUnresolvedAddr("tcp", "127.0.0.1:8002")) if err := ls.WriteBootstrapInfo(&bi); err != nil { t.Fatal(err) } // Create a new stores object to freshly read. Should get latest // version from store 1. manual.Increment(1) ls2 := NewStores(log.AmbientContext{}, ls.clock) ls2.AddStore(stores[0]) ls2.AddStore(stores[1]) var verifyBI gossip.BootstrapInfo if err := ls2.ReadBootstrapInfo(&verifyBI); err != nil { t.Fatal(err) } if !reflect.DeepEqual(bi, verifyBI) { t.Errorf("bootstrap info %+v not equal to expected %+v", verifyBI, bi) } // Verify that stores[0], which had old info, was updated with // latest bootstrap info during the read. ls3 := NewStores(log.AmbientContext{}, ls.clock) ls3.AddStore(stores[0]) verifyBI.Reset() if err := ls2.ReadBootstrapInfo(&verifyBI); err != nil { t.Fatal(err) } if !reflect.DeepEqual(bi, verifyBI) { t.Errorf("bootstrap info %+v not equal to expected %+v", verifyBI, bi) } }