github.com/pingcap/failpoint@v0.0.0-20240412033321-fd0796e60f86/http_test.go (about) 1 // Copyright 2021 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package failpoint_test 16 17 import ( 18 "errors" 19 "io/ioutil" 20 "net/http" 21 "net/http/httptest" 22 "strings" 23 "testing" 24 25 "github.com/pingcap/failpoint" 26 "github.com/stretchr/testify/require" 27 ) 28 29 type badReader struct{} 30 31 func (badReader) Read([]byte) (int, error) { 32 return 0, errors.New("mock bad read") 33 } 34 35 func TestServeHTTP(t *testing.T) { 36 require.NoError(t, failpoint.Serve(":23389")) 37 38 handler := &failpoint.HttpHandler{} 39 40 // PUT 41 req, err := http.NewRequest(http.MethodPut, "http://127.0.0.1/failpoint-name", strings.NewReader("return(1)")) 42 require.NoError(t, err) 43 res := httptest.NewRecorder() 44 handler.ServeHTTP(res, req) 45 require.Equal(t, http.StatusNoContent, res.Code) 46 47 req, err = http.NewRequest(http.MethodPut, "http://127.0.0.1", strings.NewReader("return(1)")) 48 require.NoError(t, err) 49 res = httptest.NewRecorder() 50 handler.ServeHTTP(res, req) 51 require.Equal(t, http.StatusBadRequest, res.Code) 52 require.Contains(t, res.Body.String(), "malformed request URI") 53 54 req, err = http.NewRequest(http.MethodPut, "http://127.0.0.1/failpoint-name", badReader{}) 55 require.NoError(t, err) 56 res = httptest.NewRecorder() 57 handler.ServeHTTP(res, req) 58 require.Equal(t, http.StatusBadRequest, res.Code) 59 require.Contains(t, res.Body.String(), "failed ReadAll in PUT") 60 61 req, err = http.NewRequest(http.MethodPut, "http://127.0.0.1/failpoint-name", strings.NewReader("invalid")) 62 require.NoError(t, err) 63 res = httptest.NewRecorder() 64 handler.ServeHTTP(res, req) 65 require.Equal(t, http.StatusBadRequest, res.Code) 66 require.Contains(t, res.Body.String(), "failed to set failpoint") 67 68 // GET 69 req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1/failpoint-name", strings.NewReader("")) 70 require.NoError(t, err) 71 res = httptest.NewRecorder() 72 handler.ServeHTTP(res, req) 73 require.Equal(t, http.StatusOK, res.Code) 74 require.Contains(t, res.Body.String(), "return(1)") 75 76 req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1/failpoint-name-not-exists", strings.NewReader("")) 77 require.NoError(t, err) 78 res = httptest.NewRecorder() 79 handler.ServeHTTP(res, req) 80 require.Equal(t, http.StatusNotFound, res.Code) 81 require.Contains(t, res.Body.String(), "failed to GET") 82 83 req, err = http.NewRequest(http.MethodGet, "http://127.0.0.1/", strings.NewReader("")) 84 require.NoError(t, err) 85 res = httptest.NewRecorder() 86 handler.ServeHTTP(res, req) 87 require.Equal(t, http.StatusOK, res.Code) 88 require.Contains(t, res.Body.String(), "failpoint-name=return(1)") 89 90 // DELETE 91 req, err = http.NewRequest(http.MethodDelete, "http://127.0.0.1/failpoint-name", strings.NewReader("")) 92 require.NoError(t, err) 93 res = httptest.NewRecorder() 94 handler.ServeHTTP(res, req) 95 require.Equal(t, http.StatusNoContent, res.Code) 96 97 req, err = http.NewRequest(http.MethodDelete, "http://127.0.0.1/failpoint-name-not-exists", strings.NewReader("")) 98 require.NoError(t, err) 99 res = httptest.NewRecorder() 100 handler.ServeHTTP(res, req) 101 require.Equal(t, http.StatusBadRequest, res.Code) 102 require.Contains(t, res.Body.String(), "failed to delete failpoint") 103 104 // DEFAULT 105 req, err = http.NewRequest(http.MethodPost, "http://127.0.0.1/failpoint-name", strings.NewReader("")) 106 require.NoError(t, err) 107 res = httptest.NewRecorder() 108 handler.ServeHTTP(res, req) 109 require.Equal(t, http.StatusMethodNotAllowed, res.Code) 110 require.Contains(t, res.Body.String(), "Method not allowed") 111 112 // Test environment variable injection 113 resp, err := http.Get("http://127.0.0.1:23389/failpoint-env1") 114 require.NoError(t, err) 115 require.Equal(t, http.StatusOK, resp.StatusCode) 116 body, err := ioutil.ReadAll(resp.Body) 117 require.NoError(t, err) 118 require.Contains(t, string(body), "return(10)") 119 120 resp, err = http.Get("http://127.0.0.1:23389/failpoint-env2") 121 require.NoError(t, err) 122 require.Equal(t, http.StatusOK, resp.StatusCode) 123 body, err = ioutil.ReadAll(resp.Body) 124 require.NoError(t, err) 125 require.Contains(t, string(body), "return(true)") 126 }