vault/helper/trace/debug_trace_test.go
Bruno Oliveira de Souza a2c467cc22
VAULT-31409: trace postUnseal function (#28895)
* initial implementation of unseal trace

* close file if we fail to start the trace

didn't bother to check the error from traceFile.Close()

* use reloadable config instead of env var

* license

* remove leftover

* allow setting custom dir and remove new package

* bring back StartDebugTrace

after talking to Kuba it sounds like it's a good idea to try to move stuff out of core, so even if there's no immediate need for a generic debug trace function it's still fair to add it

* track postUnseal instead of unsealInternal

also some usability improvements from manual testing

* address PR comments

* address security review

there were concerns about using the /tmp directory because of permissions, or having a default dir at all, so now it's required to set a dir in order to generate the traces.

* add unit tests to StartDebugTrace

* move back to default dir

* document new parameters

* add tiny integration test

* avoid column in trace filename

sounds like it might be forbidden in Windows and possibly cause problems in some MacOS applications.

* address PR feedback

* add go doc to test

CI was complaining about missing comments on the new test function. It feels a bit silly to require this of tests but whatever XD

* fix tests
2024-11-26 15:04:34 -03:00

112 lines
3.4 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package trace
import (
"os"
"path/filepath"
"runtime"
"testing"
"github.com/stretchr/testify/require"
)
// TestStartDebugTrace tests the debug trace functionality creating real
// files and traces.
func TestStartDebugTrace(t *testing.T) {
t.Run("error_on_non_existent_dir", func(t *testing.T) {
_, _, err := StartDebugTrace("non-existent-dir", "filePrefix")
require.Error(t, err)
require.Contains(t, err.Error(), "does not exist")
})
t.Run("error_on_non_dir", func(t *testing.T) {
f, err := os.CreateTemp("", "")
require.NoError(t, err)
require.NoError(t, f.Close())
_, _, err = StartDebugTrace(f.Name(), "")
require.Error(t, err)
require.Contains(t, err.Error(), "is not a directory")
})
t.Run("error_on_failed_to_create_trace_file", func(t *testing.T) {
noWriteFolder := filepath.Join(os.TempDir(), "no-write-permissions")
// create folder without write permission
err := os.Mkdir(noWriteFolder, 0o000)
t.Cleanup(func() {
os.RemoveAll(noWriteFolder)
})
require.NoError(t, err)
_, _, err = StartDebugTrace(noWriteFolder, "")
require.Error(t, err)
require.Contains(t, err.Error(), "failed to create trace file")
})
t.Run("error_trying_to_start_second_concurrent_trace", func(t *testing.T) {
dir, err := os.MkdirTemp("", "")
require.NoError(t, err)
t.Cleanup(func() {
os.RemoveAll(dir)
})
_, stop, err := StartDebugTrace(dir, "filePrefix")
require.NoError(t, err)
_, stopNil, err := StartDebugTrace(dir, "filePrefix")
require.Error(t, err)
require.Contains(t, err.Error(), "failed to start trace")
require.NoError(t, stop())
require.Nil(t, stopNil)
})
t.Run("error_when_stating_tmp_dir_with_restricted_permissions", func(t *testing.T) {
// this test relies on setting TMPDIR so skip it if we're not on a Unix system
if runtime.GOOS == "windows" {
t.Skip("skipping test on Windows")
}
tmpMissingPermissions := filepath.Join(t.TempDir(), "missing_permissions")
err := os.Mkdir(tmpMissingPermissions, 0o000)
require.NoError(t, err)
t.Setenv("TMPDIR", tmpMissingPermissions)
_, _, err = StartDebugTrace("", "filePrefix")
require.Error(t, err)
require.Contains(t, err.Error(), "failed to stat trace directory")
})
t.Run("successful_trace_generates_non_empty_file", func(t *testing.T) {
dir, err := os.MkdirTemp("", "")
require.NoError(t, err)
t.Cleanup(func() {
os.RemoveAll(dir)
})
file, stop, err := StartDebugTrace(dir, "filePrefix")
require.NoError(t, err)
require.NoError(t, stop())
f, err := os.Stat(file)
require.NoError(t, err)
require.Greater(t, f.Size(), int64(0))
})
t.Run("successful_creation_of_tmp_dir", func(t *testing.T) {
os.RemoveAll(filepath.Join(os.TempDir(), "vault-traces"))
file, stop, err := StartDebugTrace("", "filePrefix")
require.NoError(t, err)
require.NoError(t, stop())
require.Contains(t, file, filepath.Join(os.TempDir(), "vault-traces", "filePrefix"))
f, err := os.Stat(file)
require.NoError(t, err)
require.Greater(t, f.Size(), int64(0))
})
t.Run("successful_trace_with_existing_tmp_dir", func(t *testing.T) {
os.Mkdir(filepath.Join(os.TempDir(), "vault-traces"), 0o700)
file, stop, err := StartDebugTrace("", "filePrefix")
require.NoError(t, err)
require.NoError(t, stop())
require.Contains(t, file, filepath.Join(os.TempDir(), "vault-traces", "filePrefix"))
f, err := os.Stat(file)
require.NoError(t, err)
require.Greater(t, f.Size(), int64(0))
})
}