github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/api/v2/unsafe_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 v2
    15  
    16  import (
    17  	"context"
    18  	"encoding/json"
    19  	"net/http"
    20  	"net/http/httptest"
    21  	"testing"
    22  
    23  	"github.com/golang/mock/gomock"
    24  	"github.com/pingcap/errors"
    25  	mock_capture "github.com/pingcap/tiflow/cdc/capture/mock"
    26  	"github.com/pingcap/tiflow/cdc/model"
    27  	cerror "github.com/pingcap/tiflow/pkg/errors"
    28  	mock_etcd "github.com/pingcap/tiflow/pkg/etcd/mock"
    29  	"github.com/pingcap/tiflow/pkg/upstream"
    30  	"github.com/stretchr/testify/require"
    31  	pd "github.com/tikv/pd/client"
    32  	"go.etcd.io/etcd/api/v3/mvccpb"
    33  )
    34  
    35  var withFuntion = func(context.Context, pd.Client) error { return nil }
    36  
    37  func TestCDCMetaData(t *testing.T) {
    38  	t.Parallel()
    39  
    40  	metaData := testCase{url: "/api/v2/unsafe/metadata", method: "GET"}
    41  
    42  	cp := mock_capture.NewMockCapture(gomock.NewController(t))
    43  	helpers := NewMockAPIV2Helpers(gomock.NewController(t))
    44  	apiV2 := NewOpenAPIV2ForTest(cp, helpers)
    45  	router := newRouter(apiV2)
    46  
    47  	etcdClient := mock_etcd.NewMockCDCEtcdClient(gomock.NewController(t))
    48  	cp.EXPECT().IsController().Return(true).AnyTimes()
    49  	cp.EXPECT().IsReady().Return(true).AnyTimes()
    50  	cp.EXPECT().GetEtcdClient().Return(etcdClient).AnyTimes()
    51  
    52  	// case 1: failed
    53  	etcdClient.EXPECT().GetAllCDCInfo(gomock.Any()).Return(nil, cerror.ErrPDEtcdAPIError).Times(1)
    54  
    55  	w := httptest.NewRecorder()
    56  	req, _ := http.NewRequestWithContext(context.Background(), metaData.method, metaData.url, nil)
    57  	router.ServeHTTP(w, req)
    58  	respErr := model.HTTPError{}
    59  	err := json.NewDecoder(w.Body).Decode(&respErr)
    60  	require.Nil(t, err)
    61  	require.Contains(t, respErr.Code, "ErrPDEtcdAPIError")
    62  	require.Equal(t, http.StatusInternalServerError, w.Code)
    63  
    64  	// case 2: success
    65  	kvs := []*mvccpb.KeyValue{{Key: []byte{byte(0)}, Value: []byte{byte(1)}}}
    66  	etcdClient.EXPECT().GetAllCDCInfo(gomock.Any()).Return(kvs, nil).Times(1)
    67  
    68  	w = httptest.NewRecorder()
    69  	req, _ = http.NewRequestWithContext(context.Background(), metaData.method, metaData.url, nil)
    70  	router.ServeHTTP(w, req)
    71  	require.Equal(t, http.StatusOK, w.Code)
    72  	var resp []EtcdData
    73  	err = json.NewDecoder(w.Body).Decode(&resp)
    74  	require.Nil(t, err)
    75  	require.Equal(t, len(kvs), len(resp))
    76  	for i, kv := range resp {
    77  		require.Equal(t, string(kvs[i].Key), kv.Key)
    78  		require.Equal(t, string(kvs[i].Key), kv.Key)
    79  	}
    80  }
    81  
    82  func TestWithUpstreamConfig(t *testing.T) {
    83  	ctx, cancel := context.WithCancel(context.Background())
    84  	defer cancel()
    85  	upManager := upstream.NewManager(ctx, upstream.CaptureTopologyCfg{GCServiceID: "abc"})
    86  	upManager.AddUpstream(&model.UpstreamInfo{
    87  		ID:          uint64(1),
    88  		PDEndpoints: "http://127.0.0.1:22379",
    89  	})
    90  	cpCtrl := gomock.NewController(t)
    91  	cp := mock_capture.NewMockCapture(cpCtrl)
    92  	hpCtrl := gomock.NewController(t)
    93  	helpers := NewMockAPIV2Helpers(hpCtrl)
    94  
    95  	cp.EXPECT().GetUpstreamManager().Return(upManager, nil).AnyTimes()
    96  	api := NewOpenAPIV2ForTest(cp, helpers)
    97  
    98  	// upStream ID > 0 , getUpstream config ok
    99  	upstreamConfig := &UpstreamConfig{
   100  		ID: 1,
   101  	}
   102  	err := api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   103  	require.Nil(t, err)
   104  
   105  	// upStream ID > 0, getUpstream config not ok
   106  	upstreamConfig = &UpstreamConfig{
   107  		ID: 2,
   108  	}
   109  	err = api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   110  	require.NotNil(t, err)
   111  
   112  	// upStreamConfig.ID = 0, len(pdAddress) > 0 : failed to getPDClient
   113  	upstreamConfig = &UpstreamConfig{
   114  		PDConfig: PDConfig{
   115  			PDAddrs: []string{"http://127.0.0.1:22379"},
   116  		},
   117  	}
   118  	helpers.EXPECT().
   119  		getPDClient(gomock.Any(), gomock.Any(), gomock.Any()).
   120  		Return(&mockPDClient{}, nil)
   121  	err = api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   122  	require.Nil(t, err)
   123  
   124  	// upStreamConfig.ID = 0, len(pdAddress) > 0, get PDClient succeed
   125  	upstreamConfig = &UpstreamConfig{
   126  		PDConfig: PDConfig{
   127  			PDAddrs: []string{"http://127.0.0.1:22379"},
   128  		},
   129  	}
   130  	helpers.EXPECT().
   131  		getPDClient(gomock.Any(), gomock.Any(), gomock.Any()).
   132  		Return(&mockPDClient{}, errors.New("getPDClient failed"))
   133  	err = api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   134  	require.NotNil(t, err)
   135  
   136  	// upStreamConfig.ID = 0, len(pdAddress) > 0, no default upstream
   137  	upstreamConfig = &UpstreamConfig{}
   138  	err = api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   139  	require.NotNil(t, err)
   140  
   141  	// success
   142  	upManager = upstream.NewManager4Test(&mockPDClient{})
   143  	cp = mock_capture.NewMockCapture(gomock.NewController(t))
   144  	cp.EXPECT().GetUpstreamManager().Return(upManager, nil).AnyTimes()
   145  	api = NewOpenAPIV2ForTest(cp, helpers)
   146  	upstreamConfig = &UpstreamConfig{}
   147  	err = api.withUpstreamConfig(ctx, upstreamConfig, withFuntion)
   148  	require.Nil(t, err)
   149  }