go-micro.dev/v5@v5.12.0/web/service_test.go (about) 1 package web 2 3 import ( 4 "crypto/tls" 5 "fmt" 6 "io" 7 "net/http" 8 "os" 9 "os/signal" 10 "syscall" 11 "testing" 12 "time" 13 14 "go-micro.dev/v5/registry" 15 ) 16 17 func TestService(t *testing.T) { 18 var ( 19 beforeStartCalled bool 20 afterStartCalled bool 21 beforeStopCalled bool 22 afterStopCalled bool 23 str = `<html><body><h1>Hello World</h1></body></html>` 24 fn = func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, str) } 25 reg = registry.NewMemoryRegistry() 26 ) 27 28 beforeStart := func() error { 29 beforeStartCalled = true 30 return nil 31 } 32 33 afterStart := func() error { 34 afterStartCalled = true 35 return nil 36 } 37 38 beforeStop := func() error { 39 beforeStopCalled = true 40 return nil 41 } 42 43 afterStop := func() error { 44 afterStopCalled = true 45 return nil 46 } 47 48 service := NewService( 49 Name("go.micro.web.test"), 50 Registry(reg), 51 BeforeStart(beforeStart), 52 AfterStart(afterStart), 53 BeforeStop(beforeStop), 54 AfterStop(afterStop), 55 ) 56 57 service.HandleFunc("/", fn) 58 59 errCh := make(chan error, 1) 60 go func() { 61 errCh <- service.Run() 62 close(errCh) 63 }() 64 65 var s []*registry.Service 66 67 eventually(func() bool { 68 var err error 69 s, err = reg.GetService("go.micro.web.test") 70 return err == nil 71 }, t.Fatal) 72 73 if have, want := len(s), 1; have != want { 74 t.Fatalf("Expected %d but got %d services", want, have) 75 } 76 77 rsp, err := http.Get(fmt.Sprintf("http://%s", s[0].Nodes[0].Address)) 78 if err != nil { 79 t.Fatal(err) 80 } 81 defer rsp.Body.Close() 82 83 b, err := io.ReadAll(rsp.Body) 84 if err != nil { 85 t.Fatal(err) 86 } 87 88 if string(b) != str { 89 t.Errorf("Expected %s got %s", str, string(b)) 90 } 91 92 callbackTests := []struct { 93 subject string 94 have interface{} 95 }{ 96 {"beforeStartCalled", beforeStartCalled}, 97 {"afterStartCalled", afterStartCalled}, 98 } 99 100 for _, tt := range callbackTests { 101 if tt.have != true { 102 t.Errorf("unexpected %s: want true, have false", tt.subject) 103 } 104 } 105 106 select { 107 case err := <-errCh: 108 if err != nil { 109 t.Fatalf("service.Run():%v", err) 110 } 111 case <-time.After(time.Duration(time.Second)): 112 if len(os.Getenv("IN_TRAVIS_CI")) == 0 { 113 t.Logf("service.Run() survived a client request without an error") 114 } 115 } 116 117 ch := make(chan os.Signal, 1) 118 signal.Notify(ch, syscall.SIGTERM) 119 p, _ := os.FindProcess(os.Getpid()) 120 p.Signal(syscall.SIGTERM) 121 122 <-ch 123 124 select { 125 case err := <-errCh: 126 if err != nil { 127 t.Fatalf("service.Run():%v", err) 128 } else { 129 if len(os.Getenv("IN_TRAVIS_CI")) == 0 { 130 t.Log("service.Run() nil return on syscall.SIGTERM") 131 } 132 } 133 case <-time.After(time.Duration(time.Second)): 134 if len(os.Getenv("IN_TRAVIS_CI")) == 0 { 135 t.Logf("service.Run() survived a client request without an error") 136 } 137 } 138 139 eventually(func() bool { 140 _, err := reg.GetService("go.micro.web.test") 141 return err == registry.ErrNotFound 142 }, t.Error) 143 144 callbackTests = []struct { 145 subject string 146 have interface{} 147 }{ 148 {"beforeStopCalled", beforeStopCalled}, 149 {"afterStopCalled", afterStopCalled}, 150 } 151 152 for _, tt := range callbackTests { 153 if tt.have != true { 154 t.Errorf("unexpected %s: want true, have false", tt.subject) 155 } 156 } 157 } 158 159 func TestOptions(t *testing.T) { 160 var ( 161 name = "service-name" 162 id = "service-id" 163 version = "service-version" 164 address = "service-addr:8080" 165 advertise = "service-adv:8080" 166 reg = registry.NewMemoryRegistry() 167 registerTTL = 123 * time.Second 168 registerInterval = 456 * time.Second 169 handler = http.NewServeMux() 170 metadata = map[string]string{"key": "val"} 171 secure = true 172 ) 173 174 service := NewService( 175 Name(name), 176 Id(id), 177 Version(version), 178 Address(address), 179 Advertise(advertise), 180 Registry(reg), 181 RegisterTTL(registerTTL), 182 RegisterInterval(registerInterval), 183 Handler(handler), 184 Metadata(metadata), 185 Secure(secure), 186 ) 187 188 opts := service.Options() 189 190 tests := []struct { 191 subject string 192 want interface{} 193 have interface{} 194 }{ 195 {"name", name, opts.Name}, 196 {"version", version, opts.Version}, 197 {"id", id, opts.Id}, 198 {"address", address, opts.Address}, 199 {"advertise", advertise, opts.Advertise}, 200 {"registry", reg, opts.Registry}, 201 {"registerTTL", registerTTL, opts.RegisterTTL}, 202 {"registerInterval", registerInterval, opts.RegisterInterval}, 203 {"handler", handler, opts.Handler}, 204 {"metadata", metadata["key"], opts.Metadata["key"]}, 205 {"secure", secure, opts.Secure}, 206 } 207 208 for _, tc := range tests { 209 if tc.want != tc.have { 210 t.Errorf("unexpected %s: want %v, have %v", tc.subject, tc.want, tc.have) 211 } 212 } 213 } 214 215 func eventually(pass func() bool, fail func(...interface{})) { 216 tick := time.NewTicker(10 * time.Millisecond) 217 defer tick.Stop() 218 219 timeout := time.After(time.Second) 220 221 for { 222 select { 223 case <-timeout: 224 fail("timed out") 225 return 226 case <-tick.C: 227 if pass() { 228 return 229 } 230 } 231 } 232 } 233 234 func TestTLS(t *testing.T) { 235 var ( 236 str = `<html><body><h1>Hello World</h1></body></html>` 237 fn = func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, str) } 238 secure = true 239 reg = registry.NewMemoryRegistry() 240 ) 241 242 service := NewService( 243 Name("go.micro.web.test"), 244 Secure(secure), 245 Registry(reg), 246 ) 247 248 service.HandleFunc("/", fn) 249 250 errCh := make(chan error, 1) 251 go func() { 252 errCh <- service.Run() 253 close(errCh) 254 }() 255 256 var s []*registry.Service 257 258 eventually(func() bool { 259 var err error 260 s, err = reg.GetService("go.micro.web.test") 261 return err == nil 262 }, t.Fatal) 263 264 if have, want := len(s), 1; have != want { 265 t.Fatalf("Expected %d but got %d services", want, have) 266 } 267 268 tr := &http.Transport{ 269 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 270 } 271 client := &http.Client{Transport: tr} 272 rsp, err := client.Get(fmt.Sprintf("https://%s", s[0].Nodes[0].Address)) 273 if err != nil { 274 t.Fatal(err) 275 } 276 defer rsp.Body.Close() 277 278 b, err := io.ReadAll(rsp.Body) 279 if err != nil { 280 t.Fatal(err) 281 } 282 283 if string(b) != str { 284 t.Errorf("Expected %s got %s", str, string(b)) 285 } 286 287 select { 288 case err := <-errCh: 289 if err != nil { 290 t.Fatalf("service.Run():%v", err) 291 } 292 case <-time.After(time.Duration(time.Second)): 293 if len(os.Getenv("IN_TRAVIS_CI")) == 0 { 294 t.Logf("service.Run() survived a client request without an error") 295 } 296 } 297 }