github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/http_status_test.go (about) 1 // Copyright 2020 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 cdc 15 16 import ( 17 "bytes" 18 "fmt" 19 "io/ioutil" 20 "net/http" 21 "net/url" 22 "time" 23 24 "github.com/pingcap/check" 25 "github.com/pingcap/failpoint" 26 "github.com/pingcap/ticdc/pkg/config" 27 cerror "github.com/pingcap/ticdc/pkg/errors" 28 "github.com/pingcap/ticdc/pkg/util/testleak" 29 "go.etcd.io/etcd/clientv3/concurrency" 30 ) 31 32 type httpStatusSuite struct{} 33 34 var _ = check.Suite(&httpStatusSuite{}) 35 36 const retryTime = 20 37 38 var advertiseAddr4Test = "127.0.0.1:8300" 39 40 func (s *httpStatusSuite) waitUntilServerOnline(c *check.C) { 41 statusURL := fmt.Sprintf("http://%s/status", advertiseAddr4Test) 42 for i := 0; i < retryTime; i++ { 43 resp, err := http.Get(statusURL) 44 if err == nil { 45 _, err := ioutil.ReadAll(resp.Body) 46 c.Assert(err, check.IsNil) 47 resp.Body.Close() 48 return 49 } 50 time.Sleep(time.Millisecond * 50) 51 } 52 c.Errorf("failed to connect http status for %d retries in every 50ms", retryTime) 53 } 54 55 func (s *httpStatusSuite) TestHTTPStatus(c *check.C) { 56 defer testleak.AfterTest(c)() 57 conf := config.GetDefaultServerConfig() 58 conf.Addr = advertiseAddr4Test 59 conf.AdvertiseAddr = advertiseAddr4Test 60 config.StoreGlobalServerConfig(conf) 61 server, err := NewServer([]string{"http://127.0.0.1:2379"}) 62 c.Assert(err, check.IsNil) 63 err = server.startStatusHTTP() 64 c.Assert(err, check.IsNil) 65 defer func() { 66 c.Assert(server.statusServer.Close(), check.IsNil) 67 }() 68 69 s.waitUntilServerOnline(c) 70 71 testPprof(c) 72 testReisgnOwner(c) 73 testHandleChangefeedAdmin(c) 74 testHandleRebalance(c) 75 testHandleMoveTable(c) 76 testHandleChangefeedQuery(c) 77 testHandleFailpoint(c) 78 } 79 80 func testPprof(c *check.C) { 81 resp, err := http.Get(fmt.Sprintf("http://%s/debug/pprof/cmdline", advertiseAddr4Test)) 82 c.Assert(err, check.IsNil) 83 defer resp.Body.Close() 84 c.Assert(resp.StatusCode, check.Equals, 200) 85 _, err = ioutil.ReadAll(resp.Body) 86 c.Assert(err, check.IsNil) 87 } 88 89 func testReisgnOwner(c *check.C) { 90 uri := fmt.Sprintf("http://%s/capture/owner/resign", advertiseAddr4Test) 91 testHTTPPostOnly(c, uri) 92 testRequestNonOwnerFailed(c, uri) 93 } 94 95 func testHandleChangefeedAdmin(c *check.C) { 96 uri := fmt.Sprintf("http://%s/capture/owner/admin", advertiseAddr4Test) 97 testHTTPPostOnly(c, uri) 98 testRequestNonOwnerFailed(c, uri) 99 } 100 101 func testHandleRebalance(c *check.C) { 102 uri := fmt.Sprintf("http://%s/capture/owner/rebalance_trigger", advertiseAddr4Test) 103 testHTTPPostOnly(c, uri) 104 testRequestNonOwnerFailed(c, uri) 105 } 106 107 func testHandleMoveTable(c *check.C) { 108 uri := fmt.Sprintf("http://%s/capture/owner/move_table", advertiseAddr4Test) 109 testHTTPPostOnly(c, uri) 110 testRequestNonOwnerFailed(c, uri) 111 } 112 113 func testHandleChangefeedQuery(c *check.C) { 114 uri := fmt.Sprintf("http://%s/capture/owner/changefeed/query", advertiseAddr4Test) 115 testHTTPPostOnly(c, uri) 116 testRequestNonOwnerFailed(c, uri) 117 } 118 119 func testHTTPPostOnly(c *check.C, uri string) { 120 resp, err := http.Get(uri) 121 c.Assert(err, check.IsNil) 122 data, err := ioutil.ReadAll(resp.Body) 123 c.Assert(err, check.IsNil) 124 defer resp.Body.Close() 125 c.Assert(resp.StatusCode, check.Equals, http.StatusBadRequest) 126 c.Assert(string(data), check.Equals, cerror.ErrSupportPostOnly.Error()) 127 } 128 129 func testRequestNonOwnerFailed(c *check.C, uri string) { 130 resp, err := http.PostForm(uri, url.Values{}) 131 c.Assert(err, check.IsNil) 132 data, err := ioutil.ReadAll(resp.Body) 133 c.Assert(err, check.IsNil) 134 defer resp.Body.Close() 135 c.Assert(resp.StatusCode, check.Equals, http.StatusBadRequest) 136 c.Assert(string(data), check.Equals, concurrency.ErrElectionNotLeader.Error()) 137 } 138 139 func testHandleFailpoint(c *check.C) { 140 fp := "github.com/pingcap/ticdc/cdc/TestHandleFailpoint" 141 uri := fmt.Sprintf("http://%s/debug/fail/%s", advertiseAddr4Test, fp) 142 body := bytes.NewReader([]byte("return(true)")) 143 req, err := http.NewRequest("PUT", uri, body) 144 c.Assert(err, check.IsNil) 145 146 resp, err := http.DefaultClient.Do(req) 147 c.Assert(err, check.IsNil) 148 defer resp.Body.Close() 149 c.Assert(resp.StatusCode, check.GreaterEqual, 200) 150 c.Assert(resp.StatusCode, check.Less, 300) 151 152 failpointHit := false 153 failpoint.Inject("TestHandleFailpoint", func() { 154 failpointHit = true 155 }) 156 c.Assert(failpointHit, check.IsTrue) 157 158 req, err = http.NewRequest("DELETE", uri, body) 159 c.Assert(err, check.IsNil) 160 resp, err = http.DefaultClient.Do(req) 161 c.Assert(err, check.IsNil) 162 defer resp.Body.Close() 163 c.Assert(resp.StatusCode, check.GreaterEqual, 200) 164 c.Assert(resp.StatusCode, check.Less, 300) 165 166 failpointHit = false 167 failpoint.Inject("TestHandleFailpoint", func() { 168 failpointHit = true 169 }) 170 c.Assert(failpointHit, check.IsFalse) 171 }