Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test coverage api package [accounts, blocks, events, node, transactions, transfers] #681

Merged
merged 20 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3391cf2
test: add test coverage for api events, transactions and transfers pa…
paologalligit Mar 14, 2024
ed782a9
test: refactored httpGet util function to check also response status …
paologalligit Mar 14, 2024
59165cb
test: refactored httpPost util function to check also response status…
paologalligit Mar 14, 2024
a358416
test: refactored errors as exportable vars
paologalligit Mar 14, 2024
84f48f5
refactor: replace POST and GET string with http.Method
paologalligit Mar 14, 2024
38161fc
test: raised package account coverage at 83.6%
paologalligit Mar 14, 2024
4da8509
test: raise api/blocks test coverage to 82.8%
paologalligit Mar 14, 2024
250a427
test: raise node code coverage to 100%
paologalligit Mar 15, 2024
3bb0647
test: add more tests
paologalligit Mar 20, 2024
d3a7e27
Fix: expected response error status
paologalligit Mar 20, 2024
20c06e1
style: remove unnecessary trailing newline
paologalligit Mar 20, 2024
6948903
refactor: rollback function extraction
paologalligit Mar 28, 2024
8cc6e6a
tests: add new tests due to transactions.go rollback
paologalligit Mar 28, 2024
4a0cdc0
refactor: rename test packages by appending _test
paologalligit Mar 28, 2024
7a0ab94
style: add comments to separate api/transactions tests
paologalligit Mar 28, 2024
8af7c22
refactor: rollback export_test.go file exporting private function
paologalligit Mar 29, 2024
f25a066
typo: remove typo in test
paologalligit Apr 8, 2024
245237b
refactor: fixes as per review
paologalligit Apr 11, 2024
31217f8
refactor: make errNotFound private again
paologalligit Apr 16, 2024
d903f1f
tweak api/transaction tests, disable log for tests
libotony Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions api/accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,10 @@ func (a *Accounts) handleRevision(revision string) (*chain.BlockSummary, error)
func (a *Accounts) Mount(root *mux.Router, pathPrefix string) {
sub := root.PathPrefix(pathPrefix).Subrouter()

sub.Path("/*").Methods("POST").HandlerFunc(utils.WrapHandlerFunc(a.handleCallBatchCode))
sub.Path("/*").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallBatchCode))
sub.Path("/{address}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetAccount))
sub.Path("/{address}/code").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetCode))
sub.Path("/{address}/storage/{key}").Methods("GET").HandlerFunc(utils.WrapHandlerFunc(a.handleGetStorage))
sub.Path("").Methods("POST").HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
sub.Path("/{address}").Methods("POST").HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
sub.Path("/{address}/storage/{key}").Methods(http.MethodGet).HandlerFunc(utils.WrapHandlerFunc(a.handleGetStorage))
sub.Path("").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
sub.Path("/{address}").Methods(http.MethodPost).HandlerFunc(utils.WrapHandlerFunc(a.handleCallContract))
}
160 changes: 135 additions & 25 deletions api/accounts/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying
// file LICENSE or <https://www.gnu.org/licenses/lgpl-3.0.html>

package accounts_test
package accounts
libotony marked this conversation as resolved.
Show resolved Hide resolved

import (
"bytes"
"encoding/json"
"fmt"
"io"
"math/big"
"net/http"
Expand All @@ -22,7 +23,7 @@ import (
"github.com/gorilla/mux"
"github.com/stretchr/testify/assert"
ABI "github.com/vechain/thor/v2/abi"
"github.com/vechain/thor/v2/api/accounts"
"github.com/vechain/thor/v2/block"
"github.com/vechain/thor/v2/chain"
"github.com/vechain/thor/v2/genesis"
"github.com/vechain/thor/v2/muxdb"
Expand Down Expand Up @@ -86,6 +87,8 @@ var addr = thor.BytesToAddress([]byte("to"))
var value = big.NewInt(10000)
var storageKey = thor.Bytes32{}
var storageValue = byte(1)
var gasLimit uint64
var genesisBlock *block.Block

var contractAddr thor.Address

Expand All @@ -97,13 +100,18 @@ var invalidAddr = "abc"
var invalidBytes32 = "0x000000000000000000000000000000000000000000000000000000000000000g" //invlaid bytes32
var invalidNumberRevision = "4294967296" //invalid block number

var accounts *Accounts
var ts *httptest.Server

func TestAccount(t *testing.T) {
initAccountServer(t)
defer ts.Close()
getAccount(t)
getAccountWithNonExisitingRevision(t)
getAccountWithGenesisRevision(t)
getInvalidCode(t)
getCode(t)
getStorageWhenError(t)
getStorage(t)
deployContractWithCall(t)
callContract(t)
Expand All @@ -119,14 +127,42 @@ func getAccount(t *testing.T) {

//revision is optional defaut `best`
res, statusCode := httpGet(t, ts.URL+"/accounts/"+addr.String())
var acc accounts.Account
var acc Account
if err := json.Unmarshal(res, &acc); err != nil {
t.Fatal(err)
}
assert.Equal(t, math.HexOrDecimal256(*value), acc.Balance, "balance should be equal")
assert.Equal(t, http.StatusOK, statusCode, "OK")
}

func getAccountWithNonExisitingRevision(t *testing.T) {
revision64Len := "0123456789012345678901234567890123456789012345678901234567890123"

_, statusCode := httpGet(t, ts.URL+"/accounts/"+addr.String()+"?revision="+revision64Len)

assert.Equal(t, http.StatusBadRequest, statusCode, "bad revision")
}

func getAccountWithGenesisRevision(t *testing.T) {
res, statusCode := httpGet(t, ts.URL+"/accounts/"+addr.String()+"?revision="+genesisBlock.Header().ID().String())
assert.Equal(t, http.StatusOK, statusCode, "bad revision")

var acc Account
if err := json.Unmarshal(res, &acc); err != nil {
t.Fatal(err)
}

balance, err := acc.Balance.MarshalText()
assert.NoError(t, err)
assert.Equal(t, "0x0", string(balance), "balance should be 0")

energy, err := acc.Energy.MarshalText()
assert.NoError(t, err)
assert.Equal(t, "0x0", string(energy), "energy should be 0")

assert.Equal(t, false, acc.HasCode, "hasCode should be false")
}

func getCode(t *testing.T) {
_, statusCode := httpGet(t, ts.URL+"/accounts/"+invalidAddr+"/code")
assert.Equal(t, http.StatusBadRequest, statusCode, "bad address")
Expand All @@ -148,6 +184,36 @@ func getCode(t *testing.T) {
assert.Equal(t, http.StatusOK, statusCode, "OK")
}

func getInvalidCode(t *testing.T) {
blockSummary := &chain.BlockSummary{
Header: genesisBlock.Header(),
Txs: []thor.Bytes32{thor.BytesToBytes32([]byte("123"))},
Size: 1,
Conflicts: 1,
SteadyNum: 1,
}

code, err := accounts.getCode(addr, blockSummary)

assert.Error(t, err)
assert.Empty(t, code)
}

func getStorageWhenError(t *testing.T) {
blockSummary := &chain.BlockSummary{
Header: genesisBlock.Header(),
Txs: []thor.Bytes32{thor.BytesToBytes32([]byte("123"))},
Size: 1,
Conflicts: 1,
SteadyNum: 1,
}

storage, err := accounts.getStorage(addr, storageKey, blockSummary)

assert.Error(t, err)
assert.Equal(t, thor.Bytes32{}, storage)
}

func getStorage(t *testing.T) {
_, statusCode := httpGet(t, ts.URL+"/accounts/"+invalidAddr+"/storage/"+storageKey.String())
assert.Equal(t, http.StatusBadRequest, statusCode, "bad address")
Expand Down Expand Up @@ -181,6 +247,7 @@ func initAccountServer(t *testing.T) {
if err != nil {
t.Fatal(err)
}
genesisBlock = b
repo, _ := chain.NewRepository(db, b)
claTransfer := tx.NewClause(&addr).WithValue(value)
claDeploy := tx.NewClause(nil).WithData(bytecode)
Expand All @@ -200,7 +267,9 @@ func initAccountServer(t *testing.T) {
packTx(repo, stater, transactionCall, t)

router := mux.NewRouter()
accounts.New(repo, stater, math.MaxUint64, thor.NoFork).Mount(router, "/accounts")
gasLimit = math.MaxUint32
accounts = New(repo, stater, gasLimit, thor.NoFork)
accounts.Mount(router, "/accounts")
ts = httptest.NewServer(router)
}

Expand Down Expand Up @@ -247,14 +316,14 @@ func packTx(repo *chain.Repository, stater *state.Stater, transaction *tx.Transa
}

func deployContractWithCall(t *testing.T) {
badBody := &accounts.CallData{
badBody := &CallData{
Gas: 10000000,
Data: "abc",
}
_, statusCode := httpPost(t, ts.URL+"/accounts", badBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "bad data")

reqBody := &accounts.CallData{
reqBody := &CallData{
Gas: 10000000,
Data: hexutil.Encode(bytecode),
}
Expand All @@ -264,7 +333,7 @@ func deployContractWithCall(t *testing.T) {

//revision is optional defaut `best`
res, _ := httpPost(t, ts.URL+"/accounts", reqBody)
var output *accounts.CallResult
var output *CallResult
if err := json.Unmarshal(res, &output); err != nil {
t.Fatal(err)
}
Expand All @@ -275,7 +344,14 @@ func callContract(t *testing.T) {
_, statusCode := httpPost(t, ts.URL+"/accounts/"+invalidAddr, nil)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid address")

badBody := &accounts.CallData{
malFormedBody := 123
_, statusCode = httpPost(t, ts.URL+"/accounts", malFormedBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid address")

_, statusCode = httpPost(t, ts.URL+"/accounts/"+contractAddr.String(), malFormedBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid address")

badBody := &CallData{
Data: "input",
}
_, statusCode = httpPost(t, ts.URL+"/accounts/"+contractAddr.String(), badBody)
Expand All @@ -290,11 +366,11 @@ func callContract(t *testing.T) {
if err != nil {
t.Fatal(err)
}
reqBody := &accounts.CallData{
reqBody := &CallData{
Data: hexutil.Encode(input),
}
res, statusCode := httpPost(t, ts.URL+"/accounts/"+contractAddr.String(), reqBody)
var output *accounts.CallResult
var output *CallResult
if err = json.Unmarshal(res, &output); err != nil {
t.Fatal(err)
}
Expand All @@ -312,22 +388,44 @@ func callContract(t *testing.T) {
}

func batchCall(t *testing.T) {
badBody := &accounts.BatchCallData{
Clauses: accounts.Clauses{
accounts.Clause{
// Request body is not a valid JSON
malformedBody := 123
_, statusCode := httpPost(t, ts.URL+"/accounts/*", malformedBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "malformed data")

// Request body is not a valid BatchCallData
badBody := &BatchCallData{
Clauses: Clauses{
Clause{
To: &contractAddr,
Data: "data1",
Value: nil,
},
accounts.Clause{
Clause{
To: &contractAddr,
Data: "data2",
Value: nil,
}},
}
_, statusCode := httpPost(t, ts.URL+"/accounts/*", badBody)
_, statusCode = httpPost(t, ts.URL+"/accounts/*", badBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid data")

// Request body has an invalid blockRef
badBlockRef := &BatchCallData{
BlockRef: "0x00",
}
_, statusCode = httpPost(t, ts.URL+"/accounts/*", badBlockRef)
assert.Equal(t, http.StatusInternalServerError, statusCode, "invalid blockRef")

// Request body has an invalid malformed revision
_, statusCode = httpPost(t, fmt.Sprintf("%s/accounts/*?revision=%d", ts.URL, malformedBody), badBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid revision")

// Request body has an invalid revision number
_, statusCode = httpPost(t, ts.URL+"/accounts/*?revision="+invalidNumberRevision, badBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid revision")

// Valid request
a := uint8(1)
b := uint8(2)
method := "add"
Expand All @@ -337,25 +435,22 @@ func batchCall(t *testing.T) {
if err != nil {
t.Fatal(err)
}
reqBody := &accounts.BatchCallData{
Clauses: accounts.Clauses{
accounts.Clause{
reqBody := &BatchCallData{
Clauses: Clauses{
Clause{
To: &contractAddr,
Data: hexutil.Encode(input),
Value: nil,
},
accounts.Clause{
Clause{
To: &contractAddr,
Data: hexutil.Encode(input),
Value: nil,
}},
}

_, statusCode = httpPost(t, ts.URL+"/accounts/*?revision="+invalidNumberRevision, badBody)
assert.Equal(t, http.StatusBadRequest, statusCode, "invalid revision")

res, statusCode := httpPost(t, ts.URL+"/accounts/*", reqBody)
var results accounts.BatchCallResults
var results BatchCallResults
if err = json.Unmarshal(res, &results); err != nil {
t.Fatal(err)
}
Expand All @@ -373,9 +468,10 @@ func batchCall(t *testing.T) {
}
assert.Equal(t, http.StatusOK, statusCode)

// Valid request
big := math.HexOrDecimal256(*big.NewInt(1000))
fullBody := &accounts.BatchCallData{
Clauses: accounts.Clauses{},
fullBody := &BatchCallData{
Clauses: Clauses{},
Gas: 21000,
GasPrice: &big,
ProvedWork: &big,
Expand All @@ -386,6 +482,20 @@ func batchCall(t *testing.T) {
}
_, statusCode = httpPost(t, ts.URL+"/accounts/*", fullBody)
assert.Equal(t, http.StatusOK, statusCode)

// Request with not enough gas
tooMuchGasBody := &BatchCallData{
Clauses: Clauses{},
Gas: math.MaxUint64,
GasPrice: &big,
ProvedWork: &big,
Caller: &contractAddr,
GasPayer: &contractAddr,
Expiration: 100,
BlockRef: "0x00000000aabbccdd",
}
_, statusCode = httpPost(t, ts.URL+"/accounts/*", tooMuchGasBody)
assert.Equal(t, http.StatusForbidden, statusCode)
}

func httpPost(t *testing.T, url string, body interface{}) ([]byte, int) {
Expand Down
Loading
Loading