github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/access/rest/routes/scripts_test.go (about)

     1  package routes
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"fmt"
     8  	"net/http"
     9  	"net/url"
    10  	"testing"
    11  
    12  	mocks "github.com/stretchr/testify/mock"
    13  	"google.golang.org/grpc/codes"
    14  	"google.golang.org/grpc/status"
    15  
    16  	"github.com/onflow/flow-go/access/mock"
    17  	"github.com/onflow/flow-go/engine/access/rest/util"
    18  	"github.com/onflow/flow-go/model/flow"
    19  )
    20  
    21  func scriptReq(id string, height string, body interface{}) *http.Request {
    22  	u, _ := url.ParseRequestURI("/v1/scripts")
    23  	q := u.Query()
    24  
    25  	if id != "" {
    26  		q.Add("block_id", id)
    27  	}
    28  	if height != "" {
    29  		q.Add("block_height", height)
    30  	}
    31  
    32  	u.RawQuery = q.Encode()
    33  
    34  	jsonBody, _ := json.Marshal(body)
    35  	req, _ := http.NewRequest("POST", u.String(), bytes.NewBuffer(jsonBody))
    36  
    37  	return req
    38  }
    39  
    40  func TestScripts(t *testing.T) {
    41  	validCode := []byte(`access(all) fun main(foo: String): String { return foo }`)
    42  	validArgs := []byte(`{ "type": "String", "value": "hello world" }`)
    43  	validBody := map[string]interface{}{
    44  		"script":    util.ToBase64(validCode),
    45  		"arguments": []string{util.ToBase64(validArgs)},
    46  	}
    47  
    48  	t.Run("get by Latest height", func(t *testing.T) {
    49  		backend := &mock.API{}
    50  		backend.Mock.
    51  			On("ExecuteScriptAtLatestBlock", mocks.Anything, validCode, [][]byte{validArgs}).
    52  			Return([]byte("hello world"), nil)
    53  
    54  		req := scriptReq("", sealedHeightQueryParam, validBody)
    55  		assertOKResponse(t, req, fmt.Sprintf(
    56  			"\"%s\"",
    57  			base64.StdEncoding.EncodeToString([]byte(`hello world`)),
    58  		), backend)
    59  	})
    60  
    61  	t.Run("get by height", func(t *testing.T) {
    62  		backend := &mock.API{}
    63  		height := uint64(1337)
    64  
    65  		backend.Mock.
    66  			On("ExecuteScriptAtBlockHeight", mocks.Anything, height, validCode, [][]byte{validArgs}).
    67  			Return([]byte("hello world"), nil)
    68  
    69  		req := scriptReq("", fmt.Sprintf("%d", height), validBody)
    70  		assertOKResponse(t, req, fmt.Sprintf(
    71  			"\"%s\"",
    72  			base64.StdEncoding.EncodeToString([]byte(`hello world`)),
    73  		), backend)
    74  	})
    75  
    76  	t.Run("get by ID", func(t *testing.T) {
    77  		backend := &mock.API{}
    78  		id, _ := flow.HexStringToIdentifier("222dc5dd51b9e4910f687e475f892f495f3352362ba318b53e318b4d78131312")
    79  
    80  		backend.Mock.
    81  			On("ExecuteScriptAtBlockID", mocks.Anything, id, validCode, [][]byte{validArgs}).
    82  			Return([]byte("hello world"), nil)
    83  
    84  		req := scriptReq(id.String(), "", validBody)
    85  		assertOKResponse(t, req, fmt.Sprintf(
    86  			"\"%s\"",
    87  			base64.StdEncoding.EncodeToString([]byte(`hello world`)),
    88  		), backend)
    89  	})
    90  
    91  	t.Run("get error", func(t *testing.T) {
    92  		backend := &mock.API{}
    93  		backend.Mock.
    94  			On("ExecuteScriptAtBlockHeight", mocks.Anything, uint64(1337), validCode, [][]byte{validArgs}).
    95  			Return(nil, status.Error(codes.Internal, "internal server error"))
    96  
    97  		req := scriptReq("", "1337", validBody)
    98  		assertResponse(
    99  			t,
   100  			req,
   101  			http.StatusBadRequest,
   102  			`{"code":400, "message":"Invalid Flow request: internal server error"}`,
   103  			backend,
   104  		)
   105  	})
   106  
   107  	t.Run("get invalid", func(t *testing.T) {
   108  		backend := &mock.API{}
   109  		backend.Mock.
   110  			On("ExecuteScriptAtBlockHeight", mocks.Anything, mocks.Anything, mocks.Anything, mocks.Anything).
   111  			Return(nil, nil)
   112  
   113  		tests := []struct {
   114  			id     string
   115  			height string
   116  			body   map[string]interface{}
   117  			out    string
   118  			status int
   119  		}{
   120  			{"invalidID", "", validBody, `{"code":400,"message":"invalid ID format"}`, http.StatusBadRequest},
   121  			{"", "invalid", validBody, `{"code":400,"message":"invalid height format"}`, http.StatusBadRequest},
   122  			{"", "-1", validBody, `{"code":400,"message":"invalid height format"}`, http.StatusBadRequest},
   123  			{"", "1337", nil, `{"code":400,"message":"request body must not be empty"}`, http.StatusBadRequest},
   124  		}
   125  
   126  		for _, test := range tests {
   127  			req := scriptReq(test.id, test.height, test.body)
   128  			assertResponse(t, req, http.StatusBadRequest, test.out, backend)
   129  		}
   130  	})
   131  }