Skip to content

Commit e1dbf9c

Browse files
committed
test: add coverage baseline and unit tests
1 parent b0257d5 commit e1dbf9c

File tree

7 files changed

+170
-18
lines changed

7 files changed

+170
-18
lines changed

src/app/app.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import (
2020
)
2121

2222
type App struct {
23-
params *param.Params
24-
server *http.Server
25-
cache *lru.TwoQueueCache
23+
params *param.Params
24+
server *http.Server
25+
cache *lru.TwoQueueCache
26+
listenAndServe func(*http.Server) error
2627
}
2728

2829
type ResponseItem struct {
@@ -42,6 +43,10 @@ const (
4243
)
4344

4445
func NewApp(params *param.Params) App {
46+
return NewAppWithListenAndServe(params, nil)
47+
}
48+
49+
func NewAppWithListenAndServe(params *param.Params, listenAndServe func(*http.Server) error) App {
4550
var cache *lru.TwoQueueCache = nil
4651
var err error
4752

@@ -52,7 +57,18 @@ func NewApp(params *param.Params) App {
5257
}
5358
}
5459

55-
return App{params: params, server: nil, cache: cache}
60+
if listenAndServe == nil {
61+
listenAndServe = func(server *http.Server) error {
62+
return server.ListenAndServe()
63+
}
64+
}
65+
66+
return App{
67+
params: params,
68+
server: nil,
69+
cache: cache,
70+
listenAndServe: listenAndServe,
71+
}
5672
}
5773

5874
func (app *App) ShouldSkipCompression(filePath string) bool {
@@ -312,7 +328,7 @@ func (app *App) Listen() {
312328
}
313329

314330
fmt.Printf("Server listening on http://%s\n", app.server.Addr)
315-
err := app.server.ListenAndServe()
331+
err := app.listenAndServe(app.server)
316332
if err != nil {
317333
panic(err)
318334
}

src/main.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,21 @@ import (
88
"os"
99
)
1010

11-
func main() {
11+
type AppRunner interface {
12+
CompressFiles()
13+
Listen()
14+
}
15+
16+
func defaultNewRunner(params *param.Params) AppRunner {
17+
newApp := app.NewApp(params)
18+
return &newApp
19+
}
20+
21+
func run(args []string, newRunner func(*param.Params) AppRunner) error {
22+
if newRunner == nil {
23+
newRunner = defaultNewRunner
24+
}
25+
1226
cliApp := &cli.App{
1327
Name: "spa-to-http",
1428
Flags: param.Flags,
@@ -18,15 +32,19 @@ func main() {
1832
return err
1933
}
2034

21-
newApp := app.NewApp(params)
35+
newApp := newRunner(params)
2236
go newApp.CompressFiles()
2337
newApp.Listen()
2438

2539
return nil
2640
},
2741
}
2842

29-
if err := cliApp.Run(os.Args); err != nil {
43+
return cliApp.Run(args)
44+
}
45+
46+
func main() {
47+
if err := run(os.Args, nil); err != nil {
3048
log.Fatal(err)
3149
}
3250
}

src/param/param.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ type Params struct {
106106
}
107107

108108
func ContextToParams(c *cli.Context) (*Params, error) {
109-
directory, err := filepath.Abs(c.String("directory"))
109+
return ContextToParamsWithAbs(c, filepath.Abs)
110+
}
111+
112+
func ContextToParamsWithAbs(c *cli.Context, abs func(string) (string, error)) (*Params, error) {
113+
directory, err := abs(c.String("directory"))
110114
if err != nil {
111115
return nil, err
112116
}

src/param/param_test.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package param_test
22

33
import (
44
"context"
5+
"errors"
56
"flag"
67
"go-http-server/param"
78
"path/filepath"
9+
"reflect"
810
"testing"
911

1012
"github.com/urfave/cli/v2"
@@ -20,9 +22,12 @@ func TestContextToParams(t *testing.T) {
2022
e_directory := "example dir"
2123
e_cache_control_max_age := int64(2048)
2224
e_spa := true
23-
e_ignore_cache_control_paths := "example path1"
25+
e_ignore_cache_control_paths := []string{"example path1", "example path2"}
2426
e_cache := true
2527
e_cache_buffer := 64
28+
e_logger := true
29+
e_log_pretty := true
30+
e_no_compress := []string{".map", ".zip"}
2631

2732
f.String("address", e_adress, "")
2833
f.Int("port", e_port, "")
@@ -32,9 +37,12 @@ func TestContextToParams(t *testing.T) {
3237
f.String("directory", e_directory, "")
3338
f.Int64("cache-max-age", e_cache_control_max_age, "")
3439
f.Bool("spa", e_spa, "")
35-
f.String("ignore-cache-control-paths", e_ignore_cache_control_paths, "")
40+
f.Var(cli.NewStringSlice(e_ignore_cache_control_paths...), "ignore-cache-control-paths", "")
3641
f.Bool("cache", e_cache, "")
3742
f.Int("cache-buffer", e_cache_buffer, "")
43+
f.Bool("logger", e_logger, "")
44+
f.Bool("log-pretty", e_log_pretty, "")
45+
f.Var(cli.NewStringSlice(e_no_compress...), "no-compress", "")
3846

3947
ctx := cli.NewContext(nil, f, nil)
4048
ctx.Context = context.WithValue(context.Background(), "key", "val")
@@ -77,11 +85,9 @@ func TestContextToParams(t *testing.T) {
7785
t.Errorf("Got %t, expected %t", params.SpaMode, e_spa)
7886
}
7987

80-
//TODO
81-
// fmt.Println(params.IgnoreCacheControlPaths)
82-
// if params.IgnoreCacheControlPaths[0] != e_ignore_cache_control_paths {
83-
// t.Errorf("Got %s, expected %s", params.IgnoreCacheControlPaths, e_ignore_cache_control_paths)
84-
// }
88+
if !reflect.DeepEqual(params.IgnoreCacheControlPaths, e_ignore_cache_control_paths) {
89+
t.Errorf("Got %v, expected %v", params.IgnoreCacheControlPaths, e_ignore_cache_control_paths)
90+
}
8591

8692
if params.CacheEnabled != e_cache {
8793
t.Errorf("Got %t, expected %t", params.CacheEnabled, e_cache)
@@ -90,4 +96,38 @@ func TestContextToParams(t *testing.T) {
9096
if params.CacheBuffer != e_cache_buffer {
9197
t.Errorf("Got %d, expected %d", params.CacheBuffer, e_cache_buffer)
9298
}
99+
100+
if params.Logger != e_logger {
101+
t.Errorf("Got %t, expected %t", params.Logger, e_logger)
102+
}
103+
104+
if params.LogPretty != e_log_pretty {
105+
t.Errorf("Got %t, expected %t", params.LogPretty, e_log_pretty)
106+
}
107+
108+
if !reflect.DeepEqual(params.NoCompress, e_no_compress) {
109+
t.Errorf("Got %v, expected %v", params.NoCompress, e_no_compress)
110+
}
111+
}
112+
113+
func TestContextToParamsWithAbsError(t *testing.T) {
114+
f := flag.NewFlagSet("a", flag.ContinueOnError)
115+
f.String("directory", "example", "")
116+
117+
ctx := cli.NewContext(nil, f, nil)
118+
ctx.Context = context.WithValue(context.Background(), "key", "val")
119+
120+
expectedErr := errors.New("abs failed")
121+
params, err := param.ContextToParamsWithAbs(ctx, func(_ string) (string, error) {
122+
return "", expectedErr
123+
})
124+
if err == nil {
125+
t.Fatalf("Expected error, got nil")
126+
}
127+
if !errors.Is(err, expectedErr) {
128+
t.Fatalf("Expected error %v, got %v", expectedErr, err)
129+
}
130+
if params != nil {
131+
t.Fatalf("Expected params to be nil on error, got %v", params)
132+
}
93133
}

src/util/log_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,34 @@ func TestLogRequestHandlerNilOptions(t *testing.T) {
373373
t.Errorf("expected log output, got empty string")
374374
}
375375
}
376+
377+
func TestLogRequestHandlerWithLoggerOverride(t *testing.T) {
378+
var buf bytes.Buffer
379+
logger := slog.New(slog.NewJSONHandler(&buf, nil))
380+
381+
dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
382+
w.WriteHeader(http.StatusOK)
383+
})
384+
385+
handler := LogRequestHandler(dummyHandler, &LogRequestHandlerOptions{
386+
Logger: logger,
387+
})
388+
389+
req := httptest.NewRequest("GET", "/logger-override", nil)
390+
req.RemoteAddr = "127.0.0.1:8080"
391+
wr := httptest.NewRecorder()
392+
handler.ServeHTTP(wr, req)
393+
394+
logged := buf.String()
395+
if len(logged) == 0 {
396+
t.Fatalf("expected log output, got empty string")
397+
}
398+
399+
var logData map[string]interface{}
400+
if err := json.Unmarshal([]byte(logged), &logData); err != nil {
401+
t.Fatalf("failed to parse log output as JSON: %v", err)
402+
}
403+
if path, ok := logData["path"]; !ok || path != "/logger-override" {
404+
t.Errorf("expected path '/logger-override', got %v", path)
405+
}
406+
}

src/util/util.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,19 @@ func GetFileType(path string) FileType {
2828
}
2929

3030
func GetFileWithInfoAndType(path string) (http.File, fs.FileInfo, FileType) {
31+
return GetFileWithInfoAndTypeWithOpener(path, nil)
32+
}
33+
34+
func GetFileWithInfoAndTypeWithOpener(path string, opener func(string, string) (http.File, error)) (http.File, fs.FileInfo, FileType) {
35+
if opener == nil {
36+
opener = func(dirPath, fileName string) (http.File, error) {
37+
fsDir := http.Dir(dirPath)
38+
return fsDir.Open(fileName)
39+
}
40+
}
41+
3142
dirPath, fileName := filepath.Split(path)
32-
fsDir := http.Dir(dirPath)
33-
file, err := fsDir.Open(fileName)
43+
file, err := opener(dirPath, fileName)
3444

3545
if err != nil {
3646
return nil, nil, FileTypeNotExists

src/util/util_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package util_test
22

33
import (
4+
"errors"
45
"go-http-server/util"
6+
"io"
7+
"io/fs"
8+
"net/http"
59
"testing"
610
)
711

@@ -58,3 +62,32 @@ func TestGetFileType(t *testing.T) {
5862
}
5963
}
6064
}
65+
66+
type badStatFile struct{}
67+
68+
func (f *badStatFile) Close() error { return nil }
69+
func (f *badStatFile) Read(_ []byte) (int, error) { return 0, io.EOF }
70+
func (f *badStatFile) Seek(_ int64, _ int) (int64, error) { return 0, nil }
71+
func (f *badStatFile) Readdir(_ int) ([]fs.FileInfo, error) {
72+
return nil, nil
73+
}
74+
func (f *badStatFile) Stat() (fs.FileInfo, error) {
75+
return nil, errors.New("stat failed")
76+
}
77+
78+
func TestGetFileWithInfoAndTypeWithOpenerStatError(t *testing.T) {
79+
opener := func(_, _ string) (http.File, error) {
80+
return &badStatFile{}, nil
81+
}
82+
83+
file, info, fileType := util.GetFileWithInfoAndTypeWithOpener("irrelevant", opener)
84+
if file != nil {
85+
t.Errorf("Expected file = nil, got %v", file)
86+
}
87+
if info != nil {
88+
t.Errorf("Expected info = nil, got %v", info)
89+
}
90+
if fileType != util.FileTypeNotExists {
91+
t.Errorf("Expected FileTypeNotExists, got %v", fileType)
92+
}
93+
}

0 commit comments

Comments
 (0)