| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package prober
- import (
- "context"
- "fmt"
- "net/netip"
- "slices"
- "sync"
- "testing"
- "tailscale.com/syncs"
- )
- func TestForEachAddr(t *testing.T) {
- clk := newFakeTime()
- p := newForTest(clk.Now, clk.NewTicker)
- opts := ForEachAddrOpts{
- Logf: t.Logf,
- Networks: []string{"ip4", "ip6"},
- }
- var (
- addr4_1 = netip.MustParseAddr("76.76.21.21")
- addr4_2 = netip.MustParseAddr("127.0.0.1")
- addr6_1 = netip.MustParseAddr("2600:9000:a602:b1e6:5b89:50a1:7cf7:67b8")
- addr6_2 = netip.MustParseAddr("2600:9000:a51d:27c1:6748:d035:a989:fb3c")
- )
- var resolverAddrs4, resolverAddrs6 syncs.AtomicValue[[]netip.Addr]
- resolverAddrs4.Store([]netip.Addr{addr4_1})
- resolverAddrs6.Store([]netip.Addr{addr6_1, addr6_2})
- opts.LookupNetIP = func(_ context.Context, network string, _ string) ([]netip.Addr, error) {
- if network == "ip4" {
- return resolverAddrs4.Load(), nil
- } else if network == "ip6" {
- return resolverAddrs6.Load(), nil
- }
- return nil, fmt.Errorf("unknown network %q", network)
- }
- var (
- mu sync.Mutex // protects following
- registered []netip.Addr
- )
- newProbe := func(addr netip.Addr) []*Probe {
- // Called to register a new prober
- t.Logf("called to register new probe for %v", addr)
- mu.Lock()
- defer mu.Unlock()
- registered = append(registered, addr)
- // Return a probe that does nothing; we don't care about what this does.
- probe := p.Run(fmt.Sprintf("website/%s", addr), probeInterval, nil, FuncProbe(func(_ context.Context) error {
- return nil
- }))
- return []*Probe{probe}
- }
- fep := makeForEachAddr("tailscale.com", newProbe, opts)
- // Mimic a call from the prober; we do this ourselves instead of
- // calling it via p.Run so we know that the probe has actually run.
- ctx := context.Background()
- if err := fep.run(ctx); err != nil {
- t.Fatalf("run: %v", err)
- }
- mu.Lock()
- wantAddrs := []netip.Addr{addr4_1, addr6_1, addr6_2}
- if !slices.Equal(registered, wantAddrs) {
- t.Errorf("got registered addrs %v; want %v", registered, wantAddrs)
- }
- mu.Unlock()
- // Now, update our IP addresses to force the prober to close and
- // re-create our probes.
- resolverAddrs4.Store([]netip.Addr{addr4_2})
- resolverAddrs6.Store([]netip.Addr{addr6_2})
- // Clear out our test data.
- mu.Lock()
- registered = nil
- mu.Unlock()
- // Run our individual prober again manually (so we don't have to wait
- // or coordinate with the created probers).
- if err := fep.run(ctx); err != nil {
- t.Fatalf("run: %v", err)
- }
- // Ensure that we only registered our net-new address (addr4_2).
- mu.Lock()
- wantAddrs = []netip.Addr{addr4_2}
- if !slices.Equal(registered, wantAddrs) {
- t.Errorf("got registered addrs %v; want %v", registered, wantAddrs)
- }
- mu.Unlock()
- // Check that we don't have a probe for the addresses that we expect to
- // have been removed (addr4_1 and addr6_1).
- p.mu.Lock()
- for _, addr := range []netip.Addr{addr4_1, addr6_1} {
- _, ok := fep.probes[addr]
- if ok {
- t.Errorf("probe for %v still exists", addr)
- }
- }
- p.mu.Unlock()
- }
|