context helpers, rework logging to support ongoing inheritance
Leaves module logger property as purely an override, pulling logger information directly from the lifecycle instead.
This commit is contained in:
@@ -3,6 +3,7 @@ package app
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -11,20 +12,20 @@ import (
|
||||
func TestNewLifecycle(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Create a blank Lifecycle instance
|
||||
lc := NewLifecycle()
|
||||
assert.NotNil(lc, "expected Lifecycle instance to be created")
|
||||
assert.Equal(slog.Default(), lc.logger, "expected default logger to be set")
|
||||
}
|
||||
|
||||
func TestNewLifecycleL(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
assert.Equal(slog.Default(), lc.Logger(), "expected default logger to be available")
|
||||
|
||||
// Create a blank Lifecycle instance with a custom logger
|
||||
logger := slog.Default()
|
||||
lc := NewLifecycleL(logger)
|
||||
handler := slog.NewTextHandler(os.Stderr, nil)
|
||||
logger := slog.New(handler)
|
||||
lc = NewLifecycle().WithOpts(LifecycleOpts{
|
||||
Logger: logger,
|
||||
})
|
||||
|
||||
assert.NotNil(lc)
|
||||
assert.Equal(logger, lc.logger, "expected logger to be set")
|
||||
assert.Equal(logger, lc.Logger(), "expected logger to match")
|
||||
assert.Len(lc.modules, 0, "expected modules to be empty")
|
||||
assert.Len(lc.setupTracker, 0, "expected setup tracker to be empty")
|
||||
assert.Len(lc.teardownTracker, 0, "expected teardown tracker to be empty")
|
||||
@@ -33,15 +34,15 @@ func TestNewLifecycleL(t *testing.T) {
|
||||
mod1 := NewModule("module1", ModuleOpts{})
|
||||
mod2 := NewModule("module2", ModuleOpts{})
|
||||
|
||||
lcWithModules := NewLifecycleL(logger, mod1, mod2)
|
||||
lcWithModules := NewLifecycle(mod1, mod2)
|
||||
assert.NotNil(lcWithModules, "expected Lifecycle with modules to be created")
|
||||
assert.Contains(lcWithModules.modules, mod1, "expected module1 to be included")
|
||||
assert.Contains(lcWithModules.modules, mod2, "expected module2 to be included")
|
||||
assert.Len(lcWithModules.modules, 2, "expected two modules to be present")
|
||||
|
||||
// Test for duplicate module names
|
||||
assert.PanicsWithValue("duplicate module name: module1", func() {
|
||||
NewLifecycleL(logger, mod1, mod1)
|
||||
assert.PanicsWithValue("duplicate module: [module1]", func() {
|
||||
NewLifecycle(mod1, mod1)
|
||||
}, "expected panic on duplicate module names")
|
||||
}
|
||||
|
||||
@@ -57,17 +58,25 @@ func TestLifecycle_WithOpts(t *testing.T) {
|
||||
assert.Equal(opts, lc.opts, "expected Lifecycle to have the provided options")
|
||||
}
|
||||
|
||||
func TestLifecycle_WithLogger(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
lc := NewLifecycle()
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
lc.WithLogger(logger)
|
||||
assert.Equal(logger, lc.Logger(), "expected Lifecycle to have the provided logger")
|
||||
}
|
||||
|
||||
func TestLifecycle_Logger(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
lc := NewLifecycle()
|
||||
assert.Equal(slog.Default(), lc.Logger(), "expected Logger to return a logger")
|
||||
|
||||
// Test panic when logger is not initialized
|
||||
lc.logger = nil
|
||||
assert.PanicsWithValue("lifecycle logger is not initialized", func() {
|
||||
lc.Logger()
|
||||
}, "expected Logger to panic when logger is not set")
|
||||
// Test that custom logger is used
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
lc.opts.Logger = logger
|
||||
assert.Equal(logger, lc.Logger())
|
||||
}
|
||||
|
||||
func TestLifecycle_Setup(t *testing.T) {
|
||||
@@ -190,6 +199,7 @@ func TestLifecycle_Teardown(t *testing.T) {
|
||||
|
||||
// Fake setup for all modules
|
||||
for _, mod := range tc.modules {
|
||||
mod.loaded = true // Mark as loaded
|
||||
lc.setupTracker[mod.name] = 0 // Mark as set up
|
||||
}
|
||||
|
||||
@@ -200,7 +210,8 @@ func TestLifecycle_Teardown(t *testing.T) {
|
||||
for _, mod := range tc.modules {
|
||||
if mod.teardown != nil {
|
||||
_, ok := lc.teardownTracker[mod.name]
|
||||
assert.True(ok, "expected module to be marked as torn down")
|
||||
assert.Truef(ok, "expected module %s to be marked as torn down", mod)
|
||||
assert.Falsef(mod.loaded, "expected module %s to be unloaded after teardown", mod)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -218,22 +229,33 @@ func TestLifecycle_Require(t *testing.T) {
|
||||
mod := NewModule("module1", ModuleOpts{
|
||||
Setup: func(m *Module) error { return nil },
|
||||
})
|
||||
lc.Require(mod)
|
||||
assert.Equal(t, lc.logger, mod.logger, "expected module logger to match lifecycle logger")
|
||||
err := lc.Require(mod)
|
||||
assert.NoError(t, err, "expected Require to succeed")
|
||||
assert.Contains(t, lc.setupTracker, mod.name, "expected module to be marked as set up")
|
||||
assert.Nil(t, mod.logger, "expected module logger to be nil")
|
||||
assert.Equal(t, lc.Logger(), mod.Logger(), "expected module logger to match lifecycle logger")
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireUnique(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
lc := NewLifecycle()
|
||||
|
||||
mod := NewModule("module1", ModuleOpts{})
|
||||
err := lc.RequireUnique(mod)
|
||||
assert.NoError(t, err, "expected RequireL to succeed")
|
||||
assert.Equal(t, lc.logger, mod.logger, "expected module logger to match lifecycle logger")
|
||||
assert.NoError(err, "expected RequireL to succeed")
|
||||
assert.Nil(mod.logger, "expected module logger to be nil")
|
||||
|
||||
// Requiring the same module again should fail
|
||||
err = lc.RequireUnique(mod)
|
||||
assert.Error(err, "expected RequireUnique to fail on duplicate module")
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireL(t *testing.T) {
|
||||
// Create a logger for the test cases
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
logger *slog.Logger
|
||||
modules []*Module
|
||||
existingModules []*Module
|
||||
expectedErr string
|
||||
@@ -245,7 +267,7 @@ func TestLifecycle_RequireL(t *testing.T) {
|
||||
{
|
||||
name: "nil module",
|
||||
modules: []*Module{nil},
|
||||
expectedErr: "module is nil",
|
||||
expectedErr: "is nil",
|
||||
},
|
||||
{
|
||||
name: "basic module",
|
||||
@@ -309,21 +331,16 @@ func TestLifecycle_RequireL(t *testing.T) {
|
||||
|
||||
lc := NewLifecycle(tc.existingModules...)
|
||||
|
||||
l := tc.logger
|
||||
if l == nil {
|
||||
l = lc.logger
|
||||
}
|
||||
|
||||
err := lc.RequireL(tc.logger, tc.modules...)
|
||||
err := lc.RequireL(logger, tc.modules...)
|
||||
|
||||
if tc.expectedErr == "" {
|
||||
assert.NoError(err, "expected RequireL to succeed")
|
||||
for _, mod := range tc.modules {
|
||||
for i, mod := range tc.modules {
|
||||
if mod != nil {
|
||||
_, ok := lc.setupTracker[mod.name]
|
||||
assert.True(ok, "expected module to be marked as set up")
|
||||
assert.True(mod.loaded, "expected module to be loaded")
|
||||
assert.Equal(l, mod.logger, "expected module logger to match")
|
||||
assert.Truef(ok, "expected module %d %s to be marked as set up", i, mod)
|
||||
assert.Truef(mod.loaded, "expected module %d %s to be loaded", i, mod)
|
||||
assert.Equalf(logger, mod.logger, "expected module %d %s logger to match", i, mod)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -335,6 +352,9 @@ func TestLifecycle_RequireL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLifecycle_RequireUniqueL(t *testing.T) {
|
||||
// Create a logger for the test cases
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
modules []*Module
|
||||
@@ -354,12 +374,12 @@ func TestLifecycle_RequireUniqueL(t *testing.T) {
|
||||
NewModule("module2", ModuleOpts{}),
|
||||
},
|
||||
existingModules: []string{"module1"},
|
||||
expectedErr: "module 'module1' is already set up, cannot require it again",
|
||||
expectedErr: "module [module1] is already set up, cannot require it again",
|
||||
},
|
||||
{
|
||||
name: "nil module",
|
||||
modules: []*Module{nil},
|
||||
expectedErr: "module is nil",
|
||||
expectedErr: "is nil",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -373,7 +393,7 @@ func TestLifecycle_RequireUniqueL(t *testing.T) {
|
||||
lc.setupTracker[modName] = 0 // Mark as set up
|
||||
}
|
||||
|
||||
err := lc.RequireUniqueL(lc.logger, tc.modules...)
|
||||
err := lc.RequireUniqueL(logger, tc.modules...)
|
||||
if tc.expectedErr == "" {
|
||||
assert.NoError(err, "expected RequireUniqueL to succeed")
|
||||
} else {
|
||||
@@ -385,6 +405,9 @@ func TestLifecycle_RequireUniqueL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLifecycle_setupSingle(t *testing.T) {
|
||||
// Create a logger for the test cases
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, nil))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
lc *Lifecycle
|
||||
@@ -447,7 +470,7 @@ func TestLifecycle_setupSingle(t *testing.T) {
|
||||
Setup: func(m *Module) error { return errors.New("dependency setup failed") },
|
||||
}),
|
||||
},
|
||||
expectedErr: "error initializing 'errorModule'",
|
||||
expectedErr: "dependency setup failed",
|
||||
},
|
||||
{
|
||||
name: "dependency without autoload",
|
||||
@@ -472,7 +495,7 @@ func TestLifecycle_setupSingle(t *testing.T) {
|
||||
|
||||
l := tc.logger
|
||||
if l == nil {
|
||||
l = slog.Default()
|
||||
l = logger
|
||||
}
|
||||
|
||||
lc := tc.lc
|
||||
@@ -480,20 +503,19 @@ func TestLifecycle_setupSingle(t *testing.T) {
|
||||
lc = NewLifecycle(tc.modules...)
|
||||
}
|
||||
|
||||
err := lc.setupSingle(tc.targetModule, l)
|
||||
|
||||
if tc.targetModule != nil {
|
||||
assert.Equal(l, tc.targetModule.logger, "expected module logger to match")
|
||||
}
|
||||
err := lc.setupSingle(l, tc.targetModule)
|
||||
|
||||
if tc.expectedErr == "" {
|
||||
assert.NoError(err, "expected no error from setupSingle")
|
||||
} else {
|
||||
assert.Contains(err.Error(), tc.expectedErr, "expected error message to match")
|
||||
}
|
||||
|
||||
if tc.targetModule != nil {
|
||||
assert.Equal(l, tc.targetModule.logger, "expected module logger to match")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestLifecycle_teardownSingle(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user