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  }