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, &params)
    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  }