package watcher_test import ( "context" "log/slog" "reflect" "testing" "sneak.berlin/go/dnswatcher/internal/portcheck" "sneak.berlin/go/dnswatcher/internal/resolver" "sneak.berlin/go/dnswatcher/internal/state" "sneak.berlin/go/dnswatcher/internal/tlscheck" "sneak.berlin/go/dnswatcher/internal/watcher" ) // TestCancelledCheckSavesNothing runs a check with its context already // cancelled, which is how the rest of a check runs once shutdown cuts it // short. The real resolver drops the DNS lookup without sending a query, // and the real port and TLS checkers fail without connecting. The port // and certificate state the last check saved must stay as it was, and // nothing may be notified. func TestCancelledCheckSavesNothing(t *testing.T) { t.Parallel() cfg := defaultTestConfig(t) cfg.Hostnames = []string{host} // newTestWatcher's watcher has stand-in checkers. This one, on the // same state and notifier, has the real ones. _, deps := newTestWatcher(t, cfg) w := watcher.NewForTest( cfg, deps.state, resolver.NewFromLogger(slog.Default()), portcheck.NewStandalone(), tlscheck.NewStandalone(), deps.notifier, ) // The last check found host at a local address, with both ports // open and a good certificate. const localIP = "127.0.0.1" deps.state.SetHostnameState(host, hostnameState( map[string]map[string][]string{nsA: {"A": {localIP}}}, )) ports := map[string]*state.PortState{ localIP + ":80": {Open: true, Hostnames: []string{host}}, localIP + ":443": {Open: true, Hostnames: []string{host}}, } for key, ps := range ports { deps.state.SetPortState(key, ps) } certKey := localIP + ":443:" + host cert := &state.CertificateState{CommonName: host, Status: "ok"} deps.state.SetCertificateState(certKey, cert) ctx, cancel := context.WithCancel(t.Context()) cancel() w.RunOnce(ctx) for key, want := range ports { got, _ := deps.state.GetPortState(key) if !reflect.DeepEqual(got, want) { t.Errorf("port %s saved as %+v, want %+v", key, got, want) } } got, _ := deps.state.GetCertificateState(certKey) if !reflect.DeepEqual(got, cert) { t.Errorf("certificate saved as %+v, want %+v", got, cert) } notifications := deps.notifier.getNotifications() if len(notifications) != 0 { t.Errorf("sent %v, want no notifications", notifications) } }