github.com/braveheart12/insolar-09-08-19@v0.8.7/api/requester/requester_test.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package requester 18 19 import ( 20 "context" 21 "encoding/base64" 22 "encoding/json" 23 "fmt" 24 "net" 25 "net/http" 26 "os" 27 "testing" 28 "time" 29 30 "github.com/insolar/insolar/api" 31 "github.com/insolar/insolar/instrumentation/inslogger" 32 "github.com/insolar/insolar/log" 33 "github.com/pkg/errors" 34 "github.com/stretchr/testify/require" 35 ) 36 37 const TESTREFERENCE = "4K3NiGuqYGqKPnYp6XeGd2kdN4P9veL6rYcWkLKWXZCu.4FFB8zfQoGznSmzDxwv4njX1aR9ioL8GHSH17QXH2AFa" 38 const TESTSEED = "VGVzdA==" 39 40 var testSeedResponse = seedResponse{Seed: []byte("Test"), TraceID: "testTraceID"} 41 var testInfoResponse = InfoResponse{RootMember: "root_member_ref", RootDomain: "root_domain_ref", NodeDomain: "node_domain_ref"} 42 var testStatusResponse = StatusResponse{NetworkState: "OK"} 43 44 type rpcRequest struct { 45 RPCVersion string `json:"jsonrpc"` 46 Method string `json:"method"` 47 } 48 49 func writeReponse(response http.ResponseWriter, answer map[string]interface{}) { 50 serJSON, err := json.MarshalIndent(answer, "", " ") 51 if err != nil { 52 log.Errorf("Can't serialize response\n") 53 } 54 var newLine byte = '\n' 55 _, err = response.Write(append(serJSON, newLine)) 56 if err != nil { 57 log.Errorf("Can't write response\n") 58 } 59 } 60 61 func FakeHandler(response http.ResponseWriter, req *http.Request) { 62 response.Header().Add("Content-Type", "application/json") 63 64 params := api.Request{} 65 _, err := api.UnmarshalRequest(req, ¶ms) 66 if err != nil { 67 log.Errorf("Can't read request\n") 68 return 69 } 70 71 answer := map[string]interface{}{} 72 if params.Method == "CreateMember" { 73 answer["reference"] = TESTREFERENCE 74 } else { 75 answer["random_data"] = TESTSEED 76 } 77 78 writeReponse(response, answer) 79 } 80 81 func FakeRPCHandler(response http.ResponseWriter, req *http.Request) { 82 response.Header().Add("Content-Type", "application/json") 83 answer := map[string]interface{}{ 84 "jsonrpc": "2.0", 85 "id": "", 86 } 87 rpcReq := rpcRequest{} 88 _, err := api.UnmarshalRequest(req, &rpcReq) 89 if err != nil { 90 log.Errorf("Can't read request\n") 91 return 92 } 93 94 switch rpcReq.Method { 95 case "status.Get": 96 answer["result"] = testStatusResponse 97 case "info.Get": 98 answer["result"] = testInfoResponse 99 case "seed.Get": 100 answer["result"] = testSeedResponse 101 } 102 writeReponse(response, answer) 103 } 104 105 const callLOCATION = "/api/call" 106 const rpcLOCATION = "/api/rpc" 107 const PORT = "12221" 108 const HOST = "127.0.0.1" 109 const URL = "http://" + HOST + ":" + PORT + "/api" 110 111 var server = &http.Server{Addr: ":" + PORT} 112 113 func waitForStart() error { 114 numAttempts := 5 115 116 for ; numAttempts > 0; numAttempts-- { 117 conn, _ := net.DialTimeout("tcp", net.JoinHostPort(HOST, PORT), time.Millisecond*50) 118 if conn != nil { 119 conn.Close() 120 break 121 } 122 } 123 if numAttempts == 0 { 124 return errors.New("Problem with launching test api: couldn't wait more") 125 } 126 127 return nil 128 } 129 130 func startServer() error { 131 server := &http.Server{} 132 listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 12221}) 133 if err != nil { 134 return errors.Wrap(err, "error creating listener") 135 } 136 go server.Serve(listener) 137 138 return nil 139 } 140 141 func setup() error { 142 fh := FakeHandler 143 fRPCh := FakeRPCHandler 144 http.HandleFunc(callLOCATION, fh) 145 http.HandleFunc(rpcLOCATION, fRPCh) 146 log.Info("Starting Test api server ...") 147 148 err := startServer() 149 if err != nil { 150 log.Error("Problem with starting test server: ", err) 151 return errors.Wrap(err, "[ setup ]") 152 } 153 154 err = waitForStart() 155 if err != nil { 156 log.Error("Can't start api: ", err) 157 return errors.Wrap(err, "[ setup ]") 158 } 159 160 return nil 161 } 162 163 func teardown() { 164 const timeOut = 2 165 log.Infof("Shutting down test server gracefully ...(waiting for %d seconds)", timeOut) 166 ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeOut)*time.Second) 167 defer cancel() 168 err := server.Shutdown(ctx) 169 if err != nil { 170 fmt.Println("STOPPING TEST SERVER:", err) 171 172 } 173 } 174 175 func testMainWrapper(m *testing.M) int { 176 err := setup() 177 defer teardown() 178 if err != nil { 179 fmt.Println("error while setup, skip tests: ", err) 180 return 1 181 } 182 code := m.Run() 183 return code 184 } 185 186 func TestMain(m *testing.M) { 187 os.Exit(testMainWrapper(m)) 188 } 189 190 func TestGetSeed(t *testing.T) { 191 seed, err := GetSeed(URL) 192 require.NoError(t, err) 193 decodedSeed, err := base64.StdEncoding.DecodeString(TESTSEED) 194 require.NoError(t, err) 195 require.Equal(t, decodedSeed, seed) 196 } 197 198 func TestGetResponseBodyEmpty(t *testing.T) { 199 _, err := GetResponseBody("test", PostParams{}) 200 require.EqualError(t, err, "[ getResponseBody ] Problem with sending request: Post test: unsupported protocol scheme \"\"") 201 } 202 203 func TestGetResponseBodyBadHttpStatus(t *testing.T) { 204 _, err := GetResponseBody(URL+"TEST", PostParams{}) 205 require.EqualError(t, err, "[ getResponseBody ] Bad http response code: 404") 206 } 207 208 func TestGetResponseBody(t *testing.T) { 209 data, err := GetResponseBody(URL+"/call", PostParams{}) 210 require.NoError(t, err) 211 require.Contains(t, string(data), `"random_data": "VGVzdA=="`) 212 } 213 214 func TestSetVerbose(t *testing.T) { 215 require.False(t, verbose) 216 SetVerbose(true) 217 require.True(t, verbose) 218 } 219 220 func readConfigs(t *testing.T) (*UserConfigJSON, *RequestConfigJSON) { 221 userConf, err := ReadUserConfigFromFile("testdata/userConfig.json") 222 require.NoError(t, err) 223 reqConf, err := ReadRequestConfigFromFile("testdata/requestConfig.json") 224 require.NoError(t, err) 225 226 return userConf, reqConf 227 } 228 229 func TestSend(t *testing.T) { 230 ctx := inslogger.ContextWithTrace(context.Background(), "TestSend") 231 userConf, reqConf := readConfigs(t) 232 resp, err := Send(ctx, URL, userConf, reqConf) 233 require.NoError(t, err) 234 require.Contains(t, string(resp), TESTREFERENCE) 235 } 236 237 func TestSendWithSeed(t *testing.T) { 238 ctx := inslogger.ContextWithTrace(context.Background(), "TestSendWithSeed") 239 userConf, reqConf := readConfigs(t) 240 resp, err := SendWithSeed(ctx, URL+"/call", userConf, reqConf, []byte(TESTSEED)) 241 require.NoError(t, err) 242 require.Contains(t, string(resp), TESTREFERENCE) 243 } 244 245 func TestSendWithSeed_WithBadUrl(t *testing.T) { 246 ctx := inslogger.ContextWithTrace(context.Background(), "TestSendWithSeed_WithBadUrl") 247 userConf, reqConf := readConfigs(t) 248 _, err := SendWithSeed(ctx, URL+"TTT", userConf, reqConf, []byte(TESTSEED)) 249 require.EqualError(t, err, "[ Send ] Problem with sending target request: [ getResponseBody ] Bad http response code: 404") 250 } 251 252 func TestSendWithSeed_NilConfigs(t *testing.T) { 253 ctx := inslogger.ContextWithTrace(context.Background(), "TestSendWithSeed_NilConfigs") 254 _, err := SendWithSeed(ctx, URL, nil, nil, []byte(TESTSEED)) 255 require.EqualError(t, err, "[ Send ] Configs must be initialized") 256 } 257 258 func TestInfo(t *testing.T) { 259 resp, err := Info(URL) 260 require.NoError(t, err) 261 require.Equal(t, resp, &testInfoResponse) 262 } 263 264 func TestStatus(t *testing.T) { 265 resp, err := Status(URL) 266 require.NoError(t, err) 267 require.Equal(t, resp, &testStatusResponse) 268 }