Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: fuzzer/go/frontend/main.go

Issue 1419793011: Add front page of Fuzzer (Closed) Base URL: https://skia.googlesource.com/buildbot@file
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « fuzzer/elements.html ('k') | fuzzer/go/fuzz/stacktrace.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 package main 1 package main
2 2
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "flag" 5 "flag"
6 "fmt" 6 "fmt"
7 » htemplate "html/template" 7 » "html/template"
8 » "math/rand"
9 "net/http" 8 "net/http"
10 "os"
11 "path/filepath" 9 "path/filepath"
12 » "runtime" 10 )
13 » "time" 11
14 12 import (
15 "github.com/gorilla/mux" 13 "github.com/gorilla/mux"
16 metrics "github.com/rcrowley/go-metrics"
17 "github.com/skia-dev/glog" 14 "github.com/skia-dev/glog"
18 » "go.skia.org/infra/fuzzer/go/config" 15 )
19 » "go.skia.org/infra/go/auth" 16
17 import (
18 » "go.skia.org/infra/fuzzer/go/fuzz"
20 "go.skia.org/infra/go/common" 19 "go.skia.org/infra/go/common"
21 "go.skia.org/infra/go/login" 20 "go.skia.org/infra/go/login"
22 "go.skia.org/infra/go/metadata" 21 "go.skia.org/infra/go/metadata"
22 "go.skia.org/infra/go/skiaversion"
23 "go.skia.org/infra/go/util" 23 "go.skia.org/infra/go/util"
24 "google.golang.org/api/storage/v1"
25 )
26
27 var (
28 // indexTemplate is the main index.html page we serve.
29 indexTemplate *htemplate.Template = nil
30
31 requestsCounter = metrics.NewRegisteredCounter("request s", metrics.DefaultRegistry)
32 router *mux.Router = mux.NewRouter()
33 client *http.Client = nil
34 store *storage.Service = nil
35 )
36
37 // Command line flags.
38 var (
39 configFilename = flag.String("config", "fuzzer.toml", "Configuration fil ename")
40 ) 24 )
41 25
42 const ( 26 const (
43 // OAUTH2_CALLBACK_PATH is callback endpoint used for the Oauth2 flow. 27 // OAUTH2_CALLBACK_PATH is callback endpoint used for the Oauth2 flow.
44 OAUTH2_CALLBACK_PATH = "/oauth2callback/" 28 OAUTH2_CALLBACK_PATH = "/oauth2callback/"
45 ) 29 )
46 30
31 var (
32 // indexTemplate is the main index.html page we serve.
33 indexTemplate *template.Template = nil
34 detailsTemplate *template.Template = nil
35 )
36
37 // Command line flags.
38 var (
39 graphiteServer = flag.String("graphite_server", "localhost:2003", "Where is Graphite metrics ingestion server running.")
40 host = flag.String("host", "localhost", "HTTP service host")
41 port = flag.String("port", ":80", "HTTP service port (e.g., ': 8002')")
42 local = flag.Bool("local", false, "Running locally if true. As opposed to in production.")
43 resourcesDir = flag.String("resources_dir", "", "The directory to find templates, JS, and CSS files. If blank the current directory will be used.")
44
45 authWhiteList = flag.String("auth_whitelist", login.DEFAULT_DOMAIN_WHITE LIST, "White space separated list of domains and email addresses that are allowe d to login.")
46 redirectURL = flag.String("redirect_url", "https://fuzzer.skia.org/oau th2callback/", "OAuth2 redirect url. Only used when local=false.")
47 )
48
47 func Init() { 49 func Init() {
50 reloadTemplates()
51 }
52
53 func reloadTemplates() {
54 indexTemplate = template.Must(template.ParseFiles(
55 filepath.Join(*resourcesDir, "templates/index.html"),
56 filepath.Join(*resourcesDir, "templates/header.html"),
57 ))
58 }
59
60 func main() {
48 defer common.LogPanic() 61 defer common.LogPanic()
49 62 » // Calls flag.Parse()
50 » rand.Seed(time.Now().UnixNano()) 63 » common.InitWithMetrics("fuzzer", graphiteServer)
51 64
52 » common.InitWithMetricsCB("fuzzer", func() string {
53 » » common.DecodeTomlFile(*configFilename, &config.Config)
54 » » return config.Config.FrontEnd.GraphiteServer
55 » })
56
57 » if config.Config.Common.ResourcePath == "" {
58 » » _, filename, _, _ := runtime.Caller(0)
59 » » config.Config.Common.ResourcePath = filepath.Join(filepath.Dir(f ilename), "../..")
60 » }
61
62 » path, err := filepath.Abs(config.Config.Common.ResourcePath)
63 » if err != nil {
64 » » glog.Fatalf("Couldn't get absolute path to fuzzer resources: %s" , err)
65 » }
66 » if err := os.Chdir(path); err != nil {
67 » » glog.Fatal(err)
68 » }
69
70 » indexTemplate = htemplate.Must(htemplate.ParseFiles(
71 » » filepath.Join(path, "templates/index.html"),
72 » » filepath.Join(path, "templates/header.html"),
73 » » filepath.Join(path, "templates/titlebar.html"),
74 » » filepath.Join(path, "templates/footer.html"),
75 » ))
76
77 » if client, err = auth.NewClient(config.Config.Common.DoOAuth, config.Con fig.Common.OAuthCacheFile, storage.DevstorageFullControlScope); err != nil {
78 » » glog.Fatalf("Failed to create authenticated HTTP client: %s", er r)
79 » }
80
81 » if store, err = storage.New(client); err != nil {
82 » » glog.Fatalf("Failed to create storage service client: %s", err)
83 » }
84 }
85
86 type IndexContext struct {
87 » LoadFuzzListURL string
88 }
89
90 func getURL(router *mux.Router, name string, pairs ...string) string {
91 » route := router.Get(name)
92 » if route == nil {
93 » » glog.Fatalf("Couldn't find any route named %s", name)
94 » }
95
96 » routeURL, err := route.URL(pairs...)
97 » if err != nil {
98 » » glog.Fatalf("Couldn't resolve route %s into a URL", routeURL)
99 » }
100
101 » return routeURL.String()
102 }
103
104 func mainHandler(w http.ResponseWriter, r *http.Request) {
105 » glog.Infof("Main Handler: %q\n", r.URL.Path)
106 » requestsCounter.Inc(1)
107 » if r.Method == "GET" {
108 » » // Expand the template.
109 » » w.Header().Set("Content-Type", "text/html")
110 » » fuzzListURL := getURL(router, "fuzzListHandler")
111 » » context := IndexContext{
112 » » » fuzzListURL,
113 » » }
114 » » if err := indexTemplate.Execute(w, context); err != nil {
115 » » » glog.Errorf("Failed to expand template: %q\n", err)
116 » » }
117 » }
118 }
119
120 // makeResourceHandler creates a static file handler that sets a caching policy.
121 func makeResourceHandler() func(http.ResponseWriter, *http.Request) {
122 » fileServer := http.FileServer(http.Dir(config.Config.Common.ResourcePath ))
123 » return func(w http.ResponseWriter, r *http.Request) {
124 » » w.Header().Add("Cache-Control", string(300))
125 » » fileServer.ServeHTTP(w, r)
126 » }
127 }
128
129 func getFuzzes(baseDir string) []string {
130 » results := []string{}
131 » glog.Infof("Opening bucket/directory: %s/%s", config.Config.Common.FuzzO utputGSBucket, baseDir)
132
133 » req := store.Objects.List(config.Config.Common.FuzzOutputGSBucket).Prefi x(baseDir + "/").Delimiter("/")
134 » for req != nil {
135 » » resp, err := req.Do()
136 » » if err != nil {
137 » » » return results
138 » » }
139 » » for _, result := range resp.Prefixes {
140 » » » results = append(results, result[len(baseDir)+1:len(resu lt)-1])
141 » » }
142 » » if len(resp.NextPageToken) > 0 {
143 » » » req.PageToken(resp.NextPageToken)
144 » » } else {
145 » » » req = nil
146 » » }
147 » }
148 » return results
149 }
150
151 func fuzzListHandler(w http.ResponseWriter, r *http.Request) {
152 » if err := r.ParseForm(); err != nil {
153 » » util.ReportError(w, r, err, "Failed to parse form data.")
154 » » return
155 » }
156
157 » w.Header().Set("Content-Type", "application/json")
158 » enc := json.NewEncoder(w)
159
160 » fuzzes := []string{}
161
162 » failed := r.FormValue("failed")
163 » passed := r.FormValue("passed")
164
165 » if failed == "true" {
166 » » fuzzes = append(fuzzes, getFuzzes("failed")...)
167 » }
168 » if passed == "true" {
169 » » fuzzes = append(fuzzes, getFuzzes("working")...)
170 » }
171
172 » if err := enc.Encode(fuzzes); err != nil {
173 » » glog.Errorf("Failed to write or encode output: %s", err)
174 » }
175 }
176
177 func main() {
178 » flag.Parse()
179 Init() 65 Init()
180 66
181 » // Set up login 67 » setupOAuth()
68
69 » runServer()
70 }
71
72 func setupOAuth() {
182 var cookieSalt = "notverysecret" 73 var cookieSalt = "notverysecret"
74 // This clientID and clientSecret are only used for setting up a local s erver.
75 // Production id and secrets are in metadata and will be loaded from the re.
183 var clientID = "31977622648-ubjke2f3staq6ouas64r31h8f8tcbiqp.apps.google usercontent.com" 76 var clientID = "31977622648-ubjke2f3staq6ouas64r31h8f8tcbiqp.apps.google usercontent.com"
184 var clientSecret = "rK-kRY71CXmcg0v9I9KIgWci" 77 var clientSecret = "rK-kRY71CXmcg0v9I9KIgWci"
185 » var useRedirectURL = fmt.Sprintf("http://localhost%s/oauth2callback/", c onfig.Config.FrontEnd.Port) 78 » var useRedirectURL = fmt.Sprintf("http://localhost%s/oauth2callback/", * port)
186 » if !config.Config.Common.Local { 79 » if !*local {
187 cookieSalt = metadata.Must(metadata.ProjectGet(metadata.COOKIESA LT)) 80 cookieSalt = metadata.Must(metadata.ProjectGet(metadata.COOKIESA LT))
188 clientID = metadata.Must(metadata.ProjectGet(metadata.CLIENT_ID) ) 81 clientID = metadata.Must(metadata.ProjectGet(metadata.CLIENT_ID) )
189 clientSecret = metadata.Must(metadata.ProjectGet(metadata.CLIENT _SECRET)) 82 clientSecret = metadata.Must(metadata.ProjectGet(metadata.CLIENT _SECRET))
190 » » useRedirectURL = config.Config.FrontEnd.RedirectURL 83 » » useRedirectURL = *redirectURL
191 » } 84 » }
192 85 » login.Init(clientID, clientSecret, useRedirectURL, cookieSalt, login.DEF AULT_SCOPE, *authWhiteList, *local)
193 » login.Init(clientID, clientSecret, useRedirectURL, cookieSalt, login.DEF AULT_SCOPE, login.DEFAULT_DOMAIN_WHITELIST, config.Config.Common.Local) 86 }
194 87
195 » // Set up the login related resources. 88 func runServer() {
196 » router.HandleFunc(OAUTH2_CALLBACK_PATH, login.OAuth2CallbackHandler) 89 » serverURL := "https://" + *host
197 » router.HandleFunc("/loginstatus/", login.StatusHandler) 90 » if *local {
198 » router.HandleFunc("/logout/", login.LogoutHandler) 91 » » serverURL = "http://" + *host + *port
199 92 » }
200 » router.HandleFunc("/", mainHandler) 93
201 » router.HandleFunc("/failed", mainHandler) 94 » r := mux.NewRouter()
202 » router.HandleFunc("/passed", mainHandler) 95 » r.PathPrefix("/res/").HandlerFunc(util.MakeResourceHandler(*resourcesDir ))
203 » router.PathPrefix("/res/").HandlerFunc(makeResourceHandler()) 96
204 97 » r.HandleFunc(OAUTH2_CALLBACK_PATH, login.OAuth2CallbackHandler)
205 » jsonRouter := router.PathPrefix("/_").Subrouter() 98 » r.HandleFunc("/", indexHandler)
206 » jsonRouter.HandleFunc("/list", fuzzListHandler).Name("fuzzListHandler") 99 » r.HandleFunc("/details", detailHandler)
207 100 » r.HandleFunc("/loginstatus/", login.StatusHandler)
208 » rootHandler := util.LoggingGzipRequestResponse(router) 101 » r.HandleFunc("/logout/", login.LogoutHandler)
209 » if config.Config.FrontEnd.ForceLogin { 102 » r.HandleFunc("/json/version", skiaversion.JsonHandler)
210 » » rootHandler = login.ForceAuth(rootHandler, OAUTH2_CALLBACK_PATH) 103 » r.HandleFunc("/json/fuzz-list", fuzzListHandler)
211 » } 104
105 » rootHandler := login.ForceAuth(util.LoggingGzipRequestResponse(r), OAUTH 2_CALLBACK_PATH)
212 106
213 http.Handle("/", rootHandler) 107 http.Handle("/", rootHandler)
214 108 » glog.Infof("Ready to serve on %s", serverURL)
215 » glog.Fatal(http.ListenAndServe(config.Config.FrontEnd.Port, nil)) 109 » glog.Fatal(http.ListenAndServe(*port, nil))
216 } 110 }
111
112 func indexHandler(w http.ResponseWriter, r *http.Request) {
113 » if *local {
114 » » reloadTemplates()
115 » }
116
117 » w.Header().Set("Content-Type", "text/html")
118
119 » if err := indexTemplate.Execute(w, nil); err != nil {
120 » » glog.Errorf("Failed to write or encode output: %s", err)
121 » }
122 }
123
124 func detailHandler(w http.ResponseWriter, r *http.Request) {
125 » if *local {
126 » » reloadTemplates()
127 » }
128
129 » w.Header().Set("Content-Type", "text/html")
130
131 » if err := detailsTemplate.Execute(w, nil); err != nil {
132 » » glog.Errorf("Failed to write or encode output: %s", err)
133 » }
134 }
135
136 type fuzzReport []fuzzReportFile
137
138 type fuzzReportFile struct {
139 » FileName string `json:"fileName"`
140 » BinaryCount int `json:"binaryCount"`
141 » ApiCount int `json:"apiCount"`
142 » Functions []fuzzReportFunction `json:"byFunction"`
143 }
144
145 type fuzzReportFunction struct {
146 » FunctionName string `json:"functionName"`
147 » BinaryCount int `json:"binaryCount"`
148 » ApiCount int `json:"apiCount"`
149 » LineNumbers []fuzzReportLineNumber `json:"byLineNumber"`
150 }
151
152 type fuzzReportLineNumber struct {
153 » LineNumber int `json:"lineNumber"`
154 » BinaryCount int `json:"binaryCount"`
155 » ApiCount int `json:"apiCount"`
156 » BinaryDetails []fuzzReportBinary `json:"binaryReports"`
157 }
158
159 // We make this intermediate struct so we can control the json names and disenta gle the backend structure from what is displayed/visualized
160 type fuzzReportBinary struct {
161 » DebugStackTrace fuzz.StackTrace `json:"debugStackTrace"`
162 » ReleaseStackTrace fuzz.StackTrace `json:"releaseStackTrace"`
163 » HumanReadableFlags []string `json:"flags"`
164 » BadBinaryName string `json:"binaryName"`
165 » BinaryType string `json:"binaryType"`
166 }
167
168 func fuzzListHandler(w http.ResponseWriter, r *http.Request) {
169 » w.Header().Set("Content-Type", "application/json")
170
171 » mockFuzzes := fuzzReport{
172 » » {
173 » » » "foo.h", 30, 0, []fuzzReportFunction{
174 » » » » {
175 » » » » » "frizzle()", 18, 0, []fuzzReportLineNumb er{
176 » » » » » » {
177 » » » » » » » 64, 17, 0, []fuzzReportB inary{},
178 » » » » » » },
179 » » » » » » {
180 » » » » » » » 69, 1, 0, []fuzzReportBi nary{},
181 » » » » » » },
182 » » » » » },
183 » » » » }, {
184 » » » » » "zizzle()", 12, 0, []fuzzReportLineNumbe r{
185 » » » » » » {
186 » » » » » » » 123, 12, 0, []fuzzReport Binary{},
187 » » » » » » },
188 » » » » » },
189 » » » » },
190 » » » },
191 » » }, {
192 » » » "bar.h", 15, 3, []fuzzReportFunction{
193 » » » » {
194 » » » » » "frizzle()", 15, 3, []fuzzReportLineNumb er{
195 » » » » » » {
196 » » » » » » » 566, 15, 2, []fuzzReport Binary{},
197 » » » » » » },
198 » » » » » » {
199 » » » » » » » 568, 0, 1, []fuzzReportB inary{},
200 » » » » » » },
201 » » » » » },
202 » » » » },
203 » » » },
204 » » },
205 » }
206
207 » if err := json.NewEncoder(w).Encode(mockFuzzes); err != nil {
208 » » glog.Errorf("Failed to write or encode output: %s", err)
209 » » return
210 » }
211 }
OLDNEW
« no previous file with comments | « fuzzer/elements.html ('k') | fuzzer/go/fuzz/stacktrace.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698