From 9e06b5a48828d12771537a5fc59b32aec7161a93 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Mon, 13 Jan 2020 13:56:35 +0200 Subject: [PATCH 01/10] Replace vmValuesProcessor with scQueryServiceProxy. Use vm-values implementation and tests from elrond-go. --- api/mock/facade.go | 10 +- api/vmValues/interface.go | 6 - api/vmValues/routes.go | 135 ++++++--- api/vmValues/routes_test.go | 451 ++++++++++++---------------- cmd/proxy/main.go | 2 +- data/vmValues.go | 5 +- facade/elrondProxyFacade.go | 34 ++- facade/errors.go | 4 +- facade/interface.go | 8 +- go.mod | 1 + process/scQueryServiceProxy.go | 85 ++++++ process/scQueryServiceProxy_test.go | 166 ++++++++++ process/vmValuesProcessor.go | 83 ----- process/vmValuesProcessor_test.go | 140 --------- testing/testHttpServer.go | 3 +- 15 files changed, 569 insertions(+), 564 deletions(-) delete mode 100644 api/vmValues/interface.go create mode 100644 process/scQueryServiceProxy.go create mode 100644 process/scQueryServiceProxy_test.go delete mode 100644 process/vmValuesProcessor.go delete mode 100644 process/vmValuesProcessor_test.go diff --git a/api/mock/facade.go b/api/mock/facade.go index 46af2f25..fe162579 100644 --- a/api/mock/facade.go +++ b/api/mock/facade.go @@ -3,7 +3,9 @@ package mock import ( "math/big" + "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-proxy-go/data" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" ) // Facade is the mock implementation of a node's router handler @@ -12,7 +14,7 @@ type Facade struct { SendTransactionHandler func(tx *data.Transaction) (int, string, error) SendMultipleTransactionsHandler func(txs []*data.Transaction) (uint64, error) SendUserFundsCalled func(receiver string, value *big.Int) error - GetVmValueHandler func(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) + ExecuteSCQueryHandler func(query *process.SCQuery) (*vmcommon.VMOutput, error) GetHeartbeatDataHandler func() (*data.HeartbeatResponse, error) ValidatorStatisticsHandler func() (map[string]*data.ValidatorApiResponse, error) } @@ -42,9 +44,9 @@ func (f *Facade) SendUserFunds(receiver string, value *big.Int) error { return f.SendUserFundsCalled(receiver, value) } -// GetVmValue is the mock implementation of a handler's GetVmValue method -func (f *Facade) GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) { - return f.GetVmValueHandler(resType, address, funcName, argsBuff...) +// ExecuteSCQuery is a mock implementation. +func (f *Facade) ExecuteSCQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { + return f.ExecuteSCQueryHandler(query) } // GetHeartbeatData is the mock implementation of a handler's GetHeartbeatData method diff --git a/api/vmValues/interface.go b/api/vmValues/interface.go deleted file mode 100644 index 010fe057..00000000 --- a/api/vmValues/interface.go +++ /dev/null @@ -1,6 +0,0 @@ -package vmValues - -// FacadeHandler interface defines methods that can be used from `elrondFacade` context variable -type FacadeHandler interface { - GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) -} diff --git a/api/vmValues/routes.go b/api/vmValues/routes.go index 5ddab4fc..c3e39271 100644 --- a/api/vmValues/routes.go +++ b/api/vmValues/routes.go @@ -2,17 +2,22 @@ package vmValues import ( "encoding/hex" - "errors" "fmt" - "math/big" "net/http" + "github.com/ElrondNetwork/elrond-go/process" apiErrors "github.com/ElrondNetwork/elrond-proxy-go/api/errors" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/gin-gonic/gin" ) -// VmValueRequest represents the structure on which user input for generating a new transaction will validate against -type VmValueRequest struct { +// FacadeHandler interface defines methods that can be used from `elrondFacade` context variable +type FacadeHandler interface { + ExecuteSCQuery(*process.SCQuery) (*vmcommon.VMOutput, error) +} + +// VMValueRequest represents the structure on which user input for generating a new transaction will validate against +type VMValueRequest struct { ScAddress string `form:"scAddress" json:"scAddress"` FuncName string `form:"funcName" json:"funcName"` Args []string `form:"args" json:"args"` @@ -20,78 +25,108 @@ type VmValueRequest struct { // Routes defines address related routes func Routes(router *gin.RouterGroup) { - router.POST("/hex", GetVmValueAsHexBytes) - router.POST("/string", GetVmValueAsString) - router.POST("/int", GetVmValueAsBigInt) + router.POST("/hex", getHex) + router.POST("/string", getString) + router.POST("/int", getInt) + router.POST("/query", executeQuery) } -func vmValueFromAccount(c *gin.Context, resType string) ([]byte, int, error) { - ef, ok := c.MustGet("elrondProxyFacade").(FacadeHandler) - if !ok { - return nil, http.StatusInternalServerError, apiErrors.ErrInvalidAppContext - } +// getHex returns the data as bytes, hex-encoded +func getHex(context *gin.Context) { + doGetVMValue(context, vmcommon.AsHex) +} - var gval = VmValueRequest{} - err := c.ShouldBindJSON(&gval) - if err != nil { - return nil, http.StatusBadRequest, err - } +// getString returns the data as string +func getString(context *gin.Context) { + doGetVMValue(context, vmcommon.AsString) +} - argsBuff := make([][]byte, 0) - for _, arg := range gval.Args { - buff, err := hex.DecodeString(arg) - if err != nil { - return nil, - http.StatusBadRequest, - errors.New(fmt.Sprintf("'%s' is not a valid hex string: %s", arg, err.Error())) - } +// getInt returns the data as big int +func getInt(context *gin.Context) { + doGetVMValue(context, vmcommon.AsBigIntString) +} + +func doGetVMValue(context *gin.Context, asType vmcommon.ReturnDataKind) { + vmOutput, err := doExecuteQuery(context) - argsBuff = append(argsBuff, buff) + if err != nil { + returnBadRequest(context, "doGetVMValue", err) + return } - returnedData, err := ef.GetVmValue(resType, gval.ScAddress, gval.FuncName, argsBuff...) + returnData, err := vmOutput.GetFirstReturnData(asType) if err != nil { - return nil, http.StatusBadRequest, err + returnBadRequest(context, "doGetVMValue", err) + return } - return returnedData, http.StatusOK, nil + returnOkResponse(context, returnData) } -// GetVmValueAsHexBytes returns the data as byte slice -func GetVmValueAsHexBytes(c *gin.Context) { - data, status, err := vmValueFromAccount(c, "hex") +// executeQuery returns the data as string +func executeQuery(context *gin.Context) { + vmOutput, err := doExecuteQuery(context) if err != nil { - c.JSON(status, gin.H{"error": fmt.Sprintf("get vm value as hex bytes: %s", err)}) + returnBadRequest(context, "executeQuery", err) return } - c.JSON(http.StatusOK, gin.H{"data": hex.EncodeToString(data)}) + returnOkResponse(context, vmOutput) } -// GetVmValueAsString returns the data as string -func GetVmValueAsString(c *gin.Context) { - data, status, err := vmValueFromAccount(c, "string") +func doExecuteQuery(context *gin.Context) (*vmcommon.VMOutput, error) { + facade, ok := context.MustGet("elrondFacade").(FacadeHandler) + if !ok { + return nil, apiErrors.ErrInvalidAppContext + } + + request := VMValueRequest{} + err := context.ShouldBindJSON(&request) if err != nil { - c.JSON(status, gin.H{"error": fmt.Sprintf("get vm value as string: %s", err)}) - return + return nil, err } - c.JSON(http.StatusOK, gin.H{"data": string(data)}) + command, err := createSCQuery(&request) + if err != nil { + return nil, err + } + + vmOutput, err := facade.ExecuteSCQuery(command) + if err != nil { + return nil, err + } + + return vmOutput, nil } -// GetVmValueAsBigInt returns the data as big int -func GetVmValueAsBigInt(c *gin.Context) { - data, status, err := vmValueFromAccount(c, "int") +func createSCQuery(request *VMValueRequest) (*process.SCQuery, error) { + decodedAddress, err := hex.DecodeString(request.ScAddress) if err != nil { - c.JSON(status, gin.H{"error": fmt.Sprintf("get vm value as big int: %s", err)}) - return + return nil, fmt.Errorf("'%s' is not a valid hex string: %s", request.ScAddress, err.Error()) } - value, ok := big.NewInt(0).SetString(string(data), 10) - if !ok { - c.JSON(status, gin.H{"error": fmt.Sprintf("value %s could not be converted to a big int", string(data))}) - return + arguments := make([][]byte, len(request.Args)) + for i, arg := range request.Args { + argBytes, err := hex.DecodeString(arg) + if err != nil { + return nil, fmt.Errorf("'%s' is not a valid hex string: %s", arg, err.Error()) + } + + arguments[i] = append(arguments[i], argBytes...) } - c.JSON(http.StatusOK, gin.H{"data": value.String()}) + return &process.SCQuery{ + ScAddress: decodedAddress, + FuncName: request.FuncName, + Arguments: arguments, + }, nil +} + +func returnBadRequest(context *gin.Context, errScope string, err error) { + message := fmt.Sprintf("%s: %s", errScope, err) + context.JSON(http.StatusBadRequest, gin.H{"error": message}) +} + +func returnOkResponse(context *gin.Context, data interface{}) { + context.JSON(http.StatusOK, gin.H{"data": data}) } diff --git a/api/vmValues/routes_test.go b/api/vmValues/routes_test.go index 148fca8d..854be1a2 100644 --- a/api/vmValues/routes_test.go +++ b/api/vmValues/routes_test.go @@ -1,373 +1,310 @@ -package vmValues_test +package vmValues import ( "bytes" "encoding/hex" - "encoding/json" "errors" "fmt" "io" + "math/big" "net/http" "net/http/httptest" "testing" - apiErrors "github.com/ElrondNetwork/elrond-go/api/errors" - "github.com/ElrondNetwork/elrond-proxy-go/api" - "github.com/ElrondNetwork/elrond-proxy-go/api/mock" - "github.com/ElrondNetwork/elrond-proxy-go/api/vmValues" + "github.com/ElrondNetwork/elrond-go/api/middleware" + "github.com/ElrondNetwork/elrond-go/api/mock" + "github.com/ElrondNetwork/elrond-go/process" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin/json" "github.com/stretchr/testify/assert" ) -type GeneralResponse struct { +type simpleResponse struct { Data string `json:"data"` Error string `json:"error"` } +type vmOutputResponse struct { + Data *vmcommon.VMOutput `json:"data"` + Error string `json:"error"` +} + func init() { gin.SetMode(gin.TestMode) } -func loadResponse(rsp io.Reader, destination interface{}) { - jsonParser := json.NewDecoder(rsp) - err := jsonParser.Decode(destination) - if err != nil { - logError(err) - } -} +const DummyScAddress = "00000000000000000500fabd9501b7e5353de57a4e319857c2fb99089770720a" -func logError(err error) { - if err != nil { - fmt.Println(err) - } -} +func TestGetDataValueAsHexBytes(t *testing.T) { + t.Parallel() -func startNodeServer(handler vmValues.FacadeHandler) *gin.Engine { - ws := gin.New() - ws.Use(cors.Default()) - getValuesRoute := ws.Group("/vm-values") + valueBuff, _ := hex.DecodeString("DEADBEEF") - if handler != nil { - getValuesRoute.Use(api.WithElrondProxyFacade(handler)) + facade := mock.Facade{ + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{ + ReturnData: [][]byte{valueBuff}, + }, nil + }, } - vmValues.Routes(getValuesRoute) - return ws -} + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } -func startNodeServerWrongFacade() *gin.Engine { - ws := gin.New() - ws.Use(cors.Default()) - ws.Use(func(c *gin.Context) { - c.Set("elrondProxyFacade", mock.WrongFacade{}) - }) - getValuesRoute := ws.Group("/vm-values") - vmValues.Routes(getValuesRoute) + response := simpleResponse{} + statusCode := doPost(&facade, "/vm-values/hex", request, &response) - return ws + assert.Equal(t, http.StatusOK, statusCode) + assert.Equal(t, "", response.Error) + assert.Equal(t, hex.EncodeToString(valueBuff), response.Data) } -//------- GetDataValueAsHexBytes - -func TestGetDataValueAsHexBytes_WithWrongFacadeShouldErr(t *testing.T) { +func TestGetDataValueAsString(t *testing.T) { t.Parallel() - ws := startNodeServerWrongFacade() + valueBuff := "DEADBEEF" - jsonStr := `{"scAddress":"DEADBEEF","funcName":"DEADBEEF","args":[]}` - req, _ := http.NewRequest("POST", "/vm-values/hex", bytes.NewBuffer([]byte(jsonStr))) + facade := mock.Facade{ + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{ + ReturnData: [][]byte{[]byte(valueBuff)}, + }, nil + }, + } - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } - response := GeneralResponse{} - loadResponse(resp.Body, &response) + response := simpleResponse{} + statusCode := doPost(&facade, "/vm-values/string", request, &response) - assert.Contains(t, response.Error, apiErrors.ErrInvalidAppContext.Error()) + assert.Equal(t, http.StatusOK, statusCode) + assert.Equal(t, "", response.Error) + assert.Equal(t, valueBuff, response.Data) } -func TestGetDataValueAsHexBytes_BadRequestShouldErr(t *testing.T) { +func TestGetDataValueAsInt(t *testing.T) { t.Parallel() + value := "1234567" + facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - assert.Fail(t, "should have not called this") - return nil, nil + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + returnData := big.NewInt(0) + returnData.SetString(value, 10) + return &vmcommon.VMOutput{ + ReturnData: [][]byte{returnData.Bytes()}, + }, nil }, } - ws := startNodeServer(&facade) - - jsonStr := `{"this should error"}` - req, _ := http.NewRequest("POST", "/vm-values/hex", bytes.NewBuffer([]byte(jsonStr))) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } - response := GeneralResponse{} - loadResponse(resp.Body, &response) + response := simpleResponse{} + statusCode := doPost(&facade, "/vm-values/int", request, &response) - assert.Contains(t, response.Error, "invalid character") + assert.Equal(t, http.StatusOK, statusCode) + assert.Equal(t, "", response.Error) + assert.Equal(t, value, response.Data) } -func TestGetDataValueAsHexBytes_ArgumentIsNotHexShouldErr(t *testing.T) { +func TestExecuteQuery(t *testing.T) { t.Parallel() - scAddress := "sc address" - fName := "function" - args := []string{"not a hex argument"} - errUnexpected := errors.New("unexpected error") - valueBuff, _ := hex.DecodeString("DEADBEEF") - facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - if address == scAddress && funcName == fName && len(argsBuff) == len(args) { - paramsOk := true - for idx, arg := range args { - if arg != string(argsBuff[idx]) { - paramsOk = false - } - } - - if paramsOk { - return valueBuff, nil - } - } - - return nil, errUnexpected + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + + return &vmcommon.VMOutput{ + ReturnData: [][]byte{big.NewInt(42).Bytes()}, + }, nil }, } - ws := startNodeServer(&facade) - - argsJson, _ := json.Marshal(args) - - jsonStr := fmt.Sprintf( - `{"scAddress":"%s", "funcName":"%s", "args":%s}`, - scAddress, - fName, - argsJson) - fmt.Printf("Request: %s\n", jsonStr) + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } - req, _ := http.NewRequest("POST", "/vm-values/hex", bytes.NewBuffer([]byte(jsonStr))) + response := vmOutputResponse{} + statusCode := doPost(&facade, "/vm-values/query", request, &response) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) + assert.Equal(t, http.StatusOK, statusCode) + assert.Equal(t, "", response.Error) + assert.Equal(t, int64(42), big.NewInt(0).SetBytes(response.Data.ReturnData[0]).Int64()) +} - response := GeneralResponse{} - loadResponse(resp.Body, &response) +func TestCreateSCQuery_ArgumentIsNotHexShouldErr(t *testing.T) { + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{"bad arg"}, + } - assert.Equal(t, http.StatusBadRequest, resp.Code) - assert.Contains(t, response.Error, "not a hex argument") + _, err := createSCQuery(&request) + assert.NotNil(t, err) + assert.Contains(t, err.Error(), "'bad arg' is not a valid hex string") } -func testGetValueFacadeErrors(t *testing.T, route string) { +func TestGetDataValue_FacadeErrorsShouldErr(t *testing.T) { t.Parallel() - errExpected := errors.New("expected error") + errExpected := errors.New("no return data") facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - return nil, errExpected + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{}, nil }, } - ws := startNodeServer(&facade) - - jsonStr := `{}` - fmt.Printf("Request: %s\n", jsonStr) - - req, _ := http.NewRequest("POST", route, bytes.NewBuffer([]byte(jsonStr))) + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) + response := simpleResponse{} - response := GeneralResponse{} - loadResponse(resp.Body, &response) + statusCode := doPost(&facade, "/vm-values/hex", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) - assert.Equal(t, http.StatusBadRequest, resp.Code) + statusCode = doPost(&facade, "/vm-values/string", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) assert.Contains(t, response.Error, errExpected.Error()) -} -func TestGetDataValueAsHexBytes_FacadeErrorsShouldErr(t *testing.T) { - testGetValueFacadeErrors(t, "/vm-values/hex") + statusCode = doPost(&facade, "/vm-values/int", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) } -func TestGetDataValueAsHexBytes_WithParametersShouldReturnValueAsHex(t *testing.T) { +func TestGetDataValue_WhenBadAddress_ShouldErr(t *testing.T) { t.Parallel() - scAddress := "sc address" - fName := "function" - args := []string{"argument 1", "argument 2"} - errUnexpected := errors.New("unexpected error") - valueBuff, _ := hex.DecodeString("DEADBEEF") - + errExpected := errors.New("not a valid hex string") facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - if address == scAddress && funcName == fName && len(argsBuff) == len(args) { - paramsOk := true - for idx, arg := range args { - if arg != string(argsBuff[idx]) { - paramsOk = false - } - } - - if paramsOk { - return valueBuff, nil - } - } - - return nil, errUnexpected + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{}, nil }, } - ws := startNodeServer(&facade) - - argsHex := make([]string, len(args)) - for i := 0; i < len(args); i++ { - argsHex[i] = hex.EncodeToString([]byte(args[i])) + request := VMValueRequest{ + ScAddress: "DUMMY", + FuncName: "function", + Args: []string{}, } - argsJson, _ := json.Marshal(argsHex) - jsonStr := fmt.Sprintf( - `{"scAddress":"%s", "funcName":"%s", "args":%s}`, - scAddress, - fName, - argsJson) - fmt.Printf("Request: %s\n", jsonStr) + response := simpleResponse{} - req, _ := http.NewRequest("POST", "/vm-values/hex", bytes.NewBuffer([]byte(jsonStr))) + statusCode := doPost(&facade, "/vm-values/hex", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) +} - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) +func TestGetDataValue_WhenBadArguments_ShouldErr(t *testing.T) { + t.Parallel() - response := GeneralResponse{} - loadResponse(resp.Body, &response) + errExpected := errors.New("not a valid hex string") + facade := mock.Facade{ + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{}, nil + }, + } - assert.Equal(t, http.StatusOK, resp.Code) - assert.Equal(t, "", response.Error) - assert.Equal(t, hex.EncodeToString(valueBuff), response.Data) -} + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{"AA", "ZZ"}, + } -//------- GetDataValueAsString + response := simpleResponse{} -func TestGetDataValueAsString_FacadeErrorsShouldErr(t *testing.T) { - testGetValueFacadeErrors(t, "/vm-values/string") + statusCode := doPost(&facade, "/vm-values/hex", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) } -func TestGetDataValueAsString_WithParametersShouldReturnValueAsHex(t *testing.T) { +func TestGetDataValue_WhenNoVMReturnData_ShouldErr(t *testing.T) { t.Parallel() - scAddress := "sc address" - fName := "function" - args := []string{"argument 1", "argument 2"} - errUnexpected := errors.New("unexpected error") - valueBuff := "DEADBEEF" - + errExpected := errors.New("expected error") facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - if address == scAddress && funcName == fName && len(argsBuff) == len(args) { - paramsOk := true - for idx, arg := range args { - if arg != string(argsBuff[idx]) { - paramsOk = false - } - } - - if paramsOk { - return []byte(valueBuff), nil - } - } - - return nil, errUnexpected + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return nil, errExpected }, } - ws := startNodeServer(&facade) - - argsHex := make([]string, len(args)) - for i := 0; i < len(args); i++ { - argsHex[i] = hex.EncodeToString([]byte(args[i])) + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, } - argsJson, _ := json.Marshal(argsHex) - jsonStr := fmt.Sprintf( - `{"scAddress":"%s", "funcName":"%s", "args":%s}`, - scAddress, - fName, - argsJson) - fmt.Printf("Request: %s\n", jsonStr) + response := simpleResponse{} - req, _ := http.NewRequest("POST", "/vm-values/string", bytes.NewBuffer([]byte(jsonStr))) + statusCode := doPost(&facade, "/vm-values/hex", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) +} - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) +func TestGetDataValue_WhenBadFacade_ShouldErr(t *testing.T) { + t.Parallel() - response := GeneralResponse{} - loadResponse(resp.Body, &response) + errExpected := errors.New("invalid app context") + var facade interface{} - assert.Equal(t, http.StatusOK, resp.Code) - assert.Equal(t, "", response.Error) - assert.Equal(t, valueBuff, response.Data) -} + request := VMValueRequest{ + ScAddress: DummyScAddress, + FuncName: "function", + Args: []string{}, + } -//------- GetDataValueAsInt + response := simpleResponse{} -func TestGetDataValueAsInt_FacadeErrorsShouldErr(t *testing.T) { - testGetValueFacadeErrors(t, "/vm-values/int") + statusCode := doPost(&facade, "/vm-values/query", request, &response) + assert.Equal(t, http.StatusBadRequest, statusCode) + assert.Contains(t, response.Error, errExpected.Error()) } -func TestGetDataValueAsInt_WithParametersShouldReturnValueAsByteArray(t *testing.T) { - t.Parallel() +func doPost(facadeMock interface{}, url string, request VMValueRequest, response interface{}) int { + jsonBody, _ := json.Marshal(request) - scAddress := "sc address" - fName := "function" - args := []string{"argument 1", "argument 2"} - errUnexpected := errors.New("unexpected error") - valueBuff := "1234567" + server := startNodeServer(facadeMock) + httpRequest, _ := http.NewRequest("POST", url, bytes.NewBuffer([]byte(jsonBody))) - facade := mock.Facade{ - GetVmValueHandler: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { - if address == scAddress && funcName == fName && len(argsBuff) == len(args) { - paramsOk := true - for idx, arg := range args { - if arg != string(argsBuff[idx]) { - paramsOk = false - } - } - - if paramsOk { - return []byte(valueBuff), nil - } - } - - return nil, errUnexpected - }, - } - - ws := startNodeServer(&facade) - - argsHex := make([]string, len(args)) - for i := 0; i < len(args); i++ { - argsHex[i] = hex.EncodeToString([]byte(args[i])) - } - argsJson, _ := json.Marshal(argsHex) + responseRecorder := httptest.NewRecorder() + server.ServeHTTP(responseRecorder, httpRequest) - jsonStr := fmt.Sprintf( - `{"scAddress":"%s", "funcName":"%s", "args":%s}`, - scAddress, - fName, - argsJson) - fmt.Printf("Request: %s\n", jsonStr) + parseResponse(responseRecorder.Body, &response) + return responseRecorder.Code +} - req, _ := http.NewRequest("POST", "/vm-values/int", bytes.NewBuffer([]byte(jsonStr))) +func startNodeServer(handler interface{}) *gin.Engine { + ws := gin.New() + ws.Use(cors.Default()) + getValuesRoute := ws.Group("/vm-values") + getValuesRoute.Use(middleware.WithElrondFacade(handler)) + Routes(getValuesRoute) - resp := httptest.NewRecorder() - ws.ServeHTTP(resp, req) + return ws +} - response := GeneralResponse{} - loadResponse(resp.Body, &response) +func parseResponse(responseBody io.Reader, destination interface{}) { + jsonParser := json.NewDecoder(responseBody) - assert.Equal(t, http.StatusOK, resp.Code) - assert.Equal(t, "", response.Error) - assert.Equal(t, valueBuff, response.Data) + err := jsonParser.Decode(destination) + if err != nil { + fmt.Println(err) + } } diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index f3b6e0b3..644941b5 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -273,7 +273,7 @@ func createFacade( return nil, err } - gvpProc, err := process.NewVmValuesProcessor(bp) + gvpProc, err := process.NewSCQueryServiceProxy(bp) if err != nil { return nil, err } diff --git a/data/vmValues.go b/data/vmValues.go index 1134c78d..2d87bdf3 100644 --- a/data/vmValues.go +++ b/data/vmValues.go @@ -1,8 +1,11 @@ package data +import vmcommon "github.com/ElrondNetwork/elrond-vm-common" + // ResponseVmValue defines a wrapper over string containing returned data in hex format type ResponseVmValue struct { - HexData string `json:"data"` + Error string `json:"error"` + Data *vmcommon.VMOutput `json:"data"` } // VmValueRequest defines the request struct for values available in a VM diff --git a/facade/elrondProxyFacade.go b/facade/elrondProxyFacade.go index 58882be1..88bb13d6 100644 --- a/facade/elrondProxyFacade.go +++ b/facade/elrondProxyFacade.go @@ -3,23 +3,25 @@ package facade import ( "math/big" + "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-proxy-go/data" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" ) // ElrondProxyFacade implements the facade used in api calls type ElrondProxyFacade struct { - accountProc AccountProcessor - txProc TransactionProcessor - vmValuesProc VmValuesProcessor - heartbeatProc HeartbeatProcessor - faucetProc FaucetProcessor + accountProc AccountProcessor + txProc TransactionProcessor + scQueryService SCQueryService + heartbeatProc HeartbeatProcessor + faucetProc FaucetProcessor } // NewElrondProxyFacade creates a new ElrondProxyFacade instance func NewElrondProxyFacade( accountProc AccountProcessor, txProc TransactionProcessor, - vmValuesProc VmValuesProcessor, + scQueryService SCQueryService, heartbeatProc HeartbeatProcessor, faucetProc FaucetProcessor, ) (*ElrondProxyFacade, error) { @@ -30,8 +32,8 @@ func NewElrondProxyFacade( if txProc == nil { return nil, ErrNilTransactionProcessor } - if vmValuesProc == nil { - return nil, ErrNilVmValueProcessor + if scQueryService == nil { + return nil, ErrNilSCQueryService } if heartbeatProc == nil { return nil, ErrNilHeartbeatProcessor @@ -41,11 +43,11 @@ func NewElrondProxyFacade( } return &ElrondProxyFacade{ - accountProc: accountProc, - txProc: txProc, - vmValuesProc: vmValuesProc, - heartbeatProc: heartbeatProc, - faucetProc: faucetProc, + accountProc: accountProc, + txProc: txProc, + scQueryService: scQueryService, + heartbeatProc: heartbeatProc, + faucetProc: faucetProc, }, nil } @@ -85,9 +87,9 @@ func (epf *ElrondProxyFacade) SendUserFunds(receiver string, value *big.Int) err return err } -// GetVmValue retrieves data from existing SC trie through the use of a VM -func (epf *ElrondProxyFacade) GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) { - return epf.vmValuesProc.GetVmValue(resType, address, funcName, argsBuff...) +// ExecuteQuery retrieves data from existing SC trie through the use of a VM +func (epf *ElrondProxyFacade) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { + return epf.scQueryService.ExecuteQuery(query) } // GetHeartbeatData retrieves the heartbeat status from one observer diff --git a/facade/errors.go b/facade/errors.go index faa2832a..2715bd2b 100644 --- a/facade/errors.go +++ b/facade/errors.go @@ -8,8 +8,8 @@ var ErrNilAccountProcessor = errors.New("nil account processor provided") // ErrNilTransactionProcessor signals that a nil transaction processor has been provided var ErrNilTransactionProcessor = errors.New("nil transaction processor provided") -// ErrNilVmValueProcessor signals that a nil vm value processor has been provided -var ErrNilVmValueProcessor = errors.New("nil vm value processor provided") +// ErrNilSCQueryService signals that a nil smart contracts query service has been provided +var ErrNilSCQueryService = errors.New("nil smart contracts query service provided") // ErrNilHeartbeatProcessor signals that a nil heartbeat processor has been provided var ErrNilHeartbeatProcessor = errors.New("nil heartbeat processor provided") diff --git a/facade/interface.go b/facade/interface.go index bee8d1ea..69e62025 100644 --- a/facade/interface.go +++ b/facade/interface.go @@ -4,7 +4,9 @@ import ( "math/big" "github.com/ElrondNetwork/elrond-go/crypto" + "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-proxy-go/data" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" ) // AccountProcessor defines what an account request processor should do @@ -19,9 +21,9 @@ type TransactionProcessor interface { SendMultipleTransactions(txs []*data.Transaction) (uint64, error) } -// VmValuesProcessor defines what a get value processor should do -type VmValuesProcessor interface { - GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) +// SCQueryService defines how data should be get from a SC account +type SCQueryService interface { + ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) } // HeartbeatProcessor defines what a heartbeat processor should do diff --git a/go.mod b/go.mod index c1afcc67..620c8f02 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.12 require ( github.com/ElrondNetwork/elrond-go v1.0.61-0.20200106084935-1581395cee6a + github.com/ElrondNetwork/elrond-vm-common v0.1.6 github.com/gin-contrib/cors v0.0.0-20190301062745-f9e10995c85a github.com/gin-gonic/gin v1.3.0 github.com/pkg/errors v0.8.1 diff --git a/process/scQueryServiceProxy.go b/process/scQueryServiceProxy.go new file mode 100644 index 00000000..1da6d083 --- /dev/null +++ b/process/scQueryServiceProxy.go @@ -0,0 +1,85 @@ +package process + +import ( + "encoding/hex" + "fmt" + "net/http" + + "github.com/ElrondNetwork/elrond-go/process" + "github.com/ElrondNetwork/elrond-proxy-go/data" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" +) + +// SCQueryServicePath defines the get values path at which the nodes answer +const SCQueryServicePath = "/vm-values/query" + +// SCQueryServiceProxy is able to process smart contract queries +type SCQueryServiceProxy struct { + proc Processor +} + +// NewSCQueryServiceProxy creates a new instance of GetValuesProcessor +func NewSCQueryServiceProxy(proc Processor) (*SCQueryServiceProxy, error) { + if proc == nil { + return nil, ErrNilCoreProcessor + } + + return &SCQueryServiceProxy{ + proc: proc, + }, nil +} + +// ExecuteQuery resolves the request by sending the request to the right observer and replies back the answer +func (proxy *SCQueryServiceProxy) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { + addressBytes := query.ScAddress + shardID, err := proxy.proc.ComputeShardId(addressBytes) + if err != nil { + return nil, err + } + + observers, err := proxy.proc.GetObservers(shardID) + if err != nil { + return nil, err + } + + for _, observer := range observers { + request := proxy.createRequestFromQuery(query) + response := &data.ResponseVmValue{} + + httpStatus, err := proxy.proc.CallPostRestEndPoint(observer.Address, SCQueryServicePath, request, response) + isObserverDown := httpStatus == http.StatusNotFound || httpStatus == http.StatusRequestTimeout + isOk := httpStatus == http.StatusOK + responseHasExplicitError := len(response.Error) > 0 + + if isObserverDown { + log.LogIfError(err) + continue + } + + if isOk { + log.Info(fmt.Sprintf("SC query sent successfully to observer %v from shard %v, received response", observer.Address, shardID)) + return response.Data, nil + } + + if responseHasExplicitError { + return nil, fmt.Errorf(response.Error) + } + + return nil, err + } + + return nil, ErrSendingRequest +} + +func (proxy *SCQueryServiceProxy) createRequestFromQuery(query *process.SCQuery) data.VmValueRequest { + request := data.VmValueRequest{} + request.Address = hex.EncodeToString(query.ScAddress) + request.FuncName = query.FuncName + request.Args = make([]string, len(query.Arguments)) + for i, argument := range query.Arguments { + argumentAsHex := hex.EncodeToString(argument) + request.Args[i] = argumentAsHex + } + + return request +} diff --git a/process/scQueryServiceProxy_test.go b/process/scQueryServiceProxy_test.go new file mode 100644 index 00000000..d612d32a --- /dev/null +++ b/process/scQueryServiceProxy_test.go @@ -0,0 +1,166 @@ +package process + +import ( + "errors" + "net/http" + "testing" + + coreProcess "github.com/ElrondNetwork/elrond-go/process" + "github.com/ElrondNetwork/elrond-proxy-go/data" + "github.com/ElrondNetwork/elrond-proxy-go/process/mock" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" + "github.com/stretchr/testify/require" +) + +func TestNewSCQueryServiceProxy_NilCoreProcessorShouldErr(t *testing.T) { + t.Parallel() + + proxy, err := NewSCQueryServiceProxy(nil) + require.Nil(t, proxy) + require.Equal(t, ErrNilCoreProcessor, err) +} + +func TestNewSCQueryServiceProxy_WithCoreProcessor(t *testing.T) { + t.Parallel() + + proxy, err := NewSCQueryServiceProxy(&mock.ProcessorStub{}) + require.NotNil(t, proxy) + require.Nil(t, err) +} + +func TestSCQueryServiceProxy_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T) { + t.Parallel() + + errExpected := errors.New("expected error") + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, errExpected + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + require.Empty(t, value) + require.Equal(t, errExpected, err) +} + +func TestSCQueryServiceProxy_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) { + t.Parallel() + + errExpected := errors.New("expected error") + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { + return nil, errExpected + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + require.Empty(t, value) + require.Equal(t, errExpected, err) +} + +func TestSCQueryServiceProxy_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *testing.T) { + t.Parallel() + + errExpected := errors.New("expected error") + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { + return []*data.Observer{ + {Address: "address1", ShardId: 0}, + {Address: "address2", ShardId: 0}, + }, nil + }, + CallPostRestEndPointCalled: func(address string, path string, data interface{}, response interface{}) (int, error) { + return http.StatusNotFound, errExpected + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + require.Empty(t, value) + require.Equal(t, ErrSendingRequest, err) +} + +func TestSCQueryServiceProxy_ExecuteQuery(t *testing.T) { + t.Parallel() + + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { + return []*data.Observer{ + {Address: "adress1", ShardId: 0}, + }, nil + }, + CallPostRestEndPointCalled: func(address string, path string, dataValue interface{}, response interface{}) (int, error) { + response.(*data.ResponseVmValue).Data = &vmcommon.VMOutput{ + ReturnData: [][]byte{[]byte{42}}, + } + + return http.StatusOK, nil + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{ + ScAddress: []byte("address"), + FuncName: "function", + Arguments: [][]byte{[]byte("aa")}, + }) + + require.Nil(t, err) + require.Equal(t, byte(42), value.ReturnData[0][0]) +} + +func TestSCQueryServiceProxy_ExecuteQuery_FailsOnRandomError(t *testing.T) { + t.Parallel() + + errExpected := errors.New("expected error") + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { + return []*data.Observer{ + {Address: "address1", ShardId: 0}, + {Address: "address2", ShardId: 0}, + }, nil + }, + CallPostRestEndPointCalled: func(address string, path string, data interface{}, response interface{}) (int, error) { + return http.StatusInternalServerError, errExpected + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + require.Empty(t, value) + require.Equal(t, errExpected, err) +} + +func TestSCQueryServiceProxy_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *testing.T) { + t.Parallel() + + errExpected := errors.New("this error") + proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { + return 0, nil + }, + GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { + return []*data.Observer{ + {Address: "address1", ShardId: 0}, + {Address: "address2", ShardId: 0}, + }, nil + }, + CallPostRestEndPointCalled: func(address string, path string, dataValue interface{}, response interface{}) (int, error) { + response.(*data.ResponseVmValue).Error = errExpected.Error() + return http.StatusBadRequest, nil + }, + }) + + value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + require.Empty(t, value) + require.Equal(t, errExpected, err) +} diff --git a/process/vmValuesProcessor.go b/process/vmValuesProcessor.go deleted file mode 100644 index da9f2077..00000000 --- a/process/vmValuesProcessor.go +++ /dev/null @@ -1,83 +0,0 @@ -package process - -import ( - "encoding/hex" - "fmt" - "net/http" - - "github.com/ElrondNetwork/elrond-proxy-go/data" -) - -// GetValuesPath defines the get values path at which the nodes answer -const GetValuesPath = "/vm-values/" - -// VmValuesProcessor is able to process get values requests -type VmValuesProcessor struct { - proc Processor -} - -// NewVmValuesProcessor creates a new instance of GetValuesProcessor -func NewVmValuesProcessor(proc Processor) (*VmValuesProcessor, error) { - if proc == nil { - return nil, ErrNilCoreProcessor - } - - return &VmValuesProcessor{ - proc: proc, - }, nil -} - -// GetVmValue resolves the request by sending the request to the right observer and replies back the answer -func (gvp *VmValuesProcessor) GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) { - addressBytes, err := hex.DecodeString(address) - if err != nil { - return nil, err - } - - shardId, err := gvp.proc.ComputeShardId(addressBytes) - if err != nil { - return nil, err - } - - observers, err := gvp.proc.GetObservers(shardId) - if err != nil { - return nil, err - } - - for _, observer := range observers { - vvr := &data.VmValueRequest{} - vvr.Address = address - vvr.FuncName = funcName - - hexArgs := make([]string, len(argsBuff)) - for idx, arg := range argsBuff { - argHex := hex.EncodeToString(arg) - hexArgs[idx] = argHex - } - vvr.Args = hexArgs - - vmValueResponse := &data.ResponseVmValue{} - - respCode, err := gvp.proc.CallPostRestEndPoint(observer.Address, GetValuesPath+resType, vvr, vmValueResponse) - if respCode == http.StatusOK && err == nil { - log.Info(fmt.Sprintf("VmValues sent successfully to observer %v from shard %v, received value %s", - observer.Address, - shardId, - vmValueResponse.HexData, - )) - - return []byte(vmValueResponse.HexData), nil - } - - // if observer was down (or didn't respond in time), skip to the next one - if respCode == http.StatusNotFound || respCode == http.StatusRequestTimeout { - log.LogIfError(err) - continue - } - - // if the request was bad, return the error message - return nil, err - } - - return nil, ErrSendingRequest -} diff --git a/process/vmValuesProcessor_test.go b/process/vmValuesProcessor_test.go deleted file mode 100644 index 193d8aca..00000000 --- a/process/vmValuesProcessor_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package process_test - -import ( - "errors" - "net/http" - "testing" - - "github.com/ElrondNetwork/elrond-proxy-go/data" - "github.com/ElrondNetwork/elrond-proxy-go/process" - "github.com/ElrondNetwork/elrond-proxy-go/process/mock" - "github.com/stretchr/testify/assert" -) - -func TestNewGetValuesProcessor_NilCoreProcessorShouldErr(t *testing.T) { - t.Parallel() - - vvp, err := process.NewVmValuesProcessor(nil) - - assert.Nil(t, vvp) - assert.Equal(t, process.ErrNilCoreProcessor, err) -} - -func TestNewGetValuesProcessor_WithCoreProcessorShouldWork(t *testing.T) { - t.Parallel() - - vvp, err := process.NewVmValuesProcessor(&mock.ProcessorStub{}) - - assert.NotNil(t, vvp) - assert.Nil(t, err) -} - -//------- GetValues - -func TestGetValuesProcessor_GetDataValueInvalidHexAdressShouldErr(t *testing.T) { - t.Parallel() - - vvp, _ := process.NewVmValuesProcessor(&mock.ProcessorStub{}) - funcName := "func" - resultType := "int" - value, err := vvp.GetVmValue(resultType, "invalid hex number", funcName) - - assert.Empty(t, value) - assert.NotNil(t, err) - assert.Contains(t, err.Error(), "invalid byte") -} - -func TestGetValuesProcessor_GetDataValueComputeShardIdFailsShouldErr(t *testing.T) { - t.Parallel() - - errExpected := errors.New("expected error") - vvp, _ := process.NewVmValuesProcessor(&mock.ProcessorStub{ - ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { - return 0, errExpected - }, - }) - address := "DEADBEEF" - funcName := "func" - resultType := "int" - value, err := vvp.GetVmValue(resultType, address, funcName) - - assert.Empty(t, value) - assert.Equal(t, errExpected, err) -} - -func TestGetValuesProcessor_GetDataValueGetObserversFailsShouldErr(t *testing.T) { - t.Parallel() - - errExpected := errors.New("expected error") - vvp, _ := process.NewVmValuesProcessor(&mock.ProcessorStub{ - ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { - return 0, nil - }, - GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { - return nil, errExpected - }, - }) - address := "DEADBEEF" - funcName := "func" - resultType := "int" - value, err := vvp.GetVmValue(resultType, address, funcName) - - assert.Empty(t, value) - assert.Equal(t, errExpected, err) -} - -func TestGetValuesProcessor_GetDataValueSendingFailsOnAllObserversShouldErr(t *testing.T) { - t.Parallel() - - errExpected := errors.New("expected error") - vvp, _ := process.NewVmValuesProcessor(&mock.ProcessorStub{ - ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { - return 0, nil - }, - GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { - return []*data.Observer{ - {Address: "adress1", ShardId: 0}, - {Address: "adress2", ShardId: 0}, - }, nil - }, - CallPostRestEndPointCalled: func(address string, path string, data interface{}, response interface{}) (int, error) { - return http.StatusNotFound, errExpected - }, - }) - address := "DEADBEEF" - funcName := "func" - resultType := "int" - value, err := vvp.GetVmValue(resultType, address, funcName) - - assert.Empty(t, value) - assert.Equal(t, process.ErrSendingRequest, err) -} - -func TestGetValuesProcessor_GetDataValueShouldWork(t *testing.T) { - t.Parallel() - - expectedValueHex := "DEADBEEFDEADBEEFDEADBEEF" - expectedValue := []byte(expectedValueHex) - vvp, _ := process.NewVmValuesProcessor(&mock.ProcessorStub{ - ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { - return 0, nil - }, - GetObserversCalled: func(shardId uint32) (observers []*data.Observer, e error) { - return []*data.Observer{ - {Address: "adress1", ShardId: 0}, - }, nil - }, - CallPostRestEndPointCalled: func(address string, path string, dataValue interface{}, response interface{}) (int, error) { - response.(*data.ResponseVmValue).HexData = expectedValueHex - - return http.StatusOK, nil - }, - }) - address := "DEADBEEF" - funcName := "func" - resultType := "int" - value, err := vvp.GetVmValue(resultType, address, funcName) - - assert.Nil(t, err) - assert.Equal(t, expectedValue, value) -} diff --git a/testing/testHttpServer.go b/testing/testHttpServer.go index 1986991e..3aad30de 100644 --- a/testing/testHttpServer.go +++ b/testing/testHttpServer.go @@ -16,6 +16,7 @@ import ( "github.com/ElrondNetwork/elrond-go/logger" "github.com/ElrondNetwork/elrond-proxy-go/data" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" ) var log = logger.GetOrCreate("testing") @@ -112,7 +113,7 @@ func (ths *TestHttpServer) processRequestSendFunds(rw http.ResponseWriter, req * func (ths *TestHttpServer) processRequestVmValue(rw http.ResponseWriter, req *http.Request) { response := data.ResponseVmValue{ - HexData: "DEADBEEFDEADBEEFDEADBEEF", + Data: &vmcommon.VMOutput{}, } responseBuff, _ := json.Marshal(response) From b846054d5181798e1560ce3f70a902f114e5fa58 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Mon, 13 Jan 2020 14:03:25 +0200 Subject: [PATCH 02/10] Fix stub, tests. --- facade/elrondProxyFacade_test.go | 31 ++++++++++++++++--------------- facade/mock/scQueryServiceStub.go | 16 ++++++++++++++++ facade/mock/vmValuesStub.go | 9 --------- 3 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 facade/mock/scQueryServiceStub.go delete mode 100644 facade/mock/vmValuesStub.go diff --git a/facade/elrondProxyFacade_test.go b/facade/elrondProxyFacade_test.go index d0ad7f5b..4698220c 100644 --- a/facade/elrondProxyFacade_test.go +++ b/facade/elrondProxyFacade_test.go @@ -7,9 +7,11 @@ import ( "github.com/ElrondNetwork/elrond-go/crypto" "github.com/ElrondNetwork/elrond-go/crypto/signing" "github.com/ElrondNetwork/elrond-go/crypto/signing/kyber" + "github.com/ElrondNetwork/elrond-go/process" "github.com/ElrondNetwork/elrond-proxy-go/data" "github.com/ElrondNetwork/elrond-proxy-go/facade" "github.com/ElrondNetwork/elrond-proxy-go/facade/mock" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/stretchr/testify/assert" ) @@ -19,7 +21,7 @@ func TestNewElrondProxyFacade_NilAccountProcShouldErr(t *testing.T) { epf, err := facade.NewElrondProxyFacade( nil, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) @@ -34,7 +36,7 @@ func TestNewElrondProxyFacade_NilTransactionProcShouldErr(t *testing.T) { epf, err := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, nil, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) @@ -55,7 +57,7 @@ func TestNewElrondProxyFacade_NilGetValuesProcShouldErr(t *testing.T) { ) assert.Nil(t, epf) - assert.Equal(t, facade.ErrNilVmValueProcessor, err) + assert.Equal(t, facade.ErrNilSCQueryService, err) } func TestNewElrondProxyFacade_NilHeartbeatProcShouldErr(t *testing.T) { @@ -64,7 +66,7 @@ func TestNewElrondProxyFacade_NilHeartbeatProcShouldErr(t *testing.T) { epf, err := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, nil, &mock.FaucetProcessorStub{}, ) @@ -79,7 +81,7 @@ func TestNewElrondProxyFacade_NilFaucetProcShouldErr(t *testing.T) { epf, err := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, nil, ) @@ -94,7 +96,7 @@ func TestNewElrondProxyFacade_ShouldWork(t *testing.T) { epf, err := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) @@ -115,7 +117,7 @@ func TestElrondProxyFacade_GetAccount(t *testing.T) { }, }, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) @@ -138,7 +140,7 @@ func TestElrondProxyFacade_SendTransaction(t *testing.T) { return 0, "", nil }, }, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) @@ -166,7 +168,7 @@ func TestElrondProxyFacade_SendUserFunds(t *testing.T) { return 0, "", nil }, }, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{ SenderDetailsFromPemCalled: func(receiver string) (crypto.PrivateKey, string, error) { @@ -190,18 +192,17 @@ func TestElrondProxyFacade_GetDataValue(t *testing.T) { epf, _ := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{ - GetVmValueCalled: func(resType string, address string, funcName string, argsBuff ...[]byte) (bytes []byte, e error) { + &mock.SCQueryServiceStub{ + ExecuteQueryCalled: func(query *process.SCQuery) (*vmcommon.VMOutput, error) { wasCalled = true - - return make([]byte, 0), nil + return &vmcommon.VMOutput{}, nil }, }, &mock.HeartbeatProcessorStub{}, &mock.FaucetProcessorStub{}, ) - _, _ = epf.GetVmValue("", "", "") + _, _ = epf.ExecuteQuery(nil) assert.True(t, wasCalled) } @@ -220,7 +221,7 @@ func TestElrondProxyFacade_GetHeartbeatData(t *testing.T) { epf, _ := facade.NewElrondProxyFacade( &mock.AccountProcessorStub{}, &mock.TransactionProcessorStub{}, - &mock.VmValuesProcessorStub{}, + &mock.SCQueryServiceStub{}, &mock.HeartbeatProcessorStub{ GetHeartbeatDataCalled: func() (*data.HeartbeatResponse, error) { return expectedResults, nil diff --git a/facade/mock/scQueryServiceStub.go b/facade/mock/scQueryServiceStub.go new file mode 100644 index 00000000..0f83ac54 --- /dev/null +++ b/facade/mock/scQueryServiceStub.go @@ -0,0 +1,16 @@ +package mock + +import ( + "github.com/ElrondNetwork/elrond-go/process" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" +) + +// SCQueryServiceStub is a stub +type SCQueryServiceStub struct { + ExecuteQueryCalled func(*process.SCQuery) (*vmcommon.VMOutput, error) +} + +// ExecuteQuery is a stub +func (serviceStub *SCQueryServiceStub) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { + return serviceStub.ExecuteQueryCalled(query) +} diff --git a/facade/mock/vmValuesStub.go b/facade/mock/vmValuesStub.go deleted file mode 100644 index 0048c948..00000000 --- a/facade/mock/vmValuesStub.go +++ /dev/null @@ -1,9 +0,0 @@ -package mock - -type VmValuesProcessorStub struct { - GetVmValueCalled func(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) -} - -func (gvps *VmValuesProcessorStub) GetVmValue(resType string, address string, funcName string, argsBuff ...[]byte) ([]byte, error) { - return gvps.GetVmValueCalled(resType, address, funcName, argsBuff...) -} From 6ddef3090f597ad83bb8db94c9ceff1b0e599ec2 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Mon, 13 Jan 2020 17:25:10 +0200 Subject: [PATCH 03/10] Fix facade. --- api/vmValues/routes.go | 2 +- api/vmValues/routes_test.go | 6 ++++-- facade/elrondProxyFacade.go | 4 ++-- facade/elrondProxyFacade_test.go | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/api/vmValues/routes.go b/api/vmValues/routes.go index c3e39271..406b01d7 100644 --- a/api/vmValues/routes.go +++ b/api/vmValues/routes.go @@ -75,7 +75,7 @@ func executeQuery(context *gin.Context) { } func doExecuteQuery(context *gin.Context) (*vmcommon.VMOutput, error) { - facade, ok := context.MustGet("elrondFacade").(FacadeHandler) + facade, ok := context.MustGet("elrondProxyFacade").(FacadeHandler) if !ok { return nil, apiErrors.ErrInvalidAppContext } diff --git a/api/vmValues/routes_test.go b/api/vmValues/routes_test.go index 854be1a2..f448b6dd 100644 --- a/api/vmValues/routes_test.go +++ b/api/vmValues/routes_test.go @@ -11,7 +11,6 @@ import ( "net/http/httptest" "testing" - "github.com/ElrondNetwork/elrond-go/api/middleware" "github.com/ElrondNetwork/elrond-go/api/mock" "github.com/ElrondNetwork/elrond-go/process" vmcommon "github.com/ElrondNetwork/elrond-vm-common" @@ -294,7 +293,10 @@ func startNodeServer(handler interface{}) *gin.Engine { ws := gin.New() ws.Use(cors.Default()) getValuesRoute := ws.Group("/vm-values") - getValuesRoute.Use(middleware.WithElrondFacade(handler)) + getValuesRoute.Use(func(c *gin.Context) { + c.Set("elrondProxyFacade", handler) + c.Next() + }) Routes(getValuesRoute) return ws diff --git a/facade/elrondProxyFacade.go b/facade/elrondProxyFacade.go index 88bb13d6..85a4ded5 100644 --- a/facade/elrondProxyFacade.go +++ b/facade/elrondProxyFacade.go @@ -87,8 +87,8 @@ func (epf *ElrondProxyFacade) SendUserFunds(receiver string, value *big.Int) err return err } -// ExecuteQuery retrieves data from existing SC trie through the use of a VM -func (epf *ElrondProxyFacade) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { +// ExecuteSCQuery retrieves data from existing SC trie through the use of a VM +func (epf *ElrondProxyFacade) ExecuteSCQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { return epf.scQueryService.ExecuteQuery(query) } diff --git a/facade/elrondProxyFacade_test.go b/facade/elrondProxyFacade_test.go index 4698220c..f2708a47 100644 --- a/facade/elrondProxyFacade_test.go +++ b/facade/elrondProxyFacade_test.go @@ -202,7 +202,7 @@ func TestElrondProxyFacade_GetDataValue(t *testing.T) { &mock.FaucetProcessorStub{}, ) - _, _ = epf.ExecuteQuery(nil) + _, _ = epf.ExecuteSCQuery(nil) assert.True(t, wasCalled) } From ff03073d4918b56c68ba8cda3ca402aa769fb71b Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 09:30:07 +0200 Subject: [PATCH 04/10] Fix after review. --- api/vmValues/interface.go | 11 +++++++ api/vmValues/routes.go | 5 --- api/vmValues/routes_test.go | 4 +-- cmd/proxy/main.go | 4 +-- ...eryServiceProxy.go => scQueryProcessor.go} | 22 ++++++------- ...Proxy_test.go => scQueryProcessor_test.go} | 32 +++++++++---------- 6 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 api/vmValues/interface.go rename process/{scQueryServiceProxy.go => scQueryProcessor.go} (67%) rename process/{scQueryServiceProxy_test.go => scQueryProcessor_test.go} (78%) diff --git a/api/vmValues/interface.go b/api/vmValues/interface.go new file mode 100644 index 00000000..71aff5bc --- /dev/null +++ b/api/vmValues/interface.go @@ -0,0 +1,11 @@ +package vmValues + +import ( + "github.com/ElrondNetwork/elrond-go/process" + vmcommon "github.com/ElrondNetwork/elrond-vm-common" +) + +// FacadeHandler interface defines methods that can be used from `elrondFacade` context variable +type FacadeHandler interface { + ExecuteSCQuery(*process.SCQuery) (*vmcommon.VMOutput, error) +} diff --git a/api/vmValues/routes.go b/api/vmValues/routes.go index 406b01d7..c33b99f7 100644 --- a/api/vmValues/routes.go +++ b/api/vmValues/routes.go @@ -11,11 +11,6 @@ import ( "github.com/gin-gonic/gin" ) -// FacadeHandler interface defines methods that can be used from `elrondFacade` context variable -type FacadeHandler interface { - ExecuteSCQuery(*process.SCQuery) (*vmcommon.VMOutput, error) -} - // VMValueRequest represents the structure on which user input for generating a new transaction will validate against type VMValueRequest struct { ScAddress string `form:"scAddress" json:"scAddress"` diff --git a/api/vmValues/routes_test.go b/api/vmValues/routes_test.go index f448b6dd..a5d3e530 100644 --- a/api/vmValues/routes_test.go +++ b/api/vmValues/routes_test.go @@ -13,6 +13,7 @@ import ( "github.com/ElrondNetwork/elrond-go/api/mock" "github.com/ElrondNetwork/elrond-go/process" + apiErrors "github.com/ElrondNetwork/elrond-proxy-go/api/errors" vmcommon "github.com/ElrondNetwork/elrond-vm-common" "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" @@ -260,7 +261,6 @@ func TestGetDataValue_WhenNoVMReturnData_ShouldErr(t *testing.T) { func TestGetDataValue_WhenBadFacade_ShouldErr(t *testing.T) { t.Parallel() - errExpected := errors.New("invalid app context") var facade interface{} request := VMValueRequest{ @@ -273,7 +273,7 @@ func TestGetDataValue_WhenBadFacade_ShouldErr(t *testing.T) { statusCode := doPost(&facade, "/vm-values/query", request, &response) assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) + assert.Contains(t, response.Error, apiErrors.ErrInvalidAppContext.Error()) } func doPost(facadeMock interface{}, url string, request VMValueRequest, response interface{}) int { diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 644941b5..c19acdcb 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -273,7 +273,7 @@ func createFacade( return nil, err } - gvpProc, err := process.NewSCQueryServiceProxy(bp) + scQueryProc, err := process.NewSCQueryProcessor(bp) if err != nil { return nil, err } @@ -287,7 +287,7 @@ func createFacade( } htbProc.StartCacheUpdate() - return facade.NewElrondProxyFacade(accntProc, txProc, gvpProc, htbProc, faucetProc) + return facade.NewElrondProxyFacade(accntProc, txProc, scQueryProc, htbProc, faucetProc) } func getShardCoordinator(cfg *config.Config) (sharding.Coordinator, error) { diff --git a/process/scQueryServiceProxy.go b/process/scQueryProcessor.go similarity index 67% rename from process/scQueryServiceProxy.go rename to process/scQueryProcessor.go index 1da6d083..3ffc69e9 100644 --- a/process/scQueryServiceProxy.go +++ b/process/scQueryProcessor.go @@ -13,40 +13,40 @@ import ( // SCQueryServicePath defines the get values path at which the nodes answer const SCQueryServicePath = "/vm-values/query" -// SCQueryServiceProxy is able to process smart contract queries -type SCQueryServiceProxy struct { +// SCQueryProcessor is able to process smart contract queries +type SCQueryProcessor struct { proc Processor } -// NewSCQueryServiceProxy creates a new instance of GetValuesProcessor -func NewSCQueryServiceProxy(proc Processor) (*SCQueryServiceProxy, error) { +// NewSCQueryProcessor creates a new instance of SCQueryProcessor +func NewSCQueryProcessor(proc Processor) (*SCQueryProcessor, error) { if proc == nil { return nil, ErrNilCoreProcessor } - return &SCQueryServiceProxy{ + return &SCQueryProcessor{ proc: proc, }, nil } // ExecuteQuery resolves the request by sending the request to the right observer and replies back the answer -func (proxy *SCQueryServiceProxy) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { +func (scQueryProcessor *SCQueryProcessor) ExecuteQuery(query *process.SCQuery) (*vmcommon.VMOutput, error) { addressBytes := query.ScAddress - shardID, err := proxy.proc.ComputeShardId(addressBytes) + shardID, err := scQueryProcessor.proc.ComputeShardId(addressBytes) if err != nil { return nil, err } - observers, err := proxy.proc.GetObservers(shardID) + observers, err := scQueryProcessor.proc.GetObservers(shardID) if err != nil { return nil, err } for _, observer := range observers { - request := proxy.createRequestFromQuery(query) + request := scQueryProcessor.createRequestFromQuery(query) response := &data.ResponseVmValue{} - httpStatus, err := proxy.proc.CallPostRestEndPoint(observer.Address, SCQueryServicePath, request, response) + httpStatus, err := scQueryProcessor.proc.CallPostRestEndPoint(observer.Address, SCQueryServicePath, request, response) isObserverDown := httpStatus == http.StatusNotFound || httpStatus == http.StatusRequestTimeout isOk := httpStatus == http.StatusOK responseHasExplicitError := len(response.Error) > 0 @@ -71,7 +71,7 @@ func (proxy *SCQueryServiceProxy) ExecuteQuery(query *process.SCQuery) (*vmcommo return nil, ErrSendingRequest } -func (proxy *SCQueryServiceProxy) createRequestFromQuery(query *process.SCQuery) data.VmValueRequest { +func (scQueryProcessor *SCQueryProcessor) createRequestFromQuery(query *process.SCQuery) data.VmValueRequest { request := data.VmValueRequest{} request.Address = hex.EncodeToString(query.ScAddress) request.FuncName = query.FuncName diff --git a/process/scQueryServiceProxy_test.go b/process/scQueryProcessor_test.go similarity index 78% rename from process/scQueryServiceProxy_test.go rename to process/scQueryProcessor_test.go index d612d32a..5acc121f 100644 --- a/process/scQueryServiceProxy_test.go +++ b/process/scQueryProcessor_test.go @@ -12,27 +12,27 @@ import ( "github.com/stretchr/testify/require" ) -func TestNewSCQueryServiceProxy_NilCoreProcessorShouldErr(t *testing.T) { +func TestNewSCQueryProcessor_NilCoreProcessorShouldErr(t *testing.T) { t.Parallel() - proxy, err := NewSCQueryServiceProxy(nil) + proxy, err := NewSCQueryProcessor(nil) require.Nil(t, proxy) require.Equal(t, ErrNilCoreProcessor, err) } -func TestNewSCQueryServiceProxy_WithCoreProcessor(t *testing.T) { +func TestNewSCQueryProcessor_WithCoreProcessor(t *testing.T) { t.Parallel() - proxy, err := NewSCQueryServiceProxy(&mock.ProcessorStub{}) + proxy, err := NewSCQueryProcessor(&mock.ProcessorStub{}) require.NotNil(t, proxy) require.Nil(t, err) } -func TestSCQueryServiceProxy_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, errExpected }, @@ -43,11 +43,11 @@ func TestSCQueryServiceProxy_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testin require.Equal(t, errExpected, err) } -func TestSCQueryServiceProxy_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -61,11 +61,11 @@ func TestSCQueryServiceProxy_ExecuteQuery_GetObserversFailsShouldErr(t *testing. require.Equal(t, errExpected, err) } -func TestSCQueryServiceProxy_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -85,10 +85,10 @@ func TestSCQueryServiceProxy_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t require.Equal(t, ErrSendingRequest, err) } -func TestSCQueryServiceProxy_ExecuteQuery(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery(t *testing.T) { t.Parallel() - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -116,11 +116,11 @@ func TestSCQueryServiceProxy_ExecuteQuery(t *testing.T) { require.Equal(t, byte(42), value.ReturnData[0][0]) } -func TestSCQueryServiceProxy_ExecuteQuery_FailsOnRandomError(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery_FailsOnRandomError(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -140,11 +140,11 @@ func TestSCQueryServiceProxy_ExecuteQuery_FailsOnRandomError(t *testing.T) { require.Equal(t, errExpected, err) } -func TestSCQueryServiceProxy_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *testing.T) { t.Parallel() errExpected := errors.New("this error") - proxy, _ := NewSCQueryServiceProxy(&mock.ProcessorStub{ + proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, From 45aa843fd2bddea6026d309c62966eb1f2e9cff0 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 10:00:42 +0200 Subject: [PATCH 05/10] Update reference to elrond-go. --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 620c8f02..1542bd5e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ElrondNetwork/elrond-proxy-go go 1.12 require ( - github.com/ElrondNetwork/elrond-go v1.0.61-0.20200106084935-1581395cee6a + github.com/ElrondNetwork/elrond-go v1.0.77 github.com/ElrondNetwork/elrond-vm-common v0.1.6 github.com/gin-contrib/cors v0.0.0-20190301062745-f9e10995c85a github.com/gin-gonic/gin v1.3.0 diff --git a/go.sum b/go.sum index 941e4812..3312faa3 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,8 @@ github.com/ElrondNetwork/concurrent-map v0.1.2 h1:mr2sVF2IPDsJO8DNGzCUiNQOJcadHu github.com/ElrondNetwork/concurrent-map v0.1.2/go.mod h1:3XwSwn4JHI0lrKxWLZvtp53Emr8BXYTmNQGwcukHJEE= github.com/ElrondNetwork/elrond-go v1.0.61-0.20200106084935-1581395cee6a h1:TC8DU63L2JsU3TErYp1ZYff7vR5h9dOF+LYj1LRRg58= github.com/ElrondNetwork/elrond-go v1.0.61-0.20200106084935-1581395cee6a/go.mod h1:CqUvamLftE5HetUWguY2psd8d4sr3s29TsjYLyd3IWw= +github.com/ElrondNetwork/elrond-go v1.0.77 h1:mwQQL68Mh/PEj4vP58dd+7Xe7dSF1qT/U0JqY+uMeAA= +github.com/ElrondNetwork/elrond-go v1.0.77/go.mod h1:XHlf650zxjStfgt6orelrzp9zbup4KbDE5zXZSUvdWI= github.com/ElrondNetwork/elrond-vm v0.0.24/go.mod h1:cqYk2wq8yndnrgOjB81R/QCruaC+F+hMf8R6C6Y0ewA= github.com/ElrondNetwork/elrond-vm-common v0.0.0-20191203115206-691b00a6e76a/go.mod h1:ZakxPST/Wt8umnRtA9gobcy3Dw2bywxwkC54P5VhO9g= github.com/ElrondNetwork/elrond-vm-common v0.0.9/go.mod h1:VqCCN0cX0e4D/KDc7MGNV9ElrOsfnjuJnGvcODVjzbk= @@ -98,6 +100,8 @@ github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= From 4e40a29b3fee464440ad3f0d1b5ae7151c6744a5 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 10:10:36 +0200 Subject: [PATCH 06/10] Fix after review (rename). --- process/scQueryProcessor_test.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/process/scQueryProcessor_test.go b/process/scQueryProcessor_test.go index 5acc121f..c48d3377 100644 --- a/process/scQueryProcessor_test.go +++ b/process/scQueryProcessor_test.go @@ -15,16 +15,16 @@ import ( func TestNewSCQueryProcessor_NilCoreProcessorShouldErr(t *testing.T) { t.Parallel() - proxy, err := NewSCQueryProcessor(nil) - require.Nil(t, proxy) + processor, err := NewSCQueryProcessor(nil) + require.Nil(t, processor) require.Equal(t, ErrNilCoreProcessor, err) } func TestNewSCQueryProcessor_WithCoreProcessor(t *testing.T) { t.Parallel() - proxy, err := NewSCQueryProcessor(&mock.ProcessorStub{}) - require.NotNil(t, proxy) + processor, err := NewSCQueryProcessor(&mock.ProcessorStub{}) + require.NotNil(t, processor) require.Nil(t, err) } @@ -32,13 +32,13 @@ func TestSCQueryProcessor_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, errExpected }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{}) require.Empty(t, value) require.Equal(t, errExpected, err) } @@ -47,7 +47,7 @@ func TestSCQueryProcessor_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -56,7 +56,7 @@ func TestSCQueryProcessor_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{}) require.Empty(t, value) require.Equal(t, errExpected, err) } @@ -65,7 +65,7 @@ func TestSCQueryProcessor_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *te t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -80,7 +80,7 @@ func TestSCQueryProcessor_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *te }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{}) require.Empty(t, value) require.Equal(t, ErrSendingRequest, err) } @@ -88,7 +88,7 @@ func TestSCQueryProcessor_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *te func TestSCQueryProcessor_ExecuteQuery(t *testing.T) { t.Parallel() - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -106,7 +106,7 @@ func TestSCQueryProcessor_ExecuteQuery(t *testing.T) { }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{ + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{ ScAddress: []byte("address"), FuncName: "function", Arguments: [][]byte{[]byte("aa")}, @@ -120,7 +120,7 @@ func TestSCQueryProcessor_ExecuteQuery_FailsOnRandomError(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -135,7 +135,7 @@ func TestSCQueryProcessor_ExecuteQuery_FailsOnRandomError(t *testing.T) { }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{}) require.Empty(t, value) require.Equal(t, errExpected, err) } @@ -144,7 +144,7 @@ func TestSCQueryProcessor_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *tes t.Parallel() errExpected := errors.New("this error") - proxy, _ := NewSCQueryProcessor(&mock.ProcessorStub{ + processor, _ := NewSCQueryProcessor(&mock.ProcessorStub{ ComputeShardIdCalled: func(addressBuff []byte) (u uint32, e error) { return 0, nil }, @@ -160,7 +160,7 @@ func TestSCQueryProcessor_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *tes }, }) - value, err := proxy.ExecuteQuery(&coreProcess.SCQuery{}) + value, err := processor.ExecuteQuery(&coreProcess.SCQuery{}) require.Empty(t, value) require.Equal(t, errExpected, err) } From dae25907efe38f8f6da7360770dfc85fd3809987 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 11:47:53 +0200 Subject: [PATCH 07/10] Fix after review, plus improve tests (add extra test). --- api/errors/errors.go | 3 + api/vmValues/routes.go | 2 +- api/vmValues/routes_test.go | 141 +++++++++++++++++-------------- process/scQueryProcessor_test.go | 10 +-- 4 files changed, 86 insertions(+), 70 deletions(-) diff --git a/api/errors/errors.go b/api/errors/errors.go index a06a1f71..52bb46ad 100644 --- a/api/errors/errors.go +++ b/api/errors/errors.go @@ -8,6 +8,9 @@ import ( // ErrInvalidAppContext signals an invalid context passed to the routing system var ErrInvalidAppContext = errors.New("invalid app context") +// ErrInvalidJSONRequest signals an error in json request formatting +var ErrInvalidJSONRequest = errors.New("invalid json request") + // ErrValidation signals an error in validation var ErrValidation = errors.New("validation error") diff --git a/api/vmValues/routes.go b/api/vmValues/routes.go index c33b99f7..12610b64 100644 --- a/api/vmValues/routes.go +++ b/api/vmValues/routes.go @@ -78,7 +78,7 @@ func doExecuteQuery(context *gin.Context) (*vmcommon.VMOutput, error) { request := VMValueRequest{} err := context.ShouldBindJSON(&request) if err != nil { - return nil, err + return nil, apiErrors.ErrInvalidJSONRequest } command, err := createSCQuery(&request) diff --git a/api/vmValues/routes_test.go b/api/vmValues/routes_test.go index a5d3e530..9a23e41e 100644 --- a/api/vmValues/routes_test.go +++ b/api/vmValues/routes_test.go @@ -18,7 +18,7 @@ import ( "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/json" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type simpleResponse struct { @@ -37,7 +37,7 @@ func init() { const DummyScAddress = "00000000000000000500fabd9501b7e5353de57a4e319857c2fb99089770720a" -func TestGetDataValueAsHexBytes(t *testing.T) { +func TestGetHex_ShouldWork(t *testing.T) { t.Parallel() valueBuff, _ := hex.DecodeString("DEADBEEF") @@ -59,12 +59,12 @@ func TestGetDataValueAsHexBytes(t *testing.T) { response := simpleResponse{} statusCode := doPost(&facade, "/vm-values/hex", request, &response) - assert.Equal(t, http.StatusOK, statusCode) - assert.Equal(t, "", response.Error) - assert.Equal(t, hex.EncodeToString(valueBuff), response.Data) + require.Equal(t, http.StatusOK, statusCode) + require.Equal(t, "", response.Error) + require.Equal(t, hex.EncodeToString(valueBuff), response.Data) } -func TestGetDataValueAsString(t *testing.T) { +func TestGetString_ShouldWork(t *testing.T) { t.Parallel() valueBuff := "DEADBEEF" @@ -86,12 +86,12 @@ func TestGetDataValueAsString(t *testing.T) { response := simpleResponse{} statusCode := doPost(&facade, "/vm-values/string", request, &response) - assert.Equal(t, http.StatusOK, statusCode) - assert.Equal(t, "", response.Error) - assert.Equal(t, valueBuff, response.Data) + require.Equal(t, http.StatusOK, statusCode) + require.Equal(t, "", response.Error) + require.Equal(t, valueBuff, response.Data) } -func TestGetDataValueAsInt(t *testing.T) { +func TestGetInt_ShouldWork(t *testing.T) { t.Parallel() value := "1234567" @@ -115,12 +115,12 @@ func TestGetDataValueAsInt(t *testing.T) { response := simpleResponse{} statusCode := doPost(&facade, "/vm-values/int", request, &response) - assert.Equal(t, http.StatusOK, statusCode) - assert.Equal(t, "", response.Error) - assert.Equal(t, value, response.Data) + require.Equal(t, http.StatusOK, statusCode) + require.Equal(t, "", response.Error) + require.Equal(t, value, response.Data) } -func TestExecuteQuery(t *testing.T) { +func TestQuery_ShouldWork(t *testing.T) { t.Parallel() facade := mock.Facade{ @@ -141,9 +141,9 @@ func TestExecuteQuery(t *testing.T) { response := vmOutputResponse{} statusCode := doPost(&facade, "/vm-values/query", request, &response) - assert.Equal(t, http.StatusOK, statusCode) - assert.Equal(t, "", response.Error) - assert.Equal(t, int64(42), big.NewInt(0).SetBytes(response.Data.ReturnData[0]).Int64()) + require.Equal(t, http.StatusOK, statusCode) + require.Equal(t, "", response.Error) + require.Equal(t, int64(42), big.NewInt(0).SetBytes(response.Data.ReturnData[0]).Int64()) } func TestCreateSCQuery_ArgumentIsNotHexShouldErr(t *testing.T) { @@ -154,17 +154,17 @@ func TestCreateSCQuery_ArgumentIsNotHexShouldErr(t *testing.T) { } _, err := createSCQuery(&request) - assert.NotNil(t, err) - assert.Contains(t, err.Error(), "'bad arg' is not a valid hex string") + require.NotNil(t, err) + require.Contains(t, err.Error(), "'bad arg' is not a valid hex string") } -func TestGetDataValue_FacadeErrorsShouldErr(t *testing.T) { +func TestAllRoutes_FacadeErrorsShouldErr(t *testing.T) { t.Parallel() - errExpected := errors.New("no return data") + errExpected := errors.New("some random error") facade := mock.Facade{ ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { - return &vmcommon.VMOutput{}, nil + return nil, errExpected }, } @@ -174,22 +174,10 @@ func TestGetDataValue_FacadeErrorsShouldErr(t *testing.T) { Args: []string{}, } - response := simpleResponse{} - - statusCode := doPost(&facade, "/vm-values/hex", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) - - statusCode = doPost(&facade, "/vm-values/string", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) - - statusCode = doPost(&facade, "/vm-values/int", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) + requireErrorOnAllRoutes(t, &facade, request, errExpected) } -func TestGetDataValue_WhenBadAddress_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenBadAddressShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("not a valid hex string") @@ -205,14 +193,10 @@ func TestGetDataValue_WhenBadAddress_ShouldErr(t *testing.T) { Args: []string{}, } - response := simpleResponse{} - - statusCode := doPost(&facade, "/vm-values/hex", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) + requireErrorOnAllRoutes(t, &facade, request, errExpected) } -func TestGetDataValue_WhenBadArguments_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenBadArgumentsShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("not a valid hex string") @@ -228,20 +212,16 @@ func TestGetDataValue_WhenBadArguments_ShouldErr(t *testing.T) { Args: []string{"AA", "ZZ"}, } - response := simpleResponse{} - - statusCode := doPost(&facade, "/vm-values/hex", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) + requireErrorOnAllRoutes(t, &facade, request, errExpected) } -func TestGetDataValue_WhenNoVMReturnData_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenNoVMReturnData_ShouldErr(t *testing.T) { t.Parallel() - errExpected := errors.New("expected error") + errExpected := errors.New("no return data") facade := mock.Facade{ ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { - return nil, errExpected + return &vmcommon.VMOutput{}, nil }, } @@ -251,14 +231,22 @@ func TestGetDataValue_WhenNoVMReturnData_ShouldErr(t *testing.T) { Args: []string{}, } - response := simpleResponse{} + requireErrorOnGetSingleValueRoutes(t, &facade, request, errExpected) +} - statusCode := doPost(&facade, "/vm-values/hex", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, errExpected.Error()) +func TestAllRoutes_WhenBadJson_ShouldErr(t *testing.T) { + t.Parallel() + + facade := mock.Facade{ + ExecuteSCQueryHandler: func(query *process.SCQuery) (vmOutput *vmcommon.VMOutput, e error) { + return &vmcommon.VMOutput{}, nil + }, + } + + requireErrorOnGetSingleValueRoutes(t, &facade, []byte("dummy"), apiErrors.ErrInvalidJSONRequest) } -func TestGetDataValue_WhenBadFacade_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenBadFacade_ShouldErr(t *testing.T) { t.Parallel() var facade interface{} @@ -269,18 +257,18 @@ func TestGetDataValue_WhenBadFacade_ShouldErr(t *testing.T) { Args: []string{}, } - response := simpleResponse{} - - statusCode := doPost(&facade, "/vm-values/query", request, &response) - assert.Equal(t, http.StatusBadRequest, statusCode) - assert.Contains(t, response.Error, apiErrors.ErrInvalidAppContext.Error()) + requireErrorOnAllRoutes(t, &facade, request, apiErrors.ErrInvalidAppContext) } -func doPost(facadeMock interface{}, url string, request VMValueRequest, response interface{}) int { - jsonBody, _ := json.Marshal(request) +func doPost(facade interface{}, url string, request interface{}, response interface{}) int { + // Serialize if not already + requestAsBytes, ok := request.([]byte) + if !ok { + requestAsBytes, _ = json.Marshal(request) + } - server := startNodeServer(facadeMock) - httpRequest, _ := http.NewRequest("POST", url, bytes.NewBuffer([]byte(jsonBody))) + server := startNodeServer(facade) + httpRequest, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestAsBytes)) responseRecorder := httptest.NewRecorder() server.ServeHTTP(responseRecorder, httpRequest) @@ -310,3 +298,28 @@ func parseResponse(responseBody io.Reader, destination interface{}) { fmt.Println(err) } } + +func requireErrorOnAllRoutes(t *testing.T, facade interface{}, request interface{}, errExpected error) { + requireErrorOnGetSingleValueRoutes(t, facade, request, errExpected) + + response := simpleResponse{} + statusCode := doPost(facade, "/vm-values/query", request, &response) + require.Equal(t, http.StatusBadRequest, statusCode) + require.Contains(t, response.Error, errExpected.Error()) +} + +func requireErrorOnGetSingleValueRoutes(t *testing.T, facade interface{}, request interface{}, errExpected error) { + response := simpleResponse{} + + statusCode := doPost(facade, "/vm-values/hex", request, &response) + require.Equal(t, http.StatusBadRequest, statusCode) + require.Contains(t, response.Error, errExpected.Error()) + + statusCode = doPost(facade, "/vm-values/string", request, &response) + require.Equal(t, http.StatusBadRequest, statusCode) + require.Contains(t, response.Error, errExpected.Error()) + + statusCode = doPost(facade, "/vm-values/int", request, &response) + require.Equal(t, http.StatusBadRequest, statusCode) + require.Contains(t, response.Error, errExpected.Error()) +} diff --git a/process/scQueryProcessor_test.go b/process/scQueryProcessor_test.go index c48d3377..432e6de1 100644 --- a/process/scQueryProcessor_test.go +++ b/process/scQueryProcessor_test.go @@ -28,7 +28,7 @@ func TestNewSCQueryProcessor_WithCoreProcessor(t *testing.T) { require.Nil(t, err) } -func TestSCQueryProcessor_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQueryComputeShardIdFailsShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") @@ -43,7 +43,7 @@ func TestSCQueryProcessor_ExecuteQuery_ComputeShardIdFailsShouldErr(t *testing.T require.Equal(t, errExpected, err) } -func TestSCQueryProcessor_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQueryGetObserversFailsShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") @@ -61,7 +61,7 @@ func TestSCQueryProcessor_ExecuteQuery_GetObserversFailsShouldErr(t *testing.T) require.Equal(t, errExpected, err) } -func TestSCQueryProcessor_ExecuteQuery_SendingFailsOnAllObserversShouldErr(t *testing.T) { +func TestSCQueryProcessor_ExecuteQuerySendingFailsOnAllObserversShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") @@ -116,7 +116,7 @@ func TestSCQueryProcessor_ExecuteQuery(t *testing.T) { require.Equal(t, byte(42), value.ReturnData[0][0]) } -func TestSCQueryProcessor_ExecuteQuery_FailsOnRandomError(t *testing.T) { +func TestSCQueryProcessor_ExecuteQueryFailsOnRandomErrorShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("expected error") @@ -140,7 +140,7 @@ func TestSCQueryProcessor_ExecuteQuery_FailsOnRandomError(t *testing.T) { require.Equal(t, errExpected, err) } -func TestSCQueryProcessor_ExecuteQuery_FailsOnBadRequestWithExplicitError(t *testing.T) { +func TestSCQueryProcessor_ExecuteQueryFailsOnBadRequestWithExplicitErrorShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("this error") From 29fb8b88694c64904391bc14c6955191d1862e20 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 11:48:01 +0200 Subject: [PATCH 08/10] Fix after review. --- process/scQueryProcessor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/scQueryProcessor.go b/process/scQueryProcessor.go index 3ffc69e9..9a43fbc4 100644 --- a/process/scQueryProcessor.go +++ b/process/scQueryProcessor.go @@ -57,7 +57,7 @@ func (scQueryProcessor *SCQueryProcessor) ExecuteQuery(query *process.SCQuery) ( } if isOk { - log.Info(fmt.Sprintf("SC query sent successfully to observer %v from shard %v, received response", observer.Address, shardID)) + log.Debug(fmt.Sprintf("SC query sent successfully to observer %v from shard %v, received response", observer.Address, shardID)) return response.Data, nil } From ef5ade624cca1967bf0d49d1eb3ccf866f4b79dd Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 14:43:01 +0200 Subject: [PATCH 09/10] Fix after review - rename. --- api/vmValues/routes_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/vmValues/routes_test.go b/api/vmValues/routes_test.go index 9a23e41e..2d4daac7 100644 --- a/api/vmValues/routes_test.go +++ b/api/vmValues/routes_test.go @@ -215,7 +215,7 @@ func TestAllRoutes_WhenBadArgumentsShouldErr(t *testing.T) { requireErrorOnAllRoutes(t, &facade, request, errExpected) } -func TestAllRoutes_WhenNoVMReturnData_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenNoVMReturnDataShouldErr(t *testing.T) { t.Parallel() errExpected := errors.New("no return data") @@ -234,7 +234,7 @@ func TestAllRoutes_WhenNoVMReturnData_ShouldErr(t *testing.T) { requireErrorOnGetSingleValueRoutes(t, &facade, request, errExpected) } -func TestAllRoutes_WhenBadJson_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenBadJsonShouldErr(t *testing.T) { t.Parallel() facade := mock.Facade{ @@ -246,7 +246,7 @@ func TestAllRoutes_WhenBadJson_ShouldErr(t *testing.T) { requireErrorOnGetSingleValueRoutes(t, &facade, []byte("dummy"), apiErrors.ErrInvalidJSONRequest) } -func TestAllRoutes_WhenBadFacade_ShouldErr(t *testing.T) { +func TestAllRoutes_WhenBadFacadeShouldErr(t *testing.T) { t.Parallel() var facade interface{} From abdf5b37cb103d73d6c9b940436ba5f32ae6f1f2 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 15 Jan 2020 14:43:12 +0200 Subject: [PATCH 10/10] Fix after review - debug / log. --- process/scQueryProcessor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/scQueryProcessor.go b/process/scQueryProcessor.go index 9a43fbc4..3deb849b 100644 --- a/process/scQueryProcessor.go +++ b/process/scQueryProcessor.go @@ -57,7 +57,7 @@ func (scQueryProcessor *SCQueryProcessor) ExecuteQuery(query *process.SCQuery) ( } if isOk { - log.Debug(fmt.Sprintf("SC query sent successfully to observer %v from shard %v, received response", observer.Address, shardID)) + log.Debug("SC query sent successfully, received response", "observer", observer.Address, "shard", shardID) return response.Data, nil }