Skip to content

Commit

Permalink
main & tester (#120)
Browse files Browse the repository at this point in the history
* main & tester
  • Loading branch information
jmnote authored Oct 5, 2024
1 parent ab3085b commit 2081d13
Show file tree
Hide file tree
Showing 56 changed files with 1,530 additions and 1,599 deletions.
57 changes: 57 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package app

import (
"fmt"

"github.com/kuoss/common/logger"
"github.com/kuoss/lethe/config"
"github.com/kuoss/lethe/rotator"
"github.com/kuoss/lethe/router"
"github.com/kuoss/lethe/storage/fileservice"
"github.com/kuoss/lethe/storage/logservice"
"github.com/kuoss/lethe/storage/queryservice"
)

type IApp interface {
New(version string) error
Run() error
}

type App struct {
Config *config.Config
rotator *rotator.Rotator
router *router.Router
}

// New creates a new App instance
func New(version string) (*App, error) {
// Load configuration
cfg, err := config.New(version)
if err != nil {
return nil, fmt.Errorf("failed to load configuration: %w", err)
}
logger.Infof("Loaded configuration: %v", cfg)

// Initialize services
fileService, err := fileservice.New(cfg)
if err != nil {
return nil, fmt.Errorf("new fileservice err: %w", err)
}
logService := logservice.New(cfg, fileService)
queryService := queryservice.New(cfg, logService)

// Create rotator & router
myRotator := rotator.New(cfg, fileService)
myRouter := router.New(cfg, fileService, queryService)

return &App{
Config: cfg,
rotator: myRotator,
router: myRouter,
}, nil
}

func (a App) Run() error {
a.rotator.Start()
return a.router.Run()
}
108 changes: 108 additions & 0 deletions app/app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package app

import (
"context"
"testing"
"time"

"github.com/kuoss/common/tester"
"github.com/kuoss/lethe/config"
"github.com/stretchr/testify/require"
)

func TestNew(t *testing.T) {
_, cleanup := tester.SetupDir(t, map[string]string{})
defer cleanup()

wantConfig := &config.Config{
Version: "test",
Query: config.Query{
Limit: 1000,
Timeout: 20000000000,
},
Retention: config.Retention{
Size: 0,
Time: 15 * 24 * time.Hour, // 15d
SizingStrategy: "file",
RotationInterval: 20 * time.Second,
},
Storage: config.Storage{LogDataPath: "data/log"},
Web: config.Web{
ListenAddress: ":6060",
GinMode: "release",
},
}

app, err := New("test")
require.NoError(t, err)
require.NotEmpty(t, app)
require.NotEmpty(t, app.rotator)
require.NotEmpty(t, app.router)
require.Equal(t, wantConfig, app.Config)
}

func TestNew_error1(t *testing.T) {
_, cleanup := tester.SetupDir(t, map[string]string{
"@/testdata/etc/lethe.error1.yaml": "etc/lethe.yaml",
})
defer cleanup()

app, err := New("test")
require.Error(t, err)
require.Nil(t, app)
}

func TestNew_error2(t *testing.T) {
_, cleanup := tester.SetupDir(t, map[string]string{
"@/testdata/etc/lethe.error1.yaml": "etc/lethe.yaml",
})
defer cleanup()

app, err := New("test")
require.Error(t, err)
require.Nil(t, app)
}

func TestRun_error4(t *testing.T) {
_, cleanup := tester.SetupDir(t, map[string]string{
"@/testdata/etc/lethe.error4.yaml": "etc/lethe.yaml",
})
defer cleanup()

app, err := New("test")
require.NoError(t, err)

err = app.Run()
require.EqualError(t, err, "listen tcp: address foo: missing port in address")
}

func TestRun_smokeTest(t *testing.T) {
_, cleanup := tester.SetupDir(t, map[string]string{})
defer cleanup()

app, err := New("test")
require.NoError(t, err)

ctx, cancel := context.WithTimeout(context.TODO(), time.Second)
defer cancel()
panicChan := make(chan interface{}, 1)
go func() {
defer func() {
if r := recover(); r != nil {
panicChan <- r
}
}()
err := app.Run()
require.NoError(t, err)
close(panicChan)
}()

var done bool
select {
case <-ctx.Done():
done = true
case p := <-panicChan:
t.Fatalf("panic occurred: %v", p)
}
require.True(t, done)
}
63 changes: 12 additions & 51 deletions cmd/lethe/main.go
Original file line number Diff line number Diff line change
@@ -1,66 +1,27 @@
package main

import (
"fmt"
"time"
"os"

"github.com/kuoss/common/logger"
"github.com/kuoss/lethe/config"
"github.com/kuoss/lethe/rotator"
"github.com/kuoss/lethe/router"
"github.com/kuoss/lethe/storage/fileservice"
"github.com/kuoss/lethe/storage/logservice"
"github.com/kuoss/lethe/storage/queryservice"
"github.com/kuoss/lethe/app"
)

var (
Version = "development"

myApp app.IApp
exit = os.Exit
)

func main() {
logger.Infof("💧 Lethe starting... version: %s", Version)

// Load configuration
cfg := mustConfig(Version)

// Initialize services
fileService := mustFileService(cfg)
logService := logservice.New(fileService)
queryService := queryservice.New(logService)

// Start the rotator
startRotator(cfg, fileService)

// Run the router
runRouter(cfg, fileService, queryService)
}

func mustConfig(version string) *config.Config {
cfg, err := config.New(version)
if err != nil {
panic(fmt.Errorf("failed to create new config: %v", err))
logger.Infof("Starting Lethe, version: %s", Version)
if err := myApp.New(Version); err != nil {
logger.Errorf("Failed to create app: %s", err.Error())
exit(1)
}
logger.Infof("Loaded configuration: %v", cfg)
return cfg
}

func mustFileService(cfg *config.Config) *fileservice.FileService {
fileService, err := fileservice.New(cfg)
if err != nil {
logger.Fatalf("Failed to create new file service: %s", err.Error())
}
return fileService
}

func startRotator(cfg *config.Config, fileService *fileservice.FileService) {
rotator := rotator.New(cfg, fileService)
rotator.Start(20 * time.Minute)
logger.Infof("Log rotator started with interval: %v", 20*time.Minute)
}

func runRouter(cfg *config.Config, fileService *fileservice.FileService, queryService *queryservice.QueryService) {
r := router.New(cfg, fileService, queryService)
if err := r.Run(); err != nil {
logger.Fatalf("Failed to run router: %s", err.Error())
if err := myApp.Run(); err != nil {
logger.Errorf("Failed to run app: %s", err.Error())
exit(1)
}
}
64 changes: 38 additions & 26 deletions cmd/lethe/main_test.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,52 @@
package main

import (
"errors"
"testing"

"github.com/kuoss/common/tester"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestMustConfig(t *testing.T) {
version := "test"
cfg := mustConfig(version)
assert.NotEmpty(t, cfg)
assert.Equal(t, version, cfg.Version)
type MockApp struct {
newErr error
runErr error
}

func TestMustFileService(t *testing.T) {
_, cleanup := tester.MustSetupDir(t, map[string]string{
"@/testdata/etc/lethe.main.yaml": "etc/lethe.yaml",
})
defer cleanup()
func (m *MockApp) New(version string) error {
return m.newErr
}

cfg := mustConfig("test")
fileService := mustFileService(cfg)
assert.NotNil(t, fileService, "Expected file service to be non-nil")
func (m *MockApp) Run() error {
return m.runErr
}

func TestStartRotator(t *testing.T) {
_, cleanup := tester.MustSetupDir(t, map[string]string{
"@/testdata/etc/lethe.main.yaml": "etc/lethe.yaml",
func TestMainFunc(t *testing.T) {
originalApp := myApp
originalExit := exit
defer func() {
myApp = originalApp
exit = originalExit
}()

var gotExitCode int
exit = func(code int) {
gotExitCode = code
}

t.Run("ok", func(t *testing.T) {
myApp = &MockApp{}
main()
require.Equal(t, 0, gotExitCode)
})
t.Run("new error", func(t *testing.T) {
myApp = &MockApp{newErr: errors.New("fake new error")}
main()
require.Equal(t, 1, gotExitCode)
})

t.Run("run error", func(t *testing.T) {
myApp = &MockApp{runErr: errors.New("fake run error")}
main()
require.Equal(t, 1, gotExitCode)
})
defer cleanup()

version := "test-version"
cfg := mustConfig(version)
fileService := mustFileService(cfg)
assert.NotPanics(t, func() {
startRotator(cfg, fileService)
}, "Expected startRotator to not panic")
}
Loading

0 comments on commit 2081d13

Please sign in to comment.