summaryrefslogtreecommitdiffhomepage
path: root/logtail/logtail_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'logtail/logtail_test.go')
-rw-r--r--logtail/logtail_test.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/logtail/logtail_test.go b/logtail/logtail_test.go
index eadbbc630..f1d0585f5 100644
--- a/logtail/logtail_test.go
+++ b/logtail/logtail_test.go
@@ -7,11 +7,16 @@ import (
"bytes"
"context"
"encoding/json"
+ "fmt"
"io"
+ "net"
"net/http"
"net/http/httptest"
+ "os"
"strings"
+ "sync"
"testing"
+ "testing/synctest"
"time"
"github.com/go-json-experiment/json/jsontext"
@@ -21,6 +26,23 @@ import (
"tailscale.com/util/must"
)
+// TestMain installs a safety net that refuses non-localhost dials for any
+// test in this package. Config.BaseURL defaults to https://log.tailscale.com
+// and Config.HTTPC defaults to http.DefaultClient, so a test that forgets to
+// override either can otherwise silently hit the real logtail server.
+func TestMain(m *testing.M) {
+ tr := http.DefaultTransport.(*http.Transport)
+ orig := tr.DialContext
+ tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
+ host, _, err := net.SplitHostPort(addr)
+ if err == nil && (host == "127.0.0.1" || host == "::1" || host == "localhost") {
+ return orig(ctx, network, addr)
+ }
+ return nil, fmt.Errorf("logtail tests: refusing to dial non-localhost address %q; use httptest.Server or a custom Config.HTTPC", addr)
+ }
+ os.Exit(m.Run())
+}
+
func TestFastShutdown(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
@@ -321,6 +343,59 @@ func TestLoggerWriteResult(t *testing.T) {
}
}
+type roundTripperFunc func(*http.Request) (*http.Response, error)
+
+func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { return f(r) }
+
+func TestNewLoggerDisabled(t *testing.T) { synctest.Test(t, synctestNewLoggerDisabled) }
+
+func synctestNewLoggerDisabled(t *testing.T) {
+ // When Config.Disabled is true, NewLogger must not emit the usual
+ // "logtail started" banner: the logger should start in the disabled
+ // state before the internal startup write, so nothing ever lands
+ // in the buffer for the upload goroutine to drain.
+ buf := NewMemoryBuffer(100)
+
+ // Any HTTP attempt indicates the banner leaked into the buffer and
+ // the upload goroutine tried to ship it. Report it once (so the
+ // retry spin doesn't drown the log), then block on the request
+ // context so synctest.Wait sees a durable block and Shutdown's
+ // uploadCancel can unblock us cleanly.
+ var once sync.Once
+ httpc := &http.Client{
+ Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) {
+ once.Do(func() {
+ t.Errorf("unexpected HTTP request while Disabled=true: %s", r.URL)
+ })
+ <-r.Context().Done()
+ return nil, r.Context().Err()
+ }),
+ }
+
+ logger := NewLogger(Config{
+ BaseURL: "http://logtail.test.invalid",
+ HTTPC: httpc,
+ Bus: eventbustest.NewBus(t),
+ Buffer: buf,
+ Disabled: true,
+ }, t.Logf)
+ defer func() {
+ // Pass an already-cancelled context so Shutdown invokes
+ // uploadCancel immediately; otherwise on the regression path
+ // (Disabled=false) the upload goroutine stays in its retry
+ // loop and synctest.Test never returns.
+ ctx, cancel := context.WithCancel(context.Background())
+ cancel()
+ logger.Shutdown(ctx)
+ }()
+
+ synctest.Wait()
+
+ if back, _ := buf.TryReadLine(); len(back) != 0 {
+ t.Errorf("Disabled logger buffered a startup entry: %q", back)
+ }
+}
+
func TestLoggerSetEnabled(t *testing.T) {
buf := NewMemoryBuffer(100)
lg := &Logger{