github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/tequilapi/client/client_test.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package client 19 20 import ( 21 "io" 22 "net/http" 23 "net/http/httptest" 24 "strings" 25 "testing" 26 27 "github.com/mysteriumnetwork/node/core/monitoring" 28 29 "github.com/mysteriumnetwork/node/tequilapi/contract" 30 "github.com/stretchr/testify/assert" 31 ) 32 33 const errorMessage = ` 34 { 35 "message" : "me haz faild" 36 } 37 ` 38 39 func Test_NATStatus_ReturnsStatus(t *testing.T) { 40 httpClient := mockHTTPClient( 41 t, 42 http.MethodGet, 43 "/node/monitoring-status", 44 http.StatusOK, 45 `{"status": "failed"}`, 46 ) 47 client := Client{http: httpClient} 48 49 status, err := client.NATStatus() 50 51 assert.NoError(t, err) 52 assert.Equal(t, monitoring.Failed, status.Status) 53 } 54 55 func Test_NATStatus_ReturnsError(t *testing.T) { 56 httpClient := mockHTTPClient( 57 t, 58 http.MethodGet, 59 "/node/monitoring-status", 60 http.StatusInternalServerError, 61 ``, 62 ) 63 client := Client{http: httpClient} 64 65 _, err := client.NATStatus() 66 assert.Error(t, err) 67 } 68 69 func TestConnectionErrorIsReturnedByClientInsteadOfDoubleParsing(t *testing.T) { 70 responseBody := &trackingCloser{ 71 Reader: strings.NewReader(errorMessage), 72 } 73 74 client := Client{ 75 http: &httpClient{ 76 http: onAnyRequestReturn(&http.Response{ 77 Status: "Internal server error", 78 StatusCode: 500, 79 Body: responseBody, 80 }), 81 baseURL: "http://test-api-whatever", 82 ua: "test-agent", 83 }, 84 } 85 86 _, err := client.ConnectionCreate("consumer", "provider", "hermes", "service", contract.ConnectOptions{}) 87 assert.Error(t, err) 88 assert.EqualError(t, err, "server responded with an error: 500 (http://test-api-whatever/connection) [internal] \n{\n\t\"message\" : \"me haz faild\"\n}\n") 89 //when doing http request, response body should always be closed by client - otherwise persistent connections are leaking 90 assert.True(t, responseBody.Closed) 91 } 92 93 func mockHTTPClient(t *testing.T, method, url string, statusCode int, response string) httpClientInterface { 94 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 95 assert.Equal(t, method, r.Method) 96 assert.Equal(t, url, r.URL.Path) 97 w.Write([]byte(response)) 98 w.WriteHeader(statusCode) 99 })) 100 return newHTTPClient(server.URL, "") 101 } 102 103 type requestDoer func(req *http.Request) (*http.Response, error) 104 105 func (f requestDoer) Do(req *http.Request) (*http.Response, error) { 106 return f(req) 107 } 108 109 func onAnyRequestReturn(response *http.Response) requestDoer { 110 return func(req *http.Request) (*http.Response, error) { 111 response.Request = req 112 return response, nil 113 } 114 } 115 116 type trackingCloser struct { 117 io.Reader 118 Closed bool 119 } 120 121 func (tc *trackingCloser) Close() error { 122 tc.Closed = true 123 return nil 124 } 125 126 var _ io.ReadCloser = (*trackingCloser)(nil)