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

     1  package routes
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"strings"
     8  	"testing"
     9  
    10  	"google.golang.org/grpc/codes"
    11  	"google.golang.org/grpc/status"
    12  
    13  	mocks "github.com/stretchr/testify/mock"
    14  
    15  	"github.com/onflow/flow-go/access/mock"
    16  	"github.com/onflow/flow-go/engine/access/rest/util"
    17  	"github.com/onflow/flow-go/model/flow"
    18  	"github.com/onflow/flow-go/utils/unittest"
    19  )
    20  
    21  func getResultByIDReq(id string, blockIDs []string) *http.Request {
    22  	endpoint := "/v1/execution_results"
    23  
    24  	var u string
    25  	if id != "" {
    26  		u = fmt.Sprintf("%s/%s", endpoint, id)
    27  	} else if len(blockIDs) > 0 {
    28  		p, _ := url.Parse(endpoint)
    29  		q := p.Query()
    30  		q.Add("block_id", strings.Join(blockIDs, ","))
    31  		p.RawQuery = q.Encode()
    32  		u = p.String()
    33  	}
    34  
    35  	req, _ := http.NewRequest("GET", u, nil)
    36  	return req
    37  }
    38  
    39  func TestGetResultByID(t *testing.T) {
    40  	t.Run("get by ID", func(t *testing.T) {
    41  		backend := &mock.API{}
    42  		result := unittest.ExecutionResultFixture()
    43  		id := unittest.IdentifierFixture()
    44  		backend.Mock.
    45  			On("GetExecutionResultByID", mocks.Anything, id).
    46  			Return(result, nil).
    47  			Once()
    48  		req := getResultByIDReq(id.String(), nil)
    49  
    50  		expected := executionResultExpectedStr(result)
    51  		assertOKResponse(t, req, expected, backend)
    52  		mocks.AssertExpectationsForObjects(t, backend)
    53  	})
    54  
    55  	t.Run("get by ID not found", func(t *testing.T) {
    56  		backend := &mock.API{}
    57  		id := unittest.IdentifierFixture()
    58  		backend.Mock.
    59  			On("GetExecutionResultByID", mocks.Anything, id).
    60  			Return(nil, status.Error(codes.NotFound, "block not found")).
    61  			Once()
    62  
    63  		req := getResultByIDReq(id.String(), nil)
    64  		assertResponse(t, req, http.StatusNotFound, `{"code":404,"message":"Flow resource not found: block not found"}`, backend)
    65  		mocks.AssertExpectationsForObjects(t, backend)
    66  	})
    67  }
    68  
    69  func TestGetResultBlockID(t *testing.T) {
    70  
    71  	t.Run("get by block ID", func(t *testing.T) {
    72  		backend := &mock.API{}
    73  		blockID := unittest.IdentifierFixture()
    74  		result := unittest.ExecutionResultFixture(unittest.WithExecutionResultBlockID(blockID))
    75  
    76  		backend.Mock.
    77  			On("GetExecutionResultForBlockID", mocks.Anything, blockID).
    78  			Return(result, nil).
    79  			Once()
    80  
    81  		req := getResultByIDReq("", []string{blockID.String()})
    82  
    83  		expected := fmt.Sprintf(`[%s]`, executionResultExpectedStr(result))
    84  		assertOKResponse(t, req, expected, backend)
    85  		mocks.AssertExpectationsForObjects(t, backend)
    86  	})
    87  
    88  	t.Run("get by block ID not found", func(t *testing.T) {
    89  		backend := &mock.API{}
    90  		blockID := unittest.IdentifierFixture()
    91  		backend.Mock.
    92  			On("GetExecutionResultForBlockID", mocks.Anything, blockID).
    93  			Return(nil, status.Error(codes.NotFound, "block not found")).
    94  			Once()
    95  
    96  		req := getResultByIDReq("", []string{blockID.String()})
    97  		assertResponse(t, req, http.StatusNotFound, `{"code":404,"message":"Flow resource not found: block not found"}`, backend)
    98  		mocks.AssertExpectationsForObjects(t, backend)
    99  	})
   100  }
   101  
   102  func executionResultExpectedStr(result *flow.ExecutionResult) string {
   103  	chunks := make([]string, len(result.Chunks))
   104  	for i, chunk := range result.Chunks {
   105  		chunks[i] = fmt.Sprintf(`{
   106  				"block_id": "%s",
   107  				"collection_index": "%d",
   108  				"start_state": "%s",
   109  				"end_state": "%s",
   110  				"number_of_transactions": "%d",
   111  				"event_collection": "%s",
   112  				"index": "%d",
   113  				"total_computation_used": "%d"
   114  			}`, chunk.BlockID, chunk.CollectionIndex, util.ToBase64(chunk.StartState[:]), util.ToBase64(chunk.EndState[:]),
   115  			chunk.NumberOfTransactions, chunk.EventCollection.String(), chunk.Index, chunk.TotalComputationUsed)
   116  	}
   117  	chunksStr := fmt.Sprintf("[%s]", strings.Join(chunks, ","))
   118  	expected := fmt.Sprintf(`{
   119  			"id": "%s",
   120  			"block_id": "%s",
   121  			"events": [],
   122              "chunks": %s,
   123              "previous_result_id": "%s",
   124  			"_links": {
   125  				"_self": "/v1/execution_results/%s"
   126  			}
   127  		}`, result.ID(), result.BlockID, chunksStr, result.PreviousResultID.String(), result.ID())
   128  	return expected
   129  }