| 14 | ) |
| 15 | |
| 16 | func TestRapidToggleConfig(t *testing.T) { |
| 17 | defer goleak.VerifyNone(t) |
| 18 | |
| 19 | vh := &VirtualHarness{} |
| 20 | vh.LogLevel = new(slog.LevelInfo) |
| 21 | a1 := "192.168.1.1:1234" |
| 22 | vh.NewNode("a", "10.0.0.1/32") |
| 23 | b1 := "192.168.1.2:1234" |
| 24 | vh.NewNode("b", "10.0.0.2/32") |
| 25 | vh.Central.Graph = []string{ |
| 26 | "a, b", |
| 27 | } |
| 28 | vh.Endpoints = map[string]state.NodeId{ |
| 29 | a1: "a", |
| 30 | b1: "b", |
| 31 | } |
| 32 | vh.AddLink(a1, b1) |
| 33 | vh.AddLink(b1, a1) |
| 34 | |
| 35 | errs := vh.Start() |
| 36 | |
| 37 | vn := vh.Net |
| 38 | vn.SelfHandler = func(node state.NodeId, src, dst netip.Addr, data []byte) bool { |
| 39 | return true |
| 40 | } |
| 41 | |
| 42 | // Wait for initial convergence. |
| 43 | time.Sleep(3 * time.Second) |
| 44 | |
| 45 | _, baseCfg := vh.Central.Clone() |
| 46 | _, extraCfg := vh.Central.Clone() |
| 47 | |
| 48 | aIdx := vh.IndexOf("a") |
| 49 | extraRouter := extraCfg.Routers[aIdx] |
| 50 | for i := 0; i < 50; i++ { |
| 51 | extraRouter.Prefixes = append(extraRouter.Prefixes, state.PrefixHealthWrapper{ |
| 52 | PrefixHealth: &state.StaticPrefixHealth{ |
| 53 | Prefix: netip.MustParsePrefix(fmt.Sprintf("10.1.0.%d/32", i)), |
| 54 | Metric: 0, |
| 55 | }, |
| 56 | }) |
| 57 | } |
| 58 | extraCfg.Routers[aIdx] = extraRouter |
| 59 | |
| 60 | a := vh.Nylons[vh.IndexOf("a")].Load() |
| 61 | |
| 62 | // Break shared *DynamicEndpoint pointers from startup. |
| 63 | { |
| 64 | done := make(chan struct{}) |
| 65 | a.Dispatch(func() error { |
| 66 | _, nc := a.CentralCfg.Clone() |
| 67 | a.CentralCfg = *nc |
| 68 | close(done) |
| 69 | return nil |
| 70 | }) |
| 71 | <-done |
| 72 | } |
| 73 | |