check / check (push) Waiting to run
The config tests unset variables without restoring them and read whatever the developer's shell exported, so results could differ from one machine to the next. config.ClearEnvForTest, in internal/config/testing.go, unsets every variable in the process environment and, when the test ends, leaves it exactly as it found it; every config test and the first-boot test call it before setting their own. TestEnvPositiveInt and TestEnvPort share one table runner, and the port errors name the bad value. A PORT of zero, below zero, or too large to parse now matches ErrInvalidPort, as one above 65535 already did. The README and the Settings page say an unparseable or non-positive RETENTION_SWEEP_INTERVAL stops startup. Model: opus-5-5
141 lines
3.6 KiB
Go
141 lines
3.6 KiB
Go
package config_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"sneak.berlin/go/webhooker/internal/config"
|
|
)
|
|
|
|
// envKeySentryDSN is the variable envSentryDSN reads in production.
|
|
const envKeySentryDSN = "SENTRY_DSN"
|
|
|
|
// validSentryDSN is a syntactically complete DSN. The host is under
|
|
// .invalid (RFC 2606), so nothing a test builds around it can reach a
|
|
// real Sentry installation.
|
|
const validSentryDSN = "https://abc123@sentry.invalid/42"
|
|
|
|
// envSentryDSNCase is one row of the envSentryDSN table.
|
|
type envSentryDSNCase struct {
|
|
name string
|
|
set bool
|
|
value string
|
|
expectError bool
|
|
expected string
|
|
}
|
|
|
|
// envSentryDSNCases is the envSentryDSN table. The three invalid
|
|
// values are the ones measured on the defect: each initialised the SDK
|
|
// with an error and left the process serving with reporting off.
|
|
func envSentryDSNCases() []envSentryDSNCase {
|
|
return []envSentryDSNCase{
|
|
{
|
|
name: "unset means reporting off",
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "empty means reporting off",
|
|
set: true,
|
|
value: "",
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "whitespace means reporting off",
|
|
set: true,
|
|
value: " ",
|
|
expected: "",
|
|
},
|
|
{
|
|
name: "a valid DSN is kept",
|
|
set: true,
|
|
value: validSentryDSN,
|
|
expected: validSentryDSN,
|
|
},
|
|
{
|
|
name: "surrounding whitespace is trimmed",
|
|
set: true,
|
|
value: " " + validSentryDSN + "\t",
|
|
expected: validSentryDSN,
|
|
},
|
|
{
|
|
name: "a value that is not a URL is rejected",
|
|
set: true,
|
|
value: "not-a-dsn",
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "an unparseable URL is rejected",
|
|
set: true,
|
|
value: "%%%",
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "a DSN without a public key is rejected",
|
|
set: true,
|
|
value: "https://example.invalid/1",
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "a DSN without a project id is rejected",
|
|
set: true,
|
|
value: "https://abc123@sentry.invalid/",
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "a non-HTTP scheme is rejected",
|
|
set: true,
|
|
value: "ftp://abc123@sentry.invalid/42",
|
|
expectError: true,
|
|
},
|
|
}
|
|
}
|
|
|
|
// TestEnvSentryDSN covers the helper directly. What it pins beyond the
|
|
// value is the failure shape: a set-but-unparseable DSN names the
|
|
// variable and the value, exactly as the other fail-loud helpers do,
|
|
// so an operator reads the fix off the message.
|
|
func TestEnvSentryDSN(t *testing.T) {
|
|
for _, tt := range envSentryDSNCases() {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Cannot use t.Parallel() here because t.Setenv
|
|
// is incompatible with parallel subtests.
|
|
config.ClearEnvForTest(t)
|
|
|
|
if tt.set {
|
|
t.Setenv(envKeySentryDSN, tt.value)
|
|
}
|
|
|
|
got, err := config.EnvSentryDSNForTest(envKeySentryDSN)
|
|
|
|
if tt.expectError {
|
|
require.Error(t, err)
|
|
require.ErrorIs(t, err, config.ErrInvalidSentryDSN)
|
|
assert.Contains(t, err.Error(), envKeySentryDSN)
|
|
assert.Contains(t, err.Error(), tt.value)
|
|
assert.Empty(t, got)
|
|
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, tt.expected, got)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSentryEnabled_TracksTheDSN pins that the one method answering
|
|
// "is anything being reported" agrees with the DSN in every state. The
|
|
// startup log, the SDK initialisation and the sentryhttp middleware
|
|
// all read it, so a log field cannot report reporting as on while
|
|
// nothing is sending.
|
|
func TestSentryEnabled_TracksTheDSN(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
assert.False(t, (&config.Config{}).SentryEnabled())
|
|
assert.True(
|
|
t,
|
|
(&config.Config{SentryDSN: validSentryDSN}).SentryEnabled(),
|
|
)
|
|
}
|