Skip to content

Commit

Permalink
Merge pull request #466 from ElrondNetwork/development-to-master-sep20
Browse files Browse the repository at this point in the history
Development to master sep20
  • Loading branch information
AdoAdoAdo authored Sep 23, 2019
2 parents 450ac81 + 223a27e commit c5cf026
Show file tree
Hide file tree
Showing 585 changed files with 13,040 additions and 5,668 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

<br>

[![](https://img.shields.io/badge/made%20by-Elrond%20Network-blue.svg?style=flat-square)](http://elrond.com/)
[![](https://img.shields.io/badge/project-Elrond%20Network%20Testnet-blue.svg?style=flat-square)](http://elrond.com/)
[![](https://img.shields.io/badge/made%20by-Elrond%20Network-blue.svg)](http://elrond.com/)
[![](https://img.shields.io/badge/project-Elrond%20Network%20Testnet-blue.svg)](https://testnet.elrond.com/)
[![Go Report Card](https://goreportcard.com/badge/github.com/ElrondNetwork/elrond-go)](https://goreportcard.com/report/github.com/ElrondNetwork/elrond-go)
[![LoC](https://tokei.rs/b1/github/ElrondNetwork/elrond-go?category=code)](https://github.com/ElrondNetwork/elrond-go)
[![API Reference](https://godoc.org/github.com/ElrondNetwork/elrond-go?status.svg)](https://godoc.org/github.com/ElrondNetwork/elrond-go)
[![riot.im](https://img.shields.io/badge/riot.im-JOIN%20CHAT-green.svg)](https://riot.im/app/#/room/#elrond:matrix.org)

# Elrond go

Expand Down
1 change: 1 addition & 0 deletions api/address/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type FacadeHandler interface {
GetBalance(address string) (*big.Int, error)
GetAccount(address string) (*state.Account, error)
IsInterfaceNil() bool
}

type accountResponse struct {
Expand Down
1 change: 1 addition & 0 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type MainApiHandler interface {
PrometheusMonitoring() bool
PrometheusJoinURL() string
PrometheusNetworkID() string
IsInterfaceNil() bool
}

// Start will boot up the api and appropriate routes, handlers and validators
Expand Down
4 changes: 2 additions & 2 deletions api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ var ErrInvalidSignatureHex = errors.New("invalid signature, could not decode hex
// ErrValidationEmptyTxHash signals an empty tx hash was provided
var ErrValidationEmptyTxHash = errors.New("TxHash is empty")

// ErrGetTransaction signals an error happend trying to fetch a transaction
// ErrGetTransaction signals an error happened trying to fetch a transaction
var ErrGetTransaction = errors.New("transaction getting failed")

// ErrTxNotFound signals an error happend trying to fetch a transaction
// ErrTxNotFound signals an error happened trying to fetch a transaction
var ErrTxNotFound = errors.New("transaction was not found")
8 changes: 8 additions & 0 deletions api/mock/cacherStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ func (cs *CacherStub) Len() int {
func (cs *CacherStub) RegisterHandler(handler func(key []byte)) {
cs.RegisterHandlerCalled(handler)
}

// IsInterfaceNil returns true if there is no value under the interface
func (cs *CacherStub) IsInterfaceNil() bool {
if cs == nil {
return true
}
return false
}
38 changes: 38 additions & 0 deletions api/mock/facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/ElrondNetwork/elrond-go/core/statistics"
"github.com/ElrondNetwork/elrond-go/data/state"
"github.com/ElrondNetwork/elrond-go/data/transaction"
"github.com/ElrondNetwork/elrond-go/node/external"
"github.com/ElrondNetwork/elrond-go/node/heartbeat"
)

Expand All @@ -23,9 +24,12 @@ type Facade struct {
GenerateTransactionHandler func(sender string, receiver string, value *big.Int, code string) (*transaction.Transaction, error)
GetTransactionHandler func(hash string) (*transaction.Transaction, error)
SendTransactionHandler func(nonce uint64, sender string, receiver string, value *big.Int, gasPrice uint64, gasLimit uint64, code string, signature []byte) (string, error)
CreateTransactionHandler func(nonce uint64, value *big.Int, receiverHex string, senderHex string, gasPrice uint64, gasLimit uint64, data string, signatureHex string, challenge string) (*transaction.Transaction, error)
SendBulkTransactionsHandler func(txs []*transaction.Transaction) (uint64, error)
GenerateAndSendBulkTransactionsHandler func(destination string, value *big.Int, nrTransactions uint64) error
GenerateAndSendBulkTransactionsOneByOneHandler func(destination string, value *big.Int, nrTransactions uint64) error
GetDataValueHandler func(address string, funcName string, argsBuff ...[]byte) ([]byte, error)
StatusMetricsHandler func() external.StatusMetricsHandler
}

// IsNodeRunning is the mock implementation of a handler's IsNodeRunning method
Expand Down Expand Up @@ -83,6 +87,22 @@ func (f *Facade) GenerateTransaction(sender string, receiver string, value *big.
return f.GenerateTransactionHandler(sender, receiver, value, code)
}

// CreateTransaction is mock implementation of a handler's CreateTransaction method
func (f *Facade) CreateTransaction(
nonce uint64,
value *big.Int,
receiverHex string,
senderHex string,
gasPrice uint64,
gasLimit uint64,
data string,
signatureHex string,
challenge string,
) (*transaction.Transaction, error) {

return f.CreateTransactionHandler(nonce, value, receiverHex, senderHex, gasPrice, gasLimit, data, signatureHex, challenge)
}

// GetTransaction is the mock implementation of a handler's GetTransaction method
func (f *Facade) GetTransaction(hash string) (*transaction.Transaction, error) {
return f.GetTransactionHandler(hash)
Expand All @@ -93,6 +113,11 @@ func (f *Facade) SendTransaction(nonce uint64, sender string, receiver string, v
return f.SendTransactionHandler(nonce, sender, receiver, value, gasPrice, gasLimit, code, signature)
}

// SendBulkTransactions is the mock implementation of a handler's SendBulkTransactions method
func (f *Facade) SendBulkTransactions(txs []*transaction.Transaction) (uint64, error) {
return f.SendBulkTransactionsHandler(txs)
}

// GenerateAndSendBulkTransactions is the mock implementation of a handler's GenerateAndSendBulkTransactions method
func (f *Facade) GenerateAndSendBulkTransactions(destination string, value *big.Int, nrTransactions uint64) error {
return f.GenerateAndSendBulkTransactionsHandler(destination, value, nrTransactions)
Expand All @@ -107,6 +132,19 @@ func (f *Facade) GetVmValue(address string, funcName string, argsBuff ...[]byte)
return f.GetDataValueHandler(address, funcName, argsBuff...)
}

// StatusMetrics is the mock implementation for the StatusMetrics
func (f *Facade) StatusMetrics() external.StatusMetricsHandler {
return f.StatusMetricsHandler()
}

// IsInterfaceNil returns true if there is no value under the interface
func (f *Facade) IsInterfaceNil() bool {
if f == nil {
return true
}
return false
}

// WrongFacade is a struct that can be used as a wrong implementation of the node router handler
type WrongFacade struct {
}
37 changes: 23 additions & 14 deletions api/node/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/ElrondNetwork/elrond-go/api/errors"
"github.com/ElrondNetwork/elrond-go/core/statistics"
"github.com/ElrondNetwork/elrond-go/node/external"
"github.com/ElrondNetwork/elrond-go/node/heartbeat"
"github.com/gin-gonic/gin"
)
Expand All @@ -20,6 +21,8 @@ type FacadeHandler interface {
GetCurrentPublicKey() string
GetHeartbeats() ([]heartbeat.PubKeyHeartbeat, error)
TpsBenchmark() *statistics.TpsBenchmark
StatusMetrics() external.StatusMetricsHandler
IsInterfaceNil() bool
}

type statisticsResponse struct {
Expand Down Expand Up @@ -49,23 +52,12 @@ type shardStatisticsResponse struct {

// Routes defines node related routes
func Routes(router *gin.RouterGroup) {
router.GET("/start", StartNode)
router.GET("/status", Status)
router.GET("/stop", StopNode)
router.GET("/address", Address)
router.GET("/heartbeatstatus", HeartbeatStatus)
router.GET("/start", StartNode)
router.GET("/statistics", Statistics)
}

// Status returns the state of the node e.g. running/stopped
func Status(c *gin.Context) {
ef, ok := c.MustGet("elrondFacade").(FacadeHandler)
if !ok {
c.JSON(http.StatusInternalServerError, gin.H{"error": errors.ErrInvalidAppContext.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"message": "ok", "running": ef.IsNodeRunning()})
router.GET("/status", StatusMetrics)
router.GET("/stop", StopNode)
}

// StartNode will start the node instance
Expand Down Expand Up @@ -156,6 +148,23 @@ func Statistics(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"statistics": statsFromTpsBenchmark(ef.TpsBenchmark())})
}

// StatusMetrics returns the node statistics exported by an StatusMetricsHandler
func StatusMetrics(c *gin.Context) {
ef, ok := c.MustGet("elrondFacade").(FacadeHandler)
if !ok {
c.JSON(http.StatusInternalServerError, gin.H{"error": errors.ErrInvalidAppContext.Error()})
return
}

details, err := ef.StatusMetrics().StatusMetricsMap()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.JSON(http.StatusOK, gin.H{"details": details})
}

func statsFromTpsBenchmark(tpsBenchmark *statistics.TpsBenchmark) statisticsResponse {
sr := statisticsResponse{}
sr.LiveTPS = tpsBenchmark.LiveTPS()
Expand Down
83 changes: 28 additions & 55 deletions api/node/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"

"github.com/ElrondNetwork/elrond-go/api/errors"
"github.com/ElrondNetwork/elrond-go/api/mock"
"github.com/ElrondNetwork/elrond-go/api/node"
"github.com/ElrondNetwork/elrond-go/core/statistics"
"github.com/ElrondNetwork/elrond-go/node/external"
"github.com/ElrondNetwork/elrond-go/node/heartbeat"
"github.com/ElrondNetwork/elrond-go/statusHandler"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -54,60 +57,6 @@ func init() {
gin.SetMode(gin.TestMode)
}

func TestStatus_FailsWithoutFacade(t *testing.T) {
t.Parallel()
ws := startNodeServer(nil)
defer func() {
r := recover()
assert.NotNil(t, r, "Not providing elrondFacade context should panic")
}()
req, _ := http.NewRequest("GET", "/node/status", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)
}

func TestStatus_FailsWithWrongFacadeTypeConversion(t *testing.T) {
t.Parallel()
ws := startNodeServerWrongFacade()
req, _ := http.NewRequest("GET", "/node/status", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

statusRsp := StatusResponse{}
loadResponse(resp.Body, &statusRsp)
assert.Equal(t, resp.Code, http.StatusInternalServerError)
assert.Equal(t, statusRsp.Error, errors.ErrInvalidAppContext.Error())
}

func TestStatus_ReturnsCorrectResponseOnStart(t *testing.T) {
t.Parallel()
facade := mock.Facade{}
facade.Running = true
ws := startNodeServer(&facade)
req, _ := http.NewRequest("GET", "/node/status", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

statusRsp := StatusResponse{}
loadResponse(resp.Body, &statusRsp)
assert.True(t, statusRsp.Running)
}

func TestStatus_ReturnsCorrectResponseOnStop(t *testing.T) {
t.Parallel()
facade := mock.Facade{}
ws := startNodeServer(&facade)

facade.Running = false
req2, _ := http.NewRequest("GET", "/node/status", nil)
resp2 := httptest.NewRecorder()
ws.ServeHTTP(resp2, req2)

statusRsp2 := StatusResponse{}
loadResponse(resp2.Body, &statusRsp2)
assert.False(t, statusRsp2.Running)
}

func TestStartNode_FailsWithoutFacade(t *testing.T) {
t.Parallel()
ws := startNodeServer(nil)
Expand Down Expand Up @@ -376,7 +325,7 @@ func TestHeartbeatstatus(t *testing.T) {
TimeStamp: time.Now(),
MaxInactiveTime: heartbeat.Duration{Duration: 0},
IsActive: true,
ShardID: uint32(0),
ReceivedShardID: uint32(0),
},
}
facade := mock.Facade{
Expand Down Expand Up @@ -442,6 +391,30 @@ func TestStatistics_ReturnsSuccessfully(t *testing.T) {
assert.Equal(t, statisticsRsp.Statistics.NrOfShards, nrOfShards)
}

func TestStatusMetrics_ShouldDisplayMetrics(t *testing.T) {
statusMetricsProvider := statusHandler.NewStatusMetrics()
key := "test-details-key"
value := "test-details-value"
statusMetricsProvider.SetStringValue(key, value)

facade := mock.Facade{}
facade.StatusMetricsHandler = func() external.StatusMetricsHandler {
return statusMetricsProvider
}

ws := startNodeServer(&facade)
req, _ := http.NewRequest("GET", "/node/status", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

respBytes, _ := ioutil.ReadAll(resp.Body)
respStr := string(respBytes)
assert.Equal(t, resp.Code, http.StatusOK)

keyAndValueFoundInResponse := strings.Contains(respStr, key) && strings.Contains(respStr, value)
assert.True(t, keyAndValueFoundInResponse)
}

func loadResponse(rsp io.Reader, destination interface{}) {
jsonParser := json.NewDecoder(rsp)
err := jsonParser.Decode(destination)
Expand Down
Loading

0 comments on commit c5cf026

Please sign in to comment.