Files
trufflehog/pkg/log/codeowners_leveler_test.go
Miccah Castorina 31402a3a96 Implement CodeOwnersLeveler
CodeOwnersLeveler is a log leveler that can be dynamically controlled by
the owners found in CODEOWNERS. Levels can be independently set for each
owner, and logs will be checked based on the owner of the function that
emitted them.
2026-02-06 19:07:48 -08:00

141 lines
3.7 KiB
Go

package log
import (
"bytes"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zapcore"
)
// testCodeOwner is a test implementation of the codeOwnerData interface.
type testCodeOwner struct {
owners []string
ownersOf func(string) []string
}
func (t testCodeOwner) Owners() []string { return t.owners }
func (t testCodeOwner) OwnersOf(path string) []string {
if t.ownersOf != nil {
return t.ownersOf(path)
}
return nil
}
func TestCodeOwnersLeveler_Logging(t *testing.T) {
var buf bytes.Buffer
lvl := NewCodeOwnersLeveler(testCodeOwner{
owners: []string{"me", "you"},
ownersOf: func(path string) []string {
base := filepath.Base(path)
// Anonymous functions within a function are of the
// form: pkg.Function.funcN
if strings.Count(base, ".") == 2 {
return []string{"you"}
}
return []string{"me"}
},
})
logger, flush := New(
"service-name",
WithConsoleSink(&buf, WithLeveler(lvl)),
)
lvl.SetLevelFor("me", 1)
lvl.SetLevelFor("you", 2)
// "me" codeowner (level 1)
logger.V(0).Info("line 1")
logger.V(1).Info("line 2")
logger.V(2).Info("line 3")
logger.V(3).Info("line 4")
func() {
// "you" codeowner (level 2)
logger.V(0).Info("line 5")
logger.V(1).Info("line 6")
logger.V(2).Info("line 7")
logger.V(3).Info("line 8")
}()
require.Nil(t, flush())
// buf should have lines 1, 2 (from "me") and 5, 6, 7 (from "you").
require.Contains(t, buf.String(), "line 1")
require.Contains(t, buf.String(), "line 2")
require.NotContains(t, buf.String(), "line 3")
require.NotContains(t, buf.String(), "line 4")
require.Contains(t, buf.String(), "line 5")
require.Contains(t, buf.String(), "line 6")
require.Contains(t, buf.String(), "line 7")
require.NotContains(t, buf.String(), "line 8")
}
func TestCodeOwnersLeveler_MostVerboseLevel(t *testing.T) {
lvl := NewCodeOwnersLeveler(testCodeOwner{
owners: []string{"me", "you"},
ownersOf: func(path string) []string {
return []string{"me", "you"}
},
})
lvl.SetLevelFor("me", 1)
require.Equal(t, zapcore.Level(-1), lvl.Level())
lvl.SetLevelFor("you", 2)
require.Equal(t, zapcore.Level(-2), lvl.Level())
}
func TestCodeOwnersLeveler_AnyEnabled(t *testing.T) {
lvl := NewCodeOwnersLeveler(testCodeOwner{
owners: []string{"me", "you"},
ownersOf: func(path string) []string {
return []string{"me", "you"}
},
})
lvl.SetLevelFor("me", 1)
require.True(t, lvl.Enabled(zapcore.Level(0)))
require.True(t, lvl.Enabled(zapcore.Level(-1)))
require.False(t, lvl.Enabled(zapcore.Level(-2)))
require.False(t, lvl.Enabled(zapcore.Level(-3)))
lvl.SetLevelFor("you", 2)
require.True(t, lvl.Enabled(zapcore.Level(0)))
require.True(t, lvl.Enabled(zapcore.Level(-1)))
require.True(t, lvl.Enabled(zapcore.Level(-2)))
require.False(t, lvl.Enabled(zapcore.Level(-3)))
}
func TestCodeOwnersLeveler_BaseLevelEnabled(t *testing.T) {
lvl := NewCodeOwnersLeveler(testCodeOwner{})
require.True(t, lvl.Enabled(zapcore.Level(0)))
require.False(t, lvl.Enabled(zapcore.Level(-1)))
require.False(t, lvl.Enabled(zapcore.Level(-2)))
lvl.SetLevel(zapcore.Level(-1))
require.True(t, lvl.Enabled(zapcore.Level(0)))
require.True(t, lvl.Enabled(zapcore.Level(-1)))
require.False(t, lvl.Enabled(zapcore.Level(-2)))
}
func TestCodeOwnersLeveler_BaseLevelMostVerbose(t *testing.T) {
lvl := NewCodeOwnersLeveler(testCodeOwner{
owners: []string{"me", "you"},
ownersOf: func(path string) []string {
return []string{"me", "you"}
},
})
lvl.SetLevelFor("me", 1)
lvl.SetLevelFor("you", 2)
SetLevelForControl(lvl, 3)
require.True(t, lvl.Enabled(zapcore.Level(0)))
require.True(t, lvl.Enabled(zapcore.Level(-1)))
require.True(t, lvl.Enabled(zapcore.Level(-2)))
require.True(t, lvl.Enabled(zapcore.Level(-3)))
require.False(t, lvl.Enabled(zapcore.Level(-4)))
}