rig.go (3003B)
1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "net/http" 8 "os" 9 "os/exec" 10 "path" 11 ) 12 13 func main() { 14 if len(os.Args) > 1 && os.Args[1] == "-serve" { 15 serve() 16 } 17 18 err := build() 19 if err != nil { 20 log.Fatal(err) 21 } 22 23 go serve() 24 25 err = runTest() 26 if err != nil { 27 log.Fatal(err) 28 } 29 30 os.Exit(0) 31 } 32 33 func build() error { 34 cmd := exec.Command("make") 35 output, err := cmd.CombinedOutput() 36 if err != nil { 37 return fmt.Errorf("build failed: %v", string(output)) 38 } 39 return nil 40 } 41 42 func runTest() error { 43 cwd, err := os.Getwd() 44 if err != nil { 45 return err 46 } 47 cmd := exec.Command(path.Join(cwd, "test"), "http://localhost:4711") 48 output, err := cmd.CombinedOutput() 49 if err != nil { 50 return fmt.Errorf("Failed to run test: %s", string(output)) 51 } 52 fmt.Print(string(output)) 53 return nil 54 } 55 56 type Handler func(w http.ResponseWriter, r *http.Request) 57 58 func trace(handler Handler) Handler { 59 return func(w http.ResponseWriter, r *http.Request) { 60 log.Printf("%v - %v", r.Method, r.URL) 61 handler(w, r) 62 } 63 } 64 65 func serve() { 66 http.HandleFunc("/get", trace(testGETHandler)) 67 http.HandleFunc("/stress", testGETHandler) 68 http.HandleFunc("/post", trace(testPOSTHandler)) 69 http.HandleFunc("/redirect", trace(testRedirectHandler)) 70 http.HandleFunc("/redirected", trace(redirectedHandler)) 71 log.Fatal(http.ListenAndServe(":4711", nil)) 72 } 73 74 func fail(w http.ResponseWriter, message string) { 75 w.WriteHeader(400) 76 w.Write([]byte(message + "\n")) 77 } 78 79 func ok(w http.ResponseWriter) { 80 w.Write([]byte("OK")) 81 } 82 83 func checkHeader(w http.ResponseWriter, r *http.Request, header string, expected string) bool { 84 actual := r.Header[header] 85 if len(actual) == 0 || actual[0] != expected { 86 fail(w, fmt.Sprintf("Expected header %q to be %q, got %q", header, expected, actual)) 87 return false 88 } 89 return true 90 } 91 92 func testGETHandler(w http.ResponseWriter, r *http.Request) { 93 if r.Method != "GET" { 94 fail(w, fmt.Sprintf("Unexpected method, %q", r.Method)) 95 return 96 } 97 98 if r.ContentLength != 0 { 99 fail(w, "Non-empty body in GET") 100 return 101 } 102 103 if !checkHeader(w, r, "Accept", "naett/testresult") { 104 return 105 } 106 107 if !checkHeader(w, r, "User-Agent", "Naett/1.0") { 108 return 109 } 110 111 ok(w) 112 } 113 114 func testPOSTHandler(w http.ResponseWriter, r *http.Request) { 115 if r.Method != "POST" { 116 fail(w, fmt.Sprintf("Unexpected method, %q", r.Method)) 117 return 118 } 119 120 if r.ContentLength == 0 { 121 fail(w, "Empty body in POST") 122 return 123 } 124 125 if !checkHeader(w, r, "Accept", "naett/testresult") { 126 return 127 } 128 129 if !checkHeader(w, r, "User-Agent", "Naett/1.0") { 130 return 131 } 132 133 bodyBytes, err := io.ReadAll(r.Body) 134 if err != nil { 135 fail(w, err.Error()) 136 } 137 138 body := string(bodyBytes) 139 expectedBody := "TestRequest!" 140 141 if body != expectedBody { 142 fail(w, fmt.Sprintf("Unexpected body: %v", bodyBytes)) 143 } else { 144 ok(w) 145 } 146 } 147 148 func testRedirectHandler(w http.ResponseWriter, _ *http.Request) { 149 w.Header().Add("Location", "/redirected") 150 w.WriteHeader(302) 151 } 152 153 func redirectedHandler(w http.ResponseWriter, _ *http.Request) { 154 w.Write([]byte("Redirected")) 155 }