github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/servermaster/http_test.go (about) 1 // Copyright 2022 PingCAP, Inc. 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 // http://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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package servermaster 15 16 import ( 17 "context" 18 "fmt" 19 "net/http" 20 "net/http/httptest" 21 "testing" 22 23 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 24 pb "github.com/pingcap/tiflow/engine/enginepb" 25 "github.com/stretchr/testify/require" 26 "google.golang.org/protobuf/encoding/protojson" 27 ) 28 29 func TestRegisterRoutes(t *testing.T) { 30 t.Parallel() 31 router := http.NewServeMux() 32 grpcMux := runtime.NewServeMux( 33 runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{ 34 MarshalOptions: protojson.MarshalOptions{UseProtoNames: true}, 35 UnmarshalOptions: protojson.UnmarshalOptions{}, 36 }), 37 ) 38 err := pb.RegisterJobManagerHandlerServer(context.Background(), grpcMux, pb.UnimplementedJobManagerServer{}) 39 require.NoError(t, err) 40 41 forwardJobAPI := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 42 if r.URL.Path == "/api/v1/jobs/job1/status" { 43 w.WriteHeader(http.StatusOK) 44 } else { 45 http.NotFound(w, r) 46 } 47 }) 48 registerRoutes(router, grpcMux, forwardJobAPI) 49 50 testCases := []struct { 51 method string 52 path string 53 expectedCode int 54 }{ 55 { 56 method: http.MethodGet, 57 path: "/swagger", 58 expectedCode: http.StatusOK, 59 }, 60 { 61 method: http.MethodGet, 62 path: "/swagger/v1/openapiv2.json", 63 expectedCode: http.StatusOK, 64 }, 65 { 66 method: http.MethodGet, 67 path: "/swagger/v1/openapiv3.json", 68 expectedCode: http.StatusNotFound, 69 }, 70 { 71 method: http.MethodGet, 72 path: "/api/v1/jobs", 73 expectedCode: http.StatusNotImplemented, 74 }, 75 { 76 method: http.MethodPost, 77 path: "/api/v1/jobs", 78 expectedCode: http.StatusNotImplemented, 79 }, 80 { 81 method: http.MethodGet, 82 path: "/api/v1/jobs/job1", 83 expectedCode: http.StatusNotImplemented, 84 }, 85 { 86 method: http.MethodPost, 87 path: "/api/v1/jobs/job1", 88 expectedCode: http.StatusNotImplemented, 89 }, 90 { 91 method: http.MethodGet, 92 path: "/api/v1/jobs/job1/pause", 93 expectedCode: http.StatusNotFound, 94 }, 95 { 96 method: http.MethodGet, 97 path: "/api/v1/jobs/job1/cancel", 98 expectedCode: http.StatusNotImplemented, 99 }, 100 { 101 method: http.MethodGet, 102 path: "/api/v1/jobs/job1/status", 103 expectedCode: http.StatusOK, 104 }, 105 { 106 method: http.MethodGet, 107 path: "/api/v1/jobs/job1/config", 108 expectedCode: http.StatusNotFound, 109 }, 110 { 111 method: http.MethodGet, 112 path: "/debug/pprof/", 113 expectedCode: http.StatusOK, 114 }, 115 { 116 method: http.MethodGet, 117 path: "/metrics", 118 expectedCode: http.StatusOK, 119 }, 120 } 121 122 for i, tc := range testCases { 123 tc := tc 124 t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { 125 t.Parallel() 126 req := httptest.NewRequest(tc.method, tc.path, nil) 127 w := httptest.NewRecorder() 128 router.ServeHTTP(w, req) 129 require.Equal(t, tc.expectedCode, w.Code) 130 }) 131 } 132 } 133 134 func TestShouldForwardJobAPI(t *testing.T) { 135 t.Parallel() 136 ctx := context.Background() 137 testCases := []struct { 138 method string 139 path string 140 shouldForward bool 141 }{ 142 { 143 method: http.MethodGet, 144 path: "/api/v1/jobs", 145 shouldForward: false, 146 }, 147 { 148 method: http.MethodGet, 149 path: "/api/v1/jobs/job1", 150 shouldForward: false, 151 }, 152 { 153 method: http.MethodGet, 154 path: "/api/v1/jobs/job1/pause", 155 shouldForward: true, 156 }, 157 { 158 method: http.MethodPost, 159 path: "/api/v1/jobs/job1/pause", 160 shouldForward: true, 161 }, 162 { 163 method: http.MethodGet, 164 path: "/api/v1/jobs/job1/cancel", 165 shouldForward: false, 166 }, 167 { 168 method: http.MethodPost, 169 path: "/api/v1/jobs/job1/cancel", 170 shouldForward: false, 171 }, 172 { 173 method: http.MethodGet, 174 path: "/api/v1/jobs/job1/status", 175 shouldForward: true, 176 }, 177 { 178 method: http.MethodPost, 179 path: "/api/v1/jobs/job1/config", 180 shouldForward: true, 181 }, 182 } 183 184 for i, tc := range testCases { 185 tc := tc 186 t.Run(fmt.Sprintf("case-%d", i), func(t *testing.T) { 187 t.Parallel() 188 req, err := http.NewRequestWithContext(ctx, tc.method, tc.path, nil) 189 require.NoError(t, err) 190 require.Equal(t, tc.shouldForward, shouldForwardJobAPI(req)) 191 }) 192 } 193 }