Merge pull request #786 from status-im/improvement/issue-785/common-logic-to-lib

[#785] Extract lib specific code from geth/common
This commit is contained in:
Adrià Cidre 2018-03-29 16:10:29 +02:00 committed by GitHub
commit 33c739fecf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1591 additions and 1573 deletions

View File

@ -5,9 +5,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"os" "os"
"strings"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -85,67 +83,6 @@ func isNilOrEmpty(bytes hexutil.Bytes) bool {
return bytes == nil || len(bytes) == 0 return bytes == nil || len(bytes) == 0
} }
// APIResponse generic response from API
type APIResponse struct {
Error string `json:"error"`
}
// APIDetailedResponse represents a generic response
// with possible errors.
type APIDetailedResponse struct {
Status bool `json:"status"`
Message string `json:"message,omitempty"`
FieldErrors []APIFieldError `json:"field_errors,omitempty"`
}
func (r APIDetailedResponse) Error() string {
buf := bytes.NewBufferString("")
for _, err := range r.FieldErrors {
buf.WriteString(err.Error() + "\n") // nolint: gas
}
return strings.TrimSpace(buf.String())
}
// APIFieldError represents a set of errors
// related to a parameter.
type APIFieldError struct {
Parameter string `json:"parameter,omitempty"`
Errors []APIError `json:"errors"`
}
func (e APIFieldError) Error() string {
if len(e.Errors) == 0 {
return ""
}
buf := bytes.NewBufferString(fmt.Sprintf("Parameter: %s\n", e.Parameter))
for _, err := range e.Errors {
buf.WriteString(err.Error() + "\n") // nolint: gas
}
return strings.TrimSpace(buf.String())
}
// APIError represents a single error.
type APIError struct {
Message string `json:"message"`
}
func (e APIError) Error() string {
return fmt.Sprintf("message=%s", e.Message)
}
// AccountInfo represents account's info
type AccountInfo struct {
Address string `json:"address"`
PubKey string `json:"pubkey"`
Mnemonic string `json:"mnemonic"`
Error string `json:"error"`
}
// StopRPCCallError defines a error type specific for killing a execution process. // StopRPCCallError defines a error type specific for killing a execution process.
type StopRPCCallError struct { type StopRPCCallError struct {
Err error Err error

View File

@ -2,7 +2,6 @@ package common
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -10,7 +9,6 @@ import (
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime/debug" "runtime/debug"
"time"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/pborman/uuid" "github.com/pborman/uuid"
@ -44,18 +42,6 @@ func ImportTestAccount(keystoreDir, accountFile string) error {
return err return err
} }
// PanicAfter throws panic() after waitSeconds, unless abort channel receives notification
func PanicAfter(waitSeconds time.Duration, abort chan struct{}, desc string) {
go func() {
select {
case <-abort:
return
case <-time.After(waitSeconds):
panic("whatever you were doing takes toooo long: " + desc)
}
}()
}
// MessageIDFromContext returns message id from context (if exists) // MessageIDFromContext returns message id from context (if exists)
func MessageIDFromContext(ctx context.Context) string { func MessageIDFromContext(ctx context.Context) string {
if ctx == nil { if ctx == nil {
@ -68,17 +54,6 @@ func MessageIDFromContext(ctx context.Context) string {
return "" return ""
} }
// ParseJSONArray parses JSON array into Go array of string
func ParseJSONArray(items string) ([]string, error) {
var parsedItems []string
err := json.Unmarshal([]byte(items), &parsedItems)
if err != nil {
return nil, err
}
return parsedItems, nil
}
// Fatalf is used to halt the execution. // Fatalf is used to halt the execution.
// When called the function prints stack end exits. // When called the function prints stack end exits.
// Failure is logged into both StdErr and StdOut. // Failure is logged into both StdErr and StdOut.

View File

@ -55,22 +55,22 @@ func StopNode() *C.char {
//ValidateNodeConfig validates config for status node //ValidateNodeConfig validates config for status node
//export ValidateNodeConfig //export ValidateNodeConfig
func ValidateNodeConfig(configJSON *C.char) *C.char { func ValidateNodeConfig(configJSON *C.char) *C.char {
var resp common.APIDetailedResponse var resp APIDetailedResponse
_, err := params.LoadNodeConfig(C.GoString(configJSON)) _, err := params.LoadNodeConfig(C.GoString(configJSON))
// Convert errors to common.APIDetailedResponse // Convert errors to APIDetailedResponse
switch err := err.(type) { switch err := err.(type) {
case validator.ValidationErrors: case validator.ValidationErrors:
resp = common.APIDetailedResponse{ resp = APIDetailedResponse{
Message: "validation: validation failed", Message: "validation: validation failed",
FieldErrors: make([]common.APIFieldError, len(err)), FieldErrors: make([]APIFieldError, len(err)),
} }
for i, ve := range err { for i, ve := range err {
resp.FieldErrors[i] = common.APIFieldError{ resp.FieldErrors[i] = APIFieldError{
Parameter: ve.Namespace(), Parameter: ve.Namespace(),
Errors: []common.APIError{ Errors: []APIError{
{ {
Message: fmt.Sprintf("field validation failed on the '%s' tag", ve.Tag()), Message: fmt.Sprintf("field validation failed on the '%s' tag", ve.Tag()),
}, },
@ -78,11 +78,11 @@ func ValidateNodeConfig(configJSON *C.char) *C.char {
} }
} }
case error: case error:
resp = common.APIDetailedResponse{ resp = APIDetailedResponse{
Message: fmt.Sprintf("validation: %s", err.Error()), Message: fmt.Sprintf("validation: %s", err.Error()),
} }
case nil: case nil:
resp = common.APIDetailedResponse{ resp = APIDetailedResponse{
Status: true, Status: true,
} }
} }
@ -121,7 +121,7 @@ func CreateAccount(password *C.char) *C.char {
errString = err.Error() errString = err.Error()
} }
out := common.AccountInfo{ out := AccountInfo{
Address: address, Address: address,
PubKey: pubKey, PubKey: pubKey,
Mnemonic: mnemonic, Mnemonic: mnemonic,
@ -142,7 +142,7 @@ func CreateChildAccount(parentAddress, password *C.char) *C.char {
errString = err.Error() errString = err.Error()
} }
out := common.AccountInfo{ out := AccountInfo{
Address: address, Address: address,
PubKey: pubKey, PubKey: pubKey,
Error: errString, Error: errString,
@ -162,7 +162,7 @@ func RecoverAccount(password, mnemonic *C.char) *C.char {
errString = err.Error() errString = err.Error()
} }
out := common.AccountInfo{ out := AccountInfo{
Address: address, Address: address,
PubKey: pubKey, PubKey: pubKey,
Mnemonic: C.GoString(mnemonic), Mnemonic: C.GoString(mnemonic),
@ -225,7 +225,7 @@ func CompleteTransactions(ids, password *C.char) *C.char {
out := common.CompleteTransactionsResult{} out := common.CompleteTransactionsResult{}
out.Results = make(map[string]common.CompleteTransactionResult) out.Results = make(map[string]common.CompleteTransactionResult)
parsedIDs, err := common.ParseJSONArray(C.GoString(ids)) parsedIDs, err := ParseJSONArray(C.GoString(ids))
if err != nil { if err != nil {
out.Results["none"] = common.CompleteTransactionResult{ out.Results["none"] = common.CompleteTransactionResult{
Error: err.Error(), Error: err.Error(),
@ -288,7 +288,7 @@ func DiscardTransactions(ids *C.char) *C.char {
out := common.DiscardTransactionsResult{} out := common.DiscardTransactionsResult{}
out.Results = make(map[string]common.DiscardTransactionResult) out.Results = make(map[string]common.DiscardTransactionResult)
parsedIDs, err := common.ParseJSONArray(C.GoString(ids)) parsedIDs, err := ParseJSONArray(C.GoString(ids))
if err != nil { if err != nil {
out.Results["none"] = common.DiscardTransactionResult{ out.Results["none"] = common.DiscardTransactionResult{
Error: err.Error(), Error: err.Error(),
@ -383,7 +383,7 @@ func makeJSONResponse(err error) *C.char {
errString = err.Error() errString = err.Error()
} }
out := common.APIResponse{ out := APIResponse{
Error: errString, Error: errString,
} }
outBytes, _ := json.Marshal(out) outBytes, _ := json.Marshal(out)
@ -409,7 +409,7 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char)
errString := "" errString := ""
defer func() { defer func() {
out := common.NotifyResult{ out := NotifyResult{
Status: err == nil, Status: err == nil,
Error: errString, Error: errString,
} }
@ -424,7 +424,7 @@ func NotifyUsers(message, payloadJSON, tokensArray *C.char) (outCBytes *C.char)
outCBytes = C.CString(string(outBytes)) outCBytes = C.CString(string(outBytes))
}() }()
tokens, err := common.ParseJSONArray(C.GoString(tokensArray)) tokens, err := ParseJSONArray(C.GoString(tokensArray))
if err != nil { if err != nil {
errString = err.Error() errString = err.Error()
return return

View File

@ -9,7 +9,6 @@ package main
import ( import (
"testing" "testing"
"github.com/status-im/status-go/geth/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -23,7 +22,7 @@ func TestExportedAPI(t *testing.T) {
} }
func TestValidateNodeConfig(t *testing.T) { func TestValidateNodeConfig(t *testing.T) {
noErrorsCallback := func(resp common.APIDetailedResponse) { noErrorsCallback := func(resp APIDetailedResponse) {
require.True(t, resp.Status, "expected status equal true") require.True(t, resp.Status, "expected status equal true")
require.Empty(t, resp.FieldErrors) require.Empty(t, resp.FieldErrors)
require.Empty(t, resp.Message) require.Empty(t, resp.Message)
@ -32,7 +31,7 @@ func TestValidateNodeConfig(t *testing.T) {
testCases := []struct { testCases := []struct {
Name string Name string
Config string Config string
Callback func(common.APIDetailedResponse) Callback func(APIDetailedResponse)
}{ }{
{ {
Name: "response for valid config", Name: "response for valid config",
@ -45,7 +44,7 @@ func TestValidateNodeConfig(t *testing.T) {
{ {
Name: "response for invalid JSON string", Name: "response for invalid JSON string",
Config: `{"Network": }`, Config: `{"Network": }`,
Callback: func(resp common.APIDetailedResponse) { Callback: func(resp APIDetailedResponse) {
require.False(t, resp.Status) require.False(t, resp.Status)
require.Contains(t, resp.Message, "validation: invalid character '}'") require.Contains(t, resp.Message, "validation: invalid character '}'")
}, },
@ -53,7 +52,7 @@ func TestValidateNodeConfig(t *testing.T) {
{ {
Name: "response for config with multiple errors", Name: "response for config with multiple errors",
Config: `{}`, Config: `{}`,
Callback: func(resp common.APIDetailedResponse) { Callback: func(resp APIDetailedResponse) {
required := map[string]string{ required := map[string]string{
"NodeConfig.NetworkID": "required", "NodeConfig.NetworkID": "required",
"NodeConfig.DataDir": "required", "NodeConfig.DataDir": "required",

1479
lib/library_test_utils.go Normal file

File diff suppressed because it is too large Load Diff

77
lib/types.go Normal file
View File

@ -0,0 +1,77 @@
package main
import (
"bytes"
"fmt"
"strings"
)
// APIResponse generic response from API.
type APIResponse struct {
Error string `json:"error"`
}
// APIDetailedResponse represents a generic response
// with possible errors.
type APIDetailedResponse struct {
Status bool `json:"status"`
Message string `json:"message,omitempty"`
FieldErrors []APIFieldError `json:"field_errors,omitempty"`
}
// Error string representation of APIDetailedResponse.
func (r APIDetailedResponse) Error() string {
buf := bytes.NewBufferString("")
for _, err := range r.FieldErrors {
buf.WriteString(err.Error() + "\n") // nolint: gas
}
return strings.TrimSpace(buf.String())
}
// APIFieldError represents a set of errors
// related to a parameter.
type APIFieldError struct {
Parameter string `json:"parameter,omitempty"`
Errors []APIError `json:"errors"`
}
// Error string representation of APIFieldError.
func (e APIFieldError) Error() string {
if len(e.Errors) == 0 {
return ""
}
buf := bytes.NewBufferString(fmt.Sprintf("Parameter: %s\n", e.Parameter))
for _, err := range e.Errors {
buf.WriteString(err.Error() + "\n") // nolint: gas
}
return strings.TrimSpace(buf.String())
}
// APIError represents a single error.
type APIError struct {
Message string `json:"message"`
}
// Error string representation of APIError.
func (e APIError) Error() string {
return fmt.Sprintf("message=%s", e.Message)
}
// AccountInfo represents account's info.
type AccountInfo struct {
Address string `json:"address"`
PubKey string `json:"pubkey"`
Mnemonic string `json:"mnemonic"`
Error string `json:"error"`
}
// NotifyResult is a JSON returned from notify message.
type NotifyResult struct {
Status bool `json:"status"`
Error string `json:"error,omitempty"`
}

File diff suppressed because it is too large Load Diff