trpc.group/trpc-go/trpc-go@v1.0.3/admin/router_test.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package admin 15 16 import ( 17 "fmt" 18 "io" 19 "net" 20 "net/http" 21 "reflect" 22 "runtime" 23 "testing" 24 "time" 25 26 "github.com/stretchr/testify/require" 27 ) 28 29 func TestRouter(t *testing.T) { 30 // Given a router 31 r := newRouter() 32 33 // And config its handler function with pattern "/index" and Desc "index page" 34 r.add("/index", func(w http.ResponseWriter, r *http.Request) { 35 w.Write([]byte(r.URL.Path)) 36 }) 37 38 // When List current handlers that have already registered from the router 39 handlers := r.list() 40 41 // Then the handlers should contain only the single handler function previously registered 42 require.Len(t, handlers, 1) 43 require.Equal(t, "/index", handlers[0].pattern) 44 45 // When config a testHandler with pattern "/test1", and try to find the new handler from the router 46 testHandler := func(w http.ResponseWriter, r *http.Request) {} 47 r.add("/test", testHandler) 48 var handler *routerHandler 49 for _, h := range r.list() { 50 if h.pattern == "/test" { 51 handler = h 52 break 53 } 54 } 55 56 // Then the handler found should be the testHandler 57 require.Equal(t, 58 runtime.FuncForPC(reflect.ValueOf(testHandler).Pointer()).Name(), 59 runtime.FuncForPC(reflect.ValueOf(handler.handler).Pointer()).Name(), 60 ) 61 62 // When start a http server with the router, and send a http GET request to access index page 63 addr := mustListenAndServe(t, r) 64 resp, err := http.Get(fmt.Sprintf("http://%v%s", addr, "/index")) 65 require.Nil(t, err) 66 body, err := io.ReadAll(resp.Body) 67 resp.Body.Close() 68 69 // Then response body should be "/index" 70 require.Nil(t, err) 71 require.Equal(t, "/index", string(body)) 72 73 // When send a http GET request to access nonexistent resource 74 resp, err = http.Get(fmt.Sprintf("http://%v%s", addr, "/nonexistent-resource")) 75 require.Nil(t, err) 76 body, err = io.ReadAll(resp.Body) 77 resp.Body.Close() 78 79 // Then the response body should contain 404 error message 80 require.Nil(t, err) 81 require.Equal(t, "404 page not found\n", string(body)) 82 } 83 84 func TestRouter_ServeHTTP(t *testing.T) { 85 t.Run("panic but recovered", func(t *testing.T) { 86 // Given a router 87 r := newRouter() 88 89 // And config its handler function that always panic with pattern "/index" 90 const panicMessage = "there must be something wrong with your code" 91 r.add("/index", func(w http.ResponseWriter, r *http.Request) { 92 panic(panicMessage) 93 }) 94 95 // When start a http server with the router, and send a http GET request to access index page 96 addr := mustListenAndServe(t, r) 97 resp, err := http.Get(fmt.Sprintf("http://%v%s", addr, "/index")) 98 require.Nil(t, err) 99 require.Nil(t, err) 100 body, err := io.ReadAll(resp.Body) 101 resp.Body.Close() 102 103 // Then response body should contain panic message 104 require.Nil(t, err) 105 require.Contains(t, string(body), "PANIC : "+panicMessage) 106 }) 107 } 108 109 func mustListenAndServe(t *testing.T, r *router) net.Addr { 110 l, err := net.Listen("tcp", testAddress) 111 if err != nil { 112 t.Fatal(err) 113 } 114 go func() { 115 if http.Serve(l, r); err != nil && err != http.ErrServerClosed { 116 t.Log(err) 117 } 118 }() 119 time.Sleep(time.Second) 120 return l.Addr() 121 }