Fail loudly on an unparseable SENTRY_DSN and a malformed .env (closes #283)
check / check (push) Successful in 2m54s
check / check (push) Successful in 2m54s
This commit was merged in pull request #289.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sneak.berlin/go/webhooker/internal/config"
|
||||
)
|
||||
|
||||
// dotEnvKey is a throwaway variable name these tests write and read,
|
||||
// so they cannot disturb real configuration.
|
||||
const dotEnvKey = "WEBHOOKER_TEST_DISPATCH_VALUE"
|
||||
|
||||
// writeDotEnvInWorkingDir puts contents in a .env file in a fresh
|
||||
// temporary directory and moves the process there.
|
||||
//
|
||||
// The callers are deliberately not parallel and must stay that way:
|
||||
// t.Chdir moves the whole process. Go releases parallel tests only
|
||||
// after every sequential test in the package has finished, so nothing
|
||||
// else runs while these do.
|
||||
func writeDotEnvInWorkingDir(t *testing.T, contents string) {
|
||||
t.Helper()
|
||||
|
||||
dir := t.TempDir()
|
||||
require.NoError(t, os.WriteFile(
|
||||
filepath.Join(dir, config.DotEnvPath),
|
||||
[]byte(contents), 0o600,
|
||||
))
|
||||
t.Chdir(dir)
|
||||
}
|
||||
|
||||
// TestDispatch_MalformedDotEnvRefuses pins the second half of the
|
||||
// defect. godotenv applies nothing at all when a file will not parse,
|
||||
// so one mistyped line used to revert every variable in it to its
|
||||
// default and start the server anyway, with no log line naming the
|
||||
// file. The refusal has to arrive before any subcommand runs, which
|
||||
// is why `help` — the one subcommand that touches nothing — is still
|
||||
// refused here.
|
||||
//
|
||||
//nolint:paralleltest // t.Chdir moves the whole process.
|
||||
func TestDispatch_MalformedDotEnvRefuses(t *testing.T) {
|
||||
writeDotEnvInWorkingDir(t, "PORT 19615\n")
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := dispatch(
|
||||
[]string{helpCommand}, strings.NewReader(""), &stdout, &stderr,
|
||||
)
|
||||
|
||||
require.Equal(t, 1, code, "a broken .env must exit non-zero")
|
||||
assert.Contains(
|
||||
t, stderr.String(), config.DotEnvPath,
|
||||
"the refusal must name the file",
|
||||
)
|
||||
assert.Empty(
|
||||
t, stdout.String(),
|
||||
"the subcommand must not have run",
|
||||
)
|
||||
}
|
||||
|
||||
// TestDispatch_LoadsDotEnvBeforeSubcommands pins the ordering the
|
||||
// godotenv/autoload import used to provide for free. It ran in an
|
||||
// init(), so .env was in the environment before anything read it —
|
||||
// including config.DataDir, which both the DATA_DIR lock and resetpw
|
||||
// call outside the fx graph. Loading any later would let a .env that
|
||||
// sets DATA_DIR lock one directory while the config opened databases
|
||||
// in another.
|
||||
func TestDispatch_LoadsDotEnvBeforeSubcommands(t *testing.T) {
|
||||
t.Setenv(dotEnvKey, "placeholder")
|
||||
require.NoError(t, os.Unsetenv(dotEnvKey))
|
||||
|
||||
writeDotEnvInWorkingDir(t, dotEnvKey+"=from-dot-env\n")
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := dispatch(
|
||||
[]string{helpCommand}, strings.NewReader(""), &stdout, &stderr,
|
||||
)
|
||||
|
||||
require.Equal(t, 0, code)
|
||||
assert.Equal(
|
||||
t, "from-dot-env", os.Getenv(dotEnvKey),
|
||||
"the file must be applied before the subcommand runs",
|
||||
)
|
||||
}
|
||||
|
||||
// TestDispatch_MissingDotEnvIsFine pins the case most deployments are
|
||||
// in: no .env at all, which must stay a normal start.
|
||||
//
|
||||
//nolint:paralleltest // t.Chdir moves the whole process.
|
||||
func TestDispatch_MissingDotEnvIsFine(t *testing.T) {
|
||||
t.Chdir(t.TempDir())
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
code := dispatch(
|
||||
[]string{helpCommand}, strings.NewReader(""), &stdout, &stderr,
|
||||
)
|
||||
|
||||
require.Equal(t, 0, code)
|
||||
assert.Empty(t, stderr.String())
|
||||
}
|
||||
Reference in New Issue
Block a user