1// Copyright 2018 The Go Cloud Development Kit Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package server 16 17import ( 18 "context" 19 "errors" 20 "net/http" 21 "net/http/httptest" 22 "testing" 23 24 "gocloud.dev/server/requestlog" 25) 26 27const ( 28 certFile = "my-cert" 29 keyFile = "my-key" 30) 31 32func TestListenAndServe(t *testing.T) { 33 td := new(testDriver) 34 s := New(http.NotFoundHandler(), &Options{Driver: td}) 35 err := s.ListenAndServe(":8080") 36 if err != nil { 37 t.Fatal(err) 38 } 39 if !td.listenAndServeCalled { 40 t.Error("ListenAndServe was not called from the supplied driver") 41 } 42 if td.certFile != "" || td.keyFile != "" { 43 t.Errorf("ListenAndServe got non-empty certFile or keyFile (%q, %q), wanted empty", td.certFile, td.keyFile) 44 } 45 if td.handler == nil { 46 t.Error("testDriver must set handler, got nil") 47 } 48} 49 50func TestListenAndServeTLSNoSupported(t *testing.T) { 51 td := new(testDriverNoTLS) 52 s := New(http.NotFoundHandler(), &Options{Driver: td}) 53 err := s.ListenAndServeTLS(":8080", certFile, keyFile) 54 if err == nil { 55 t.Fatal("expected TLS not supported error") 56 } 57} 58 59func TestListenAndServeTLS(t *testing.T) { 60 td := new(testDriver) 61 s := New(http.NotFoundHandler(), &Options{Driver: td}) 62 err := s.ListenAndServeTLS(":8080", certFile, keyFile) 63 if err != nil { 64 t.Fatal(err) 65 } 66 if !td.listenAndServeCalled { 67 t.Error("ListenAndServe was not called from the supplied driver") 68 } 69 if td.certFile != certFile { 70 t.Errorf("ListenAndServe got certFile %q, want %q", td.certFile, certFile) 71 } 72 if td.keyFile != keyFile { 73 t.Errorf("ListenAndServe got keyFile %q, want %q", td.keyFile, keyFile) 74 } 75 if td.handler == nil { 76 t.Error("testDriver must set handler, got nil") 77 } 78} 79 80func TestMiddleware(t *testing.T) { 81 onLogCalled := 0 82 83 tl := &testLogger{ 84 onLog: func(ent *requestlog.Entry) { 85 onLogCalled++ 86 if ent.TraceID.String() == "" { 87 t.Error("TraceID is empty") 88 } 89 if ent.SpanID.String() == "" { 90 t.Error("SpanID is empty") 91 } 92 }, 93 } 94 95 td := new(testDriver) 96 s := New(http.NotFoundHandler(), &Options{Driver: td, RequestLogger: tl}) 97 err := s.ListenAndServe(":8080") 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 req, err := http.NewRequest("GET", "/", nil) 103 if err != nil { 104 t.Fatal(err) 105 } 106 107 rr := httptest.NewRecorder() 108 td.handler.ServeHTTP(rr, req) 109 if onLogCalled != 1 { 110 t.Fatal("logging middleware was not called") 111 } 112 113 // Repeat with TLS. 114 err = s.ListenAndServeTLS(":8081", certFile, keyFile) 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 req, err = http.NewRequest("GET", "/", nil) 120 if err != nil { 121 t.Fatal(err) 122 } 123 td.handler.ServeHTTP(rr, req) 124 if onLogCalled != 2 { 125 t.Fatal("logging middleware was not called for TLS") 126 } 127 128} 129 130type testDriverNoTLS string 131 132func (td *testDriverNoTLS) ListenAndServe(addr string, h http.Handler) error { 133 return errors.New("this is a method for satisfying the interface") 134} 135 136func (td *testDriverNoTLS) Shutdown(ctx context.Context) error { 137 return errors.New("this is a method for satisfying the interface") 138} 139 140type testDriver struct { 141 listenAndServeCalled bool 142 certFile, keyFile string 143 handler http.Handler 144} 145 146func (td *testDriver) ListenAndServe(addr string, h http.Handler) error { 147 td.listenAndServeCalled = true 148 td.handler = h 149 return nil 150} 151 152func (td *testDriver) ListenAndServeTLS(addr, certFile, keyFile string, h http.Handler) error { 153 td.listenAndServeCalled = true 154 td.certFile = certFile 155 td.keyFile = keyFile 156 td.handler = h 157 return nil 158} 159 160func (td *testDriver) Shutdown(ctx context.Context) error { 161 return errors.New("this is a method for satisfying the interface") 162} 163 164type testLogger struct { 165 onLog func(ent *requestlog.Entry) 166} 167 168func (tl *testLogger) Log(ent *requestlog.Entry) { 169 tl.onLog(ent) 170} 171