From 2222a898a19744a3a54326d492a6b33c97d91807 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 4 Sep 2015 02:52:19 +0900 Subject: [PATCH] integration: Add mruby tests --- integration-tests/nghttpx_http1_test.go | 184 ++++++++++++++++++++++++ integration-tests/nghttpx_http2_test.go | 184 ++++++++++++++++++++++++ integration-tests/nghttpx_spdy_test.go | 184 ++++++++++++++++++++++++ integration-tests/req-set-header.rb | 3 + integration-tests/resp-set-header.rb | 3 + integration-tests/return.rb | 6 + 6 files changed, 564 insertions(+) create mode 100644 integration-tests/req-set-header.rb create mode 100644 integration-tests/resp-set-header.rb create mode 100644 integration-tests/return.rb diff --git a/integration-tests/nghttpx_http1_test.go b/integration-tests/nghttpx_http1_test.go index 71aeeb85..c7658eb5 100644 --- a/integration-tests/nghttpx_http1_test.go +++ b/integration-tests/nghttpx_http1_test.go @@ -355,6 +355,120 @@ func TestH1H1Websocket(t *testing.T) { } } +// TestH1H1ReqPhaseSetHeader tests mruby request phase hook +// modifies request header fields. +func TestH1H1ReqPhaseSetHeader(t *testing.T) { + st := newServerTester([]string{"--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { + t.Errorf("User-Agent = %v; want %v", got, want) + } + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1ReqPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } +} + +// TestH1H1ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestH1H1ReqPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestH1H1RespPhaseSetHeader tests mruby response phase hook modifies +// response header fields. +func TestH1H1RespPhaseSetHeader(t *testing.T) { + st := newServerTester([]string{"--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1RespPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + if got, want := res.header.Get("alpha"), "bravo"; got != want { + t.Errorf("alpha = %v; want %v", got, want) + } +} + +// TestH1H1RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestH1H1RespPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H1RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + // TestH1H2ConnectFailure tests that server handles the situation that // connection attempt to HTTP/2 backend failed. func TestH1H2ConnectFailure(t *testing.T) { @@ -547,3 +661,73 @@ func TestH1H2NoVia(t *testing.T) { t.Errorf("Via: %v; want %v", got, want) } } + +// TestH1H2ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestH1H2ReqPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H2ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestH1H2RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestH1H2RespPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1H2RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} diff --git a/integration-tests/nghttpx_http2_test.go b/integration-tests/nghttpx_http2_test.go index 5fe4c3db..41c527f7 100644 --- a/integration-tests/nghttpx_http2_test.go +++ b/integration-tests/nghttpx_http2_test.go @@ -640,6 +640,120 @@ func TestH2H1HeaderFields(t *testing.T) { } } +// TestH2H1ReqPhaseSetHeader tests mruby request phase hook +// modifies request header fields. +func TestH2H1ReqPhaseSetHeader(t *testing.T) { + st := newServerTester([]string{"--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { + t.Errorf("User-Agent = %v; want %v", got, want) + } + }) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1ReqPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } +} + +// TestH2H1ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestH2H1ReqPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestH2H1RespPhaseSetHeader tests mruby response phase hook modifies +// response header fields. +func TestH2H1RespPhaseSetHeader(t *testing.T) { + st := newServerTester([]string{"--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1RespPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + if got, want := res.header.Get("alpha"), "bravo"; got != want { + t.Errorf("alpha = %v; want %v", got, want) + } +} + +// TestH2H1RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestH2H1RespPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H1RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + // TestH2H1Upgrade tests HTTP Upgrade to HTTP/2 func TestH2H1Upgrade(t *testing.T) { st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {}) @@ -875,3 +989,73 @@ func TestH2H2TLSXfp(t *testing.T) { t.Errorf("res.status: %v; want %v", got, want) } } + +// TestH2H2ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestH2H2ReqPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H2ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestH2H2RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestH2H2RespPhaseReturn(t *testing.T) { + st := newServerTester([]string{"--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2H2RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} diff --git a/integration-tests/nghttpx_spdy_test.go b/integration-tests/nghttpx_spdy_test.go index 76d349e8..e0447fad 100644 --- a/integration-tests/nghttpx_spdy_test.go +++ b/integration-tests/nghttpx_spdy_test.go @@ -230,6 +230,120 @@ func TestS3H1InvalidMethod(t *testing.T) { } } +// TestS3H1ReqPhaseSetHeader tests mruby request phase hook +// modifies request header fields. +func TestS3H1ReqPhaseSetHeader(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-phase-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + if got, want := r.Header.Get("User-Agent"), "mruby"; got != want { + t.Errorf("User-Agent = %v; want %v", got, want) + } + }) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1ReqPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } +} + +// TestS3H1ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestS3H1ReqPhaseReturn(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestS3H1RespPhaseSetHeader tests mruby response phase hook modifies +// response header fields. +func TestS3H1RespPhaseSetHeader(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--response-phase-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1RespPhaseSetHeader", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 200; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + if got, want := res.header.Get("alpha"), "bravo"; got != want { + t.Errorf("alpha = %v; want %v", got, want) + } +} + +// TestS3H1RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestS3H1RespPhaseReturn(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H1RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + // TestS3H2ConnectFailure tests that server handles the situation that // connection attempt to HTTP/2 backend failed. func TestS3H2ConnectFailure(t *testing.T) { @@ -250,3 +364,73 @@ func TestS3H2ConnectFailure(t *testing.T) { t.Errorf("status: %v; want %v", got, want) } } + +// TestS3H2ReqPhaseReturn tests mruby request phase hook returns +// custom response. +func TestS3H2ReqPhaseReturn(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--request-phase-file=" + testDir + "/return.rb"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H2ReqPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} + +// TestS3H2RespPhaseReturn tests mruby response phase hook returns +// custom response. +func TestS3H2RespPhaseReturn(t *testing.T) { + st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--response-phase-file=" + testDir + "/return.rb"}, t, noopHandler) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3H2RespPhaseReturn", + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + + if got, want := res.status, 404; got != want { + t.Errorf("status = %v; want %v", got, want) + } + + hdtests := []struct { + k, v string + }{ + {"content-length", "11"}, + {"from", "mruby"}, + } + for _, tt := range hdtests { + if got, want := res.header.Get(tt.k), tt.v; got != want { + t.Errorf("%v = %v; want %v", tt.k, got, want) + } + } + + if got, want := string(res.body), "Hello World"; got != want { + t.Errorf("body = %v; want %v", got, want) + } +} diff --git a/integration-tests/req-set-header.rb b/integration-tests/req-set-header.rb new file mode 100644 index 00000000..6f63e357 --- /dev/null +++ b/integration-tests/req-set-header.rb @@ -0,0 +1,3 @@ +Nghttpx.run do |resp, req| + req.set_header "User-Agent", "mruby" +end diff --git a/integration-tests/resp-set-header.rb b/integration-tests/resp-set-header.rb new file mode 100644 index 00000000..a1f2d806 --- /dev/null +++ b/integration-tests/resp-set-header.rb @@ -0,0 +1,3 @@ +Nghttpx.run do |resp, req| + resp.set_header "Alpha", "bravo" +end diff --git a/integration-tests/return.rb b/integration-tests/return.rb new file mode 100644 index 00000000..42b1e345 --- /dev/null +++ b/integration-tests/return.rb @@ -0,0 +1,6 @@ +Nghttpx.run do |resp, req| + resp.clear_headers + resp.status = 404 + resp.add_header "from", "mruby" + resp.return "Hello World" +end