github.com/core-coin/go-core/v2@v2.1.9/graphql/graphql_test.go (about)

     1  // Copyright 2019 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser 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  // The go-core library 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 Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package graphql
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"net/http"
    23  	"strings"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  
    29  	"github.com/core-coin/go-core/v2/consensus/cryptore"
    30  
    31  	"github.com/core-coin/go-core/v2/common"
    32  	"github.com/core-coin/go-core/v2/core"
    33  	"github.com/core-coin/go-core/v2/miner"
    34  	"github.com/core-coin/go-core/v2/node"
    35  	"github.com/core-coin/go-core/v2/xcb"
    36  )
    37  
    38  func TestBuildSchema(t *testing.T) {
    39  	stack, err := node.New(&node.DefaultConfig)
    40  	if err != nil {
    41  		t.Fatalf("could not create new node: %v", err)
    42  	}
    43  	// Make sure the schema can be parsed and matched up to the object model.
    44  	if err := newHandler(stack, nil, []string{}, []string{}); err != nil {
    45  		t.Errorf("Could not construct GraphQL handler: %v", err)
    46  	}
    47  }
    48  
    49  // Tests that a graphQL request is successfully handled when graphql is enabled on the specified endpoint
    50  func TestGraphQLHTTPOnSamePort_GQLRequest_Successful(t *testing.T) {
    51  	stack := createNode(t, true)
    52  	defer stack.Close()
    53  	// start node
    54  	if err := stack.Start(); err != nil {
    55  		t.Fatalf("could not start node: %v", err)
    56  	}
    57  	// create http request
    58  	body := strings.NewReader("{\"query\": \"{block{number}}\",\"variables\": null}")
    59  	gqlReq, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s/graphql", "127.0.0.1:9393"), body)
    60  	if err != nil {
    61  		t.Error("could not issue new http request ", err)
    62  	}
    63  	gqlReq.Header.Set("Content-Type", "application/json")
    64  	// read from response
    65  	resp := doHTTPRequest(t, gqlReq)
    66  	bodyBytes, err := ioutil.ReadAll(resp.Body)
    67  	if err != nil {
    68  		t.Fatalf("could not read from response body: %v", err)
    69  	}
    70  	expected := "{\"data\":{\"block\":{\"number\":\"0x0\"}}}"
    71  	assert.Equal(t, 200, resp.StatusCode)
    72  	assert.Equal(t, expected, string(bodyBytes))
    73  }
    74  
    75  // Tests that a graphQL request is not handled successfully when graphql is not enabled on the specified endpoint
    76  func TestGraphQLHTTPOnSamePort_GQLRequest_Unsuccessful(t *testing.T) {
    77  	stack := createNode(t, false)
    78  	defer stack.Close()
    79  	if err := stack.Start(); err != nil {
    80  		t.Fatalf("could not start node: %v", err)
    81  	}
    82  
    83  	// create http request
    84  	body := strings.NewReader("{\"query\": \"{block{number}}\",\"variables\": null}")
    85  	gqlReq, err := http.NewRequest(http.MethodPost, fmt.Sprintf("http://%s/graphql", "127.0.0.1:9393"), body)
    86  	if err != nil {
    87  		t.Error("could not issue new http request ", err)
    88  	}
    89  	gqlReq.Header.Set("Content-Type", "application/json")
    90  	// read from response
    91  	resp := doHTTPRequest(t, gqlReq)
    92  	// make sure the request is not handled successfully
    93  	assert.Equal(t, http.StatusNotFound, resp.StatusCode)
    94  }
    95  
    96  // Tests that 400 is returned when an invalid RPC request is made.
    97  func TestGraphQL_BadRequest(t *testing.T) {
    98  	stack := createNode(t, true)
    99  	defer stack.Close()
   100  	// start node
   101  	if err := stack.Start(); err != nil {
   102  		t.Fatalf("could not start node: %v", err)
   103  	}
   104  	// create http request
   105  	body := strings.NewReader("{\"query\": \"{bleh{number}}\",\"variables\": null}")
   106  	gqlReq, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s/graphql", "127.0.0.1:9393"), body)
   107  	if err != nil {
   108  		t.Error("could not issue new http request ", err)
   109  	}
   110  	gqlReq.Header.Set("Content-Type", "application/json")
   111  	// read from response
   112  	resp := doHTTPRequest(t, gqlReq)
   113  	bodyBytes, err := ioutil.ReadAll(resp.Body)
   114  	if err != nil {
   115  		t.Fatalf("could not read from response body: %v", err)
   116  	}
   117  	expected := "{\"errors\":[{\"message\":\"Cannot query field \\\"bleh\\\" on type \\\"Query\\\".\",\"locations\":[{\"line\":1,\"column\":2}]}]}"
   118  	assert.Equal(t, expected, string(bodyBytes))
   119  	assert.Equal(t, 400, resp.StatusCode)
   120  }
   121  
   122  func createNode(t *testing.T, gqlEnabled bool) *node.Node {
   123  	stack, err := node.New(&node.Config{
   124  		HTTPHost: "127.0.0.1",
   125  		HTTPPort: 9393,
   126  		WSHost:   "127.0.0.1",
   127  		WSPort:   9393,
   128  	})
   129  	if err != nil {
   130  		t.Fatalf("could not create node: %v", err)
   131  	}
   132  	if !gqlEnabled {
   133  		return stack
   134  	}
   135  
   136  	createGQLService(t, stack, "127.0.0.1:9393")
   137  
   138  	return stack
   139  }
   140  
   141  func createGQLService(t *testing.T, stack *node.Node, endpoint string) {
   142  	addr, err := common.HexToAddress("cb27de521e43741cf785cbad450d5649187b9612018f")
   143  	if err != nil {
   144  		t.Error(err)
   145  	}
   146  	// create backend (use a config which is light on mem consumption)
   147  	xcbConf := &xcb.Config{
   148  		Genesis: core.DeveloperGenesisBlock(15, common.Address{}),
   149  		Miner: miner.Config{
   150  			Corebase: addr,
   151  		},
   152  		Cryptore: cryptore.Config{
   153  			PowMode: cryptore.ModeTest,
   154  		},
   155  		NetworkId:               1,
   156  		TrieCleanCache:          5,
   157  		TrieCleanCacheJournal:   "triecache",
   158  		TrieCleanCacheRejournal: 60 * time.Minute,
   159  		TrieDirtyCache:          5,
   160  		TrieTimeout:             60 * time.Minute,
   161  		SnapshotCache:           5,
   162  	}
   163  	xcbBackend, err := xcb.New(stack, xcbConf)
   164  	if err != nil {
   165  		t.Fatalf("could not create xcb backend: %v", err)
   166  	}
   167  
   168  	// create gql service
   169  	err = New(stack, xcbBackend.APIBackend, []string{}, []string{})
   170  	if err != nil {
   171  		t.Fatalf("could not create graphql service: %v", err)
   172  	}
   173  }
   174  
   175  func doHTTPRequest(t *testing.T, req *http.Request) *http.Response {
   176  	client := &http.Client{}
   177  	resp, err := client.Do(req)
   178  	if err != nil {
   179  		t.Fatal("could not issue a GET request to the given endpoint", err)
   180  
   181  	}
   182  	return resp
   183  }