~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/Azure/azure-sdk-for-go/core/http/cgi/matryoshka_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2011 The Go Authors. All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
// Tests a Go CGI program running under a Go CGI host process.
 
6
// Further, the two programs are the same binary, just checking
 
7
// their environment to figure out what mode to run in.
 
8
 
 
9
package cgi
 
10
 
 
11
import (
 
12
        "bytes"
 
13
        "errors"
 
14
        "fmt"
 
15
        "io"
 
16
        "net/http"
 
17
        "net/http/httptest"
 
18
        "os"
 
19
        "runtime"
 
20
        "testing"
 
21
        "time"
 
22
)
 
23
 
 
24
// This test is a CGI host (testing host.go) that runs its own binary
 
25
// as a child process testing the other half of CGI (child.go).
 
26
func TestHostingOurselves(t *testing.T) {
 
27
        if runtime.GOOS == "nacl" {
 
28
                t.Skip("skipping on nacl")
 
29
        }
 
30
 
 
31
        h := &Handler{
 
32
                Path: os.Args[0],
 
33
                Root: "/test.go",
 
34
                Args: []string{"-test.run=TestBeChildCGIProcess"},
 
35
        }
 
36
        expectedMap := map[string]string{
 
37
                "test":                  "Hello CGI-in-CGI",
 
38
                "param-a":               "b",
 
39
                "param-foo":             "bar",
 
40
                "env-GATEWAY_INTERFACE": "CGI/1.1",
 
41
                "env-HTTP_HOST":         "example.com",
 
42
                "env-PATH_INFO":         "",
 
43
                "env-QUERY_STRING":      "foo=bar&a=b",
 
44
                "env-REMOTE_ADDR":       "1.2.3.4",
 
45
                "env-REMOTE_HOST":       "1.2.3.4",
 
46
                "env-REQUEST_METHOD":    "GET",
 
47
                "env-REQUEST_URI":       "/test.go?foo=bar&a=b",
 
48
                "env-SCRIPT_FILENAME":   os.Args[0],
 
49
                "env-SCRIPT_NAME":       "/test.go",
 
50
                "env-SERVER_NAME":       "example.com",
 
51
                "env-SERVER_PORT":       "80",
 
52
                "env-SERVER_SOFTWARE":   "go",
 
53
        }
 
54
        replay := runCgiTest(t, h, "GET /test.go?foo=bar&a=b HTTP/1.0\nHost: example.com\n\n", expectedMap)
 
55
 
 
56
        if expected, got := "text/html; charset=utf-8", replay.Header().Get("Content-Type"); got != expected {
 
57
                t.Errorf("got a Content-Type of %q; expected %q", got, expected)
 
58
        }
 
59
        if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
 
60
                t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
 
61
        }
 
62
}
 
63
 
 
64
type customWriterRecorder struct {
 
65
        w io.Writer
 
66
        *httptest.ResponseRecorder
 
67
}
 
68
 
 
69
func (r *customWriterRecorder) Write(p []byte) (n int, err error) {
 
70
        return r.w.Write(p)
 
71
}
 
72
 
 
73
type limitWriter struct {
 
74
        w io.Writer
 
75
        n int
 
76
}
 
77
 
 
78
func (w *limitWriter) Write(p []byte) (n int, err error) {
 
79
        if len(p) > w.n {
 
80
                p = p[:w.n]
 
81
        }
 
82
        if len(p) > 0 {
 
83
                n, err = w.w.Write(p)
 
84
                w.n -= n
 
85
        }
 
86
        if w.n == 0 {
 
87
                err = errors.New("past write limit")
 
88
        }
 
89
        return
 
90
}
 
91
 
 
92
// If there's an error copying the child's output to the parent, test
 
93
// that we kill the child.
 
94
func TestKillChildAfterCopyError(t *testing.T) {
 
95
        if runtime.GOOS == "nacl" {
 
96
                t.Skip("skipping on nacl")
 
97
        }
 
98
 
 
99
        defer func() { testHookStartProcess = nil }()
 
100
        proc := make(chan *os.Process, 1)
 
101
        testHookStartProcess = func(p *os.Process) {
 
102
                proc <- p
 
103
        }
 
104
 
 
105
        h := &Handler{
 
106
                Path: os.Args[0],
 
107
                Root: "/test.go",
 
108
                Args: []string{"-test.run=TestBeChildCGIProcess"},
 
109
        }
 
110
        req, _ := http.NewRequest("GET", "http://example.com/test.cgi?write-forever=1", nil)
 
111
        rec := httptest.NewRecorder()
 
112
        var out bytes.Buffer
 
113
        const writeLen = 50 << 10
 
114
        rw := &customWriterRecorder{&limitWriter{&out, writeLen}, rec}
 
115
 
 
116
        donec := make(chan bool, 1)
 
117
        go func() {
 
118
                h.ServeHTTP(rw, req)
 
119
                donec <- true
 
120
        }()
 
121
 
 
122
        select {
 
123
        case <-donec:
 
124
                if out.Len() != writeLen || out.Bytes()[0] != 'a' {
 
125
                        t.Errorf("unexpected output: %q", out.Bytes())
 
126
                }
 
127
        case <-time.After(5 * time.Second):
 
128
                t.Errorf("timeout. ServeHTTP hung and didn't kill the child process?")
 
129
                select {
 
130
                case p := <-proc:
 
131
                        p.Kill()
 
132
                        t.Logf("killed process")
 
133
                default:
 
134
                        t.Logf("didn't kill process")
 
135
                }
 
136
        }
 
137
}
 
138
 
 
139
// Test that a child handler writing only headers works.
 
140
// golang.org/issue/7196
 
141
func TestChildOnlyHeaders(t *testing.T) {
 
142
        if runtime.GOOS == "nacl" {
 
143
                t.Skip("skipping on nacl")
 
144
        }
 
145
 
 
146
        h := &Handler{
 
147
                Path: os.Args[0],
 
148
                Root: "/test.go",
 
149
                Args: []string{"-test.run=TestBeChildCGIProcess"},
 
150
        }
 
151
        expectedMap := map[string]string{
 
152
                "_body": "",
 
153
        }
 
154
        replay := runCgiTest(t, h, "GET /test.go?no-body=1 HTTP/1.0\nHost: example.com\n\n", expectedMap)
 
155
        if expected, got := "X-Test-Value", replay.Header().Get("X-Test-Header"); got != expected {
 
156
                t.Errorf("got a X-Test-Header of %q; expected %q", got, expected)
 
157
        }
 
158
}
 
159
 
 
160
// golang.org/issue/7198
 
161
func Test500WithNoHeaders(t *testing.T)     { want500Test(t, "/immediate-disconnect") }
 
162
func Test500WithNoContentType(t *testing.T) { want500Test(t, "/no-content-type") }
 
163
func Test500WithEmptyHeaders(t *testing.T)  { want500Test(t, "/empty-headers") }
 
164
 
 
165
func want500Test(t *testing.T, path string) {
 
166
        h := &Handler{
 
167
                Path: os.Args[0],
 
168
                Root: "/test.go",
 
169
                Args: []string{"-test.run=TestBeChildCGIProcess"},
 
170
        }
 
171
        expectedMap := map[string]string{
 
172
                "_body": "",
 
173
        }
 
174
        replay := runCgiTest(t, h, "GET "+path+" HTTP/1.0\nHost: example.com\n\n", expectedMap)
 
175
        if replay.Code != 500 {
 
176
                t.Errorf("Got code %d; want 500", replay.Code)
 
177
        }
 
178
}
 
179
 
 
180
type neverEnding byte
 
181
 
 
182
func (b neverEnding) Read(p []byte) (n int, err error) {
 
183
        for i := range p {
 
184
                p[i] = byte(b)
 
185
        }
 
186
        return len(p), nil
 
187
}
 
188
 
 
189
// Note: not actually a test.
 
190
func TestBeChildCGIProcess(t *testing.T) {
 
191
        if os.Getenv("REQUEST_METHOD") == "" {
 
192
                // Not in a CGI environment; skipping test.
 
193
                return
 
194
        }
 
195
        switch os.Getenv("REQUEST_URI") {
 
196
        case "/immediate-disconnect":
 
197
                os.Exit(0)
 
198
        case "/no-content-type":
 
199
                fmt.Printf("Content-Length: 6\n\nHello\n")
 
200
                os.Exit(0)
 
201
        case "/empty-headers":
 
202
                fmt.Printf("\nHello")
 
203
                os.Exit(0)
 
204
        }
 
205
        Serve(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
 
206
                rw.Header().Set("X-Test-Header", "X-Test-Value")
 
207
                req.ParseForm()
 
208
                if req.FormValue("no-body") == "1" {
 
209
                        return
 
210
                }
 
211
                if req.FormValue("write-forever") == "1" {
 
212
                        io.Copy(rw, neverEnding('a'))
 
213
                        for {
 
214
                                time.Sleep(5 * time.Second) // hang forever, until killed
 
215
                        }
 
216
                }
 
217
                fmt.Fprintf(rw, "test=Hello CGI-in-CGI\n")
 
218
                for k, vv := range req.Form {
 
219
                        for _, v := range vv {
 
220
                                fmt.Fprintf(rw, "param-%s=%s\n", k, v)
 
221
                        }
 
222
                }
 
223
                for _, kv := range os.Environ() {
 
224
                        fmt.Fprintf(rw, "env-%s\n", kv)
 
225
                }
 
226
        }))
 
227
        os.Exit(0)
 
228
}