Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(838)

Unified Diff: dashboard/app/build/test.go

Issue 12180043: code review 12180043: go.tools: add dashboard
Patch Set: diff -r 79ec8d3bcf1d https://code.google.com/p/go/ Created 12 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dashboard/app/build/notify.txt ('k') | dashboard/app/build/ui.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dashboard/app/build/test.go
===================================================================
new file mode 100644
--- /dev/null
+++ b/dashboard/app/build/test.go
@@ -0,0 +1,258 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package build
+
+// TODO(adg): test authentication
+
+import (
+ "appengine"
+ "appengine/datastore"
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "net/url"
+ "strings"
+ "time"
+)
+
+func init() {
+ http.HandleFunc("/buildtest", testHandler)
+}
+
+var testEntityKinds = []string{
+ "Package",
+ "Commit",
+ "Result",
+ "Log",
+}
+
+const testPkg = "code.google.com/p/go.test"
+
+var testPackage = &Package{Name: "Test", Kind: "subrepo", Path: testPkg}
+
+var testPackages = []*Package{
+ {Name: "Go", Path: ""},
+ testPackage,
+}
+
+var tCommitTime = time.Now().Add(-time.Hour * 24 * 7)
+
+func tCommit(hash, parentHash, path string) *Commit {
+ tCommitTime.Add(time.Hour) // each commit should have a different time
+ return &Commit{
+ PackagePath: path,
+ Hash: hash,
+ ParentHash: parentHash,
+ Time: tCommitTime,
+ User: "adg",
+ Desc: "change description " + hash,
+ }
+}
+
+var testRequests = []struct {
+ path string
+ vals url.Values
+ req interface{}
+ res interface{}
+}{
+ // Packages
+ {"/packages?kind=subrepo", nil, nil, []*Package{testPackage}},
+
+ // Go repo
+ {"/commit", nil, tCommit("0001", "0000", ""), nil},
+ {"/commit", nil, tCommit("0002", "0001", ""), nil},
+ {"/commit", nil, tCommit("0003", "0002", ""), nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0001", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0002", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+ // multiple builders
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+ {"/result", nil, &Result{Builder: "linux-amd64", Hash: "0003", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-amd64"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0002"}}},
+
+ // branches
+ {"/commit", nil, tCommit("0004", "0003", ""), nil},
+ {"/commit", nil, tCommit("0005", "0002", ""), nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0005", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0004"}}},
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0004", OK: false}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0003"}}},
+
+ // logs
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+ {"/log/a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", nil, nil, "test"},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+
+ // repeat failure (shouldn't re-send mail)
+ {"/result", nil, &Result{Builder: "linux-386", Hash: "0003", OK: false, Log: "test"}, nil},
+
+ // non-Go repos
+ {"/commit", nil, tCommit("1001", "1000", testPkg), nil},
+ {"/commit", nil, tCommit("1002", "1001", testPkg), nil},
+ {"/commit", nil, tCommit("1003", "1002", testPkg), nil},
+ {"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+ {"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1003", GoHash: "0001", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1002"}}},
+ {"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1002", GoHash: "0001", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1001"}}},
+ {"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0001", OK: true}, nil},
+ {"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0001"}}, nil, nil},
+ {"/todo", url.Values{"kind": {"build-package"}, "builder": {"linux-386"}, "packagePath": {testPkg}, "goHash": {"0002"}}, nil, &Todo{Kind: "build-package", Data: &Commit{Hash: "1003"}}},
+
+ // re-build Go revision for stale subrepos
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, &Todo{Kind: "build-go-commit", Data: &Commit{Hash: "0005"}}},
+ {"/result", nil, &Result{PackagePath: testPkg, Builder: "linux-386", Hash: "1001", GoHash: "0005", OK: false, Log: "boo"}, nil},
+ {"/todo", url.Values{"kind": {"build-go-commit"}, "builder": {"linux-386"}}, nil, nil},
+}
+
+func testHandler(w http.ResponseWriter, r *http.Request) {
+ if !appengine.IsDevAppServer() {
+ fmt.Fprint(w, "These tests must be run under the dev_appserver.")
+ return
+ }
+ c := appengine.NewContext(r)
+ if err := nukeEntities(c, testEntityKinds); err != nil {
+ logErr(w, r, err)
+ return
+ }
+ if r.FormValue("nukeonly") != "" {
+ fmt.Fprint(w, "OK")
+ return
+ }
+
+ for _, p := range testPackages {
+ if _, err := datastore.Put(c, p.Key(c), p); err != nil {
+ logErr(w, r, err)
+ return
+ }
+ }
+
+ for i, t := range testRequests {
+ c.Infof("running test %d %s", i, t.path)
+ errorf := func(format string, args ...interface{}) {
+ fmt.Fprintf(w, "%d %s: ", i, t.path)
+ fmt.Fprintf(w, format, args...)
+ fmt.Fprintln(w)
+ }
+ var body io.ReadWriter
+ if t.req != nil {
+ body = new(bytes.Buffer)
+ json.NewEncoder(body).Encode(t.req)
+ }
+ url := "http://" + domain + t.path
+ if t.vals != nil {
+ url += "?" + t.vals.Encode()
+ }
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ logErr(w, r, err)
+ return
+ }
+ if t.req != nil {
+ req.Method = "POST"
+ }
+ req.Header = r.Header
+ rec := httptest.NewRecorder()
+
+ // Make the request
+ http.DefaultServeMux.ServeHTTP(rec, req)
+
+ if rec.Code != 0 && rec.Code != 200 {
+ errorf(rec.Body.String())
+ return
+ }
+ resp := new(dashResponse)
+
+ // If we're expecting a *Todo value,
+ // prime the Response field with a Todo and a Commit inside it.
+ if _, ok := t.res.(*Todo); ok {
+ resp.Response = &Todo{Data: &Commit{}}
+ }
+
+ if strings.HasPrefix(t.path, "/log/") {
+ resp.Response = rec.Body.String()
+ } else {
+ err := json.NewDecoder(rec.Body).Decode(resp)
+ if err != nil {
+ errorf("decoding response: %v", err)
+ return
+ }
+ }
+ if e, ok := t.res.(string); ok {
+ g, ok := resp.Response.(string)
+ if !ok {
+ errorf("Response not string: %T", resp.Response)
+ return
+ }
+ if g != e {
+ errorf("response mismatch: got %q want %q", g, e)
+ return
+ }
+ }
+ if e, ok := t.res.(*Todo); ok {
+ g, ok := resp.Response.(*Todo)
+ if !ok {
+ errorf("Response not *Todo: %T", resp.Response)
+ return
+ }
+ if e.Data == nil && g.Data != nil {
+ errorf("Response.Data should be nil, got: %v", g.Data)
+ return
+ }
+ if g.Data == nil {
+ errorf("Response.Data is nil, want: %v", e.Data)
+ return
+ }
+ gd, ok := g.Data.(*Commit)
+ if !ok {
+ errorf("Response.Data not *Commit: %T", g.Data)
+ return
+ }
+ if eh := e.Data.(*Commit).Hash; eh != gd.Hash {
+ errorf("hashes don't match: got %q, want %q", gd.Hash, eh)
+ return
+ }
+ }
+ if t.res == nil && resp.Response != nil {
+ errorf("response mismatch: got %q expected <nil>",
+ resp.Response)
+ return
+ }
+ }
+ fmt.Fprint(w, "PASS\nYou should see only one mail notification (for 0003/linux-386) in the dev_appserver logs.")
+}
+
+func nukeEntities(c appengine.Context, kinds []string) error {
+ if !appengine.IsDevAppServer() {
+ return errors.New("can't nuke production data")
+ }
+ var keys []*datastore.Key
+ for _, kind := range kinds {
+ q := datastore.NewQuery(kind).KeysOnly()
+ for t := q.Run(c); ; {
+ k, err := t.Next(nil)
+ if err == datastore.Done {
+ break
+ }
+ if err != nil {
+ return err
+ }
+ keys = append(keys, k)
+ }
+ }
+ return datastore.DeleteMulti(c, keys)
+}
« no previous file with comments | « dashboard/app/build/notify.txt ('k') | dashboard/app/build/ui.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b