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 }