From 64907ecc42ea17acbd68ccdd4b32d560e0c673e0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 7 Nov 2024 16:01:03 +0100 Subject: pkg/manager: add test for all HTTP templates It's easy to make mistakes in templates that lead to runtime panics. Catch them during testing. This required to convert some pointers to values for things that must not be nil. Otherwise the randomized test can pass nil for the objects and templates fail. --- pkg/manager/http.go | 60 +++++++++++++++++++++++++++++------------------- pkg/manager/http_test.go | 22 ++++++++++++++++++ 2 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 pkg/manager/http_test.go (limited to 'pkg/manager') diff --git a/pkg/manager/http.go b/pkg/manager/http.go index 76458f75e..38a9b9432 100644 --- a/pkg/manager/http.go +++ b/pkg/manager/http.go @@ -283,17 +283,17 @@ func (serv *HTTPServer) httpVM(w http.ResponseWriter, r *http.Request) { } } -func makeUICrashType(info *BugInfo, startTime time.Time, repros map[string]bool) *UICrashType { - var crashes []*UICrash +func makeUICrashType(info *BugInfo, startTime time.Time, repros map[string]bool) UICrashType { + var crashes []UICrash for _, crash := range info.Crashes { - crashes = append(crashes, &UICrash{ - CrashInfo: crash, + crashes = append(crashes, UICrash{ + CrashInfo: *crash, Active: crash.Time.After(startTime), }) } triaged := reproStatus(info.HasRepro, info.HasCRepro, repros[info.Title], info.ReproAttempts >= MaxReproAttempts) - return &UICrashType{ + return UICrashType{ Description: info.Title, LastTime: info.LastTime, Active: info.LastTime.After(startTime), @@ -336,7 +336,7 @@ func (serv *HTTPServer) httpCorpus(w http.ResponseWriter, r *http.Request) { if data.Call != "" && data.Call != inp.StringCall() { continue } - data.Inputs = append(data.Inputs, &UIInput{ + data.Inputs = append(data.Inputs, UIInput{ Sig: inp.Sig, Short: inp.Prog.String(), Cover: len(inp.Cover), @@ -786,13 +786,13 @@ func (serv *HTTPServer) nowReproducing() map[string]bool { return nil } -func (serv *HTTPServer) collectCrashes(workdir string) ([]*UICrashType, error) { +func (serv *HTTPServer) collectCrashes(workdir string) ([]UICrashType, error) { list, err := serv.CrashStore.BugList() if err != nil { return nil, err } repros := serv.nowReproducing() - var ret []*UICrashType + var ret []UICrashType for _, info := range list { ret = append(ret, makeUICrashType(info, serv.StartTime, repros)) } @@ -875,7 +875,7 @@ type UISummaryData struct { RevisionLink string Expert bool Stats []UIStat - Crashes []*UICrashType + Crashes []UICrashType PatchedOnly *UIDiffTable AffectsBoth *UIDiffTable InProgress *UIDiffTable @@ -913,11 +913,11 @@ type UICrashType struct { Count int Triaged string Strace string - Crashes []*UICrash + Crashes []UICrash } type UICrash struct { - *CrashInfo + CrashInfo Active bool } @@ -943,7 +943,7 @@ type UICallType struct { type UICorpus struct { Call string RawCover bool - Inputs []*UIInput + Inputs []UIInput } type UIInput struct { @@ -952,8 +952,8 @@ type UIInput struct { Cover int } -func createPage(title, body string) *template.Template { - return pages.Create(fmt.Sprintf(` +func createPage(title string, data any, body string) *template.Template { + templ := pages.Create(fmt.Sprintf(` @@ -965,9 +965,23 @@ func createPage(title, body string) *template.Template { %v `, template.HTMLEscaper(title), body)) + templTypes = append(templTypes, templType{ + title: title, + templ: templ, + data: data, + }) + return templ +} + +type templType struct { + title string + templ *template.Template + data any } -var summaryTemplate = createPage("syzkaller", ` +var templTypes []templType + +var summaryTemplate = createPage("syzkaller", UISummaryData{}, ` {{.Name }} syzkaller [config] {{.Revision}} @@ -1084,7 +1098,7 @@ var summaryTemplate = createPage("syzkaller", ` `) -var vmsTemplate = createPage("VMs", ` +var vmsTemplate = createPage("VMs", UIVMData{}, ` @@ -1106,7 +1120,7 @@ var vmsTemplate = createPage("VMs", `
VM Info:
`) -var syscallsTemplate = createPage("syscalls", ` +var syscallsTemplate = createPage("syscalls", UISyscallsData{}, ` @@ -1126,7 +1140,7 @@ var syscallsTemplate = createPage("syscalls", `
Per-syscall coverage:
`) -var crashTemplate = createPage("crash", ` +var crashTemplate = createPage("crash", UICrashType{}, ` {{.Description}} {{if .Triaged}} @@ -1157,7 +1171,7 @@ Report: {{.Triaged}} `) -var corpusTemplate = createPage("corpus", ` +var corpusTemplate = createPage("corpus", UICorpus{}, ` @@ -1190,7 +1204,7 @@ type UIPrio struct { Prio int32 } -var prioTemplate = createPage("syscall priorities", ` +var prioTemplate = createPage("syscall priorities", UIPrioData{}, `
@@ -1216,7 +1230,7 @@ type UIFallbackCall struct { Errnos []int } -var fallbackCoverTemplate = createPage("coverage", ` +var fallbackCoverTemplate = createPage("coverage", UIFallbackCoverData{}, `
Priorities for {{$.Call}}:
@@ -1239,7 +1253,7 @@ type UIRawCallCover struct { UpdateIDs []int } -var rawCoverTemplate = createPage("raw coverage", ` +var rawCoverTemplate = createPage("raw coverage", []UIRawCallCover{}, `
Call
@@ -1271,7 +1285,7 @@ type UIJobInfo struct { Execs int32 } -var jobListTemplate = createPage("job list", ` +var jobListTemplate = createPage("job list", UIJobList{}, `
Raw cover
diff --git a/pkg/manager/http_test.go b/pkg/manager/http_test.go new file mode 100644 index 000000000..a99c9f4a0 --- /dev/null +++ b/pkg/manager/http_test.go @@ -0,0 +1,22 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package manager + +import ( + "io" + "testing" + + "github.com/google/syzkaller/pkg/testutil" +) + +func TestHttpTemplates(t *testing.T) { + for _, typ := range templTypes { + t.Run(typ.title, func(t *testing.T) { + data := testutil.RandValue(t, typ.data) + if err := typ.templ.Execute(io.Discard, data); err != nil { + t.Fatal(err) + } + }) + } +} -- cgit mrf-deployment
{{.Title}} ({{len .Jobs}}):