Clean api package (#1055)
This commit is contained in:
parent
3ca120c2aa
commit
afb3ce159e
|
@ -5,30 +5,30 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// AppState represents if the app is in foreground, background or some other state
|
||||
type AppState string
|
||||
// appState represents if the app is in foreground, background or some other state
|
||||
type appState string
|
||||
|
||||
func (a AppState) String() string {
|
||||
func (a appState) String() string {
|
||||
return string(a)
|
||||
}
|
||||
|
||||
// Specific app states
|
||||
// see https://facebook.github.io/react-native/docs/appstate.html
|
||||
const (
|
||||
AppStateForeground = AppState("active") // these constant values are kept in sync with React Native
|
||||
AppStateBackground = AppState("background")
|
||||
AppStateInactive = AppState("inactive")
|
||||
appStateForeground = appState("active") // these constant values are kept in sync with React Native
|
||||
appStateBackground = appState("background")
|
||||
appStateInactive = appState("inactive")
|
||||
|
||||
AppStateInvalid = AppState("")
|
||||
appStateInvalid = appState("")
|
||||
)
|
||||
|
||||
// validAppStates returns an immutable set of valid states.
|
||||
func validAppStates() []AppState {
|
||||
return []AppState{AppStateInactive, AppStateBackground, AppStateForeground}
|
||||
func validAppStates() []appState {
|
||||
return []appState{appStateInactive, appStateBackground, appStateForeground}
|
||||
}
|
||||
|
||||
// ParseAppState creates AppState from a string
|
||||
func ParseAppState(stateString string) (AppState, error) {
|
||||
// parseAppState creates AppState from a string
|
||||
func parseAppState(stateString string) (appState, error) {
|
||||
// a bit of cleaning up
|
||||
stateString = strings.ToLower(strings.TrimSpace(stateString))
|
||||
|
||||
|
@ -38,5 +38,5 @@ func ParseAppState(stateString string) (AppState, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return AppStateInvalid, fmt.Errorf("could not parse app state: %s", stateString)
|
||||
return appStateInvalid, fmt.Errorf("could not parse app state: %s", stateString)
|
||||
}
|
||||
|
|
|
@ -7,22 +7,22 @@ import (
|
|||
)
|
||||
|
||||
func TestParseAppType(t *testing.T) {
|
||||
check := func(input string, expectedState AppState, expectError bool) {
|
||||
actualState, err := ParseAppState(input)
|
||||
assert.Equalf(t, expectedState, actualState, "unexpected result from ParseAppState")
|
||||
check := func(input string, expectedState appState, expectError bool) {
|
||||
actualState, err := parseAppState(input)
|
||||
assert.Equalf(t, expectedState, actualState, "unexpected result from parseAppState")
|
||||
if expectError {
|
||||
assert.NotNil(t, err, "error should not be nil")
|
||||
}
|
||||
}
|
||||
|
||||
check("active", AppStateForeground, false)
|
||||
check("background", AppStateBackground, false)
|
||||
check("inactive", AppStateInactive, false)
|
||||
check(" acTIVE ", AppStateForeground, false)
|
||||
check(" backGROUND ", AppStateBackground, false)
|
||||
check(" INACTIVE ", AppStateInactive, false)
|
||||
check("", AppStateInvalid, true)
|
||||
check("back ground", AppStateInvalid, true)
|
||||
check(" back ground ", AppStateInvalid, true)
|
||||
check(" ", AppStateInvalid, true)
|
||||
check("active", appStateForeground, false)
|
||||
check("background", appStateBackground, false)
|
||||
check("inactive", appStateInactive, false)
|
||||
check(" acTIVE ", appStateForeground, false)
|
||||
check(" backGROUND ", appStateBackground, false)
|
||||
check(" INACTIVE ", appStateInactive, false)
|
||||
check("", appStateInvalid, true)
|
||||
check("back ground", appStateInvalid, true)
|
||||
check(" back ground ", appStateInvalid, true)
|
||||
check(" ", appStateInvalid, true)
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ type StatusBackend struct {
|
|||
transactor *transactions.Transactor
|
||||
jailManager jail.Manager
|
||||
newNotification fcm.NotificationConstructor
|
||||
connectionState ConnectionState
|
||||
connectionState connectionState
|
||||
appState appState
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
|
@ -90,11 +91,6 @@ func (b *StatusBackend) JailManager() jail.Manager {
|
|||
return b.jailManager
|
||||
}
|
||||
|
||||
// PersonalAPI returns reference to personal APIs
|
||||
func (b *StatusBackend) PersonalAPI() *personal.PublicAPI {
|
||||
return b.personalAPI
|
||||
}
|
||||
|
||||
// Transactor returns reference to a status transactor
|
||||
func (b *StatusBackend) Transactor() *transactions.Transactor {
|
||||
return b.transactor
|
||||
|
@ -155,7 +151,7 @@ func (b *StatusBackend) startNode(config *params.NodeConfig) (err error) {
|
|||
}
|
||||
b.log.Info("Handlers registered")
|
||||
|
||||
if err = b.ReSelectAccount(); err != nil {
|
||||
if err = b.reSelectAccount(); err != nil {
|
||||
b.log.Error("Reselect account failed", "err", err)
|
||||
return
|
||||
}
|
||||
|
@ -316,24 +312,22 @@ func (b *StatusBackend) registerHandlers() error {
|
|||
return hash.Hex(), err
|
||||
})
|
||||
|
||||
rpcClient.RegisterHandler(params.PersonalSignMethodName, b.PersonalAPI().Sign)
|
||||
rpcClient.RegisterHandler(params.PersonalRecoverMethodName, b.PersonalAPI().Recover)
|
||||
rpcClient.RegisterHandler(params.PersonalSignMethodName, b.personalAPI.Sign)
|
||||
rpcClient.RegisterHandler(params.PersonalRecoverMethodName, b.personalAPI.Recover)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// ConnectionChange handles network state changes logic.
|
||||
func (b *StatusBackend) ConnectionChange(typ string, expensive bool) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
state := ConnectionState{
|
||||
Type: NewConnectionType(typ),
|
||||
state := connectionState{
|
||||
Type: newConnectionType(typ),
|
||||
Expensive: expensive,
|
||||
}
|
||||
if typ == "none" {
|
||||
if typ == none {
|
||||
state.Offline = true
|
||||
}
|
||||
|
||||
|
@ -348,13 +342,14 @@ func (b *StatusBackend) ConnectionChange(typ string, expensive bool) {
|
|||
// AppStateChange handles app state changes (background/foreground).
|
||||
// state values: see https://facebook.github.io/react-native/docs/appstate.html
|
||||
func (b *StatusBackend) AppStateChange(state string) {
|
||||
appState, err := ParseAppState(state)
|
||||
s, err := parseAppState(state)
|
||||
if err != nil {
|
||||
log.Error("AppStateChange failed, ignoring", "error", err)
|
||||
return // and do nothing
|
||||
}
|
||||
|
||||
b.log.Info("App State changed", "new-state", appState)
|
||||
b.log.Info("App State changed", "new-state", s)
|
||||
b.appState = s
|
||||
|
||||
// TODO: put node in low-power mode if the app is in background (or inactive)
|
||||
// and normal mode if the app is in foreground.
|
||||
|
@ -385,8 +380,8 @@ func (b *StatusBackend) Logout() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ReSelectAccount selects previously selected account, often, after node restart.
|
||||
func (b *StatusBackend) ReSelectAccount() error {
|
||||
// reSelectAccount selects previously selected account, often, after node restart.
|
||||
func (b *StatusBackend) reSelectAccount() error {
|
||||
selectedAccount, err := b.AccountManager().SelectedAccount()
|
||||
if selectedAccount == nil || err == account.ErrNoAccountSelected {
|
||||
return nil
|
||||
|
|
|
@ -103,7 +103,7 @@ func TestBackendGettersConcurrently(t *testing.T) {
|
|||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
assert.NotNil(t, backend.PersonalAPI())
|
||||
assert.NotNil(t, backend.personalAPI)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
|
@ -174,7 +174,7 @@ func TestBackendAccountsConcurrently(t *testing.T) {
|
|||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
assert.NoError(t, backend.ReSelectAccount())
|
||||
assert.NoError(t, backend.reSelectAccount())
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
|
@ -189,7 +189,7 @@ func TestBackendAccountsConcurrently(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBackendConnectionChangesConcurrently(t *testing.T) {
|
||||
connections := [...]string{"wifi", "cellular"}
|
||||
connections := [...]string{wifi, cellular, unknown}
|
||||
backend := NewStatusBackend()
|
||||
count := 3
|
||||
|
||||
|
@ -207,6 +207,18 @@ func TestBackendConnectionChangesConcurrently(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestBackendConnectionChangesToOffline(t *testing.T) {
|
||||
b := NewStatusBackend()
|
||||
b.ConnectionChange(none, false)
|
||||
assert.True(t, b.connectionState.Offline)
|
||||
|
||||
b.ConnectionChange(wifi, false)
|
||||
assert.False(t, b.connectionState.Offline)
|
||||
|
||||
b.ConnectionChange("unknown-state", false)
|
||||
assert.False(t, b.connectionState.Offline)
|
||||
}
|
||||
|
||||
func TestBackendCallRPCConcurrently(t *testing.T) {
|
||||
backend := NewStatusBackend()
|
||||
config := params.NodeConfig{}
|
||||
|
@ -245,6 +257,38 @@ func TestBackendCallRPCConcurrently(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestAppStateChange(t *testing.T) {
|
||||
backend := NewStatusBackend()
|
||||
|
||||
var testCases = []struct {
|
||||
name string
|
||||
fromState appState
|
||||
toState appState
|
||||
expectedState appState
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
fromState: appStateInactive,
|
||||
toState: appStateBackground,
|
||||
expectedState: appStateBackground,
|
||||
},
|
||||
{
|
||||
name: "invalid state",
|
||||
fromState: appStateInactive,
|
||||
toState: "unexisting",
|
||||
expectedState: appStateInactive,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
backend.appState = tc.fromState
|
||||
backend.AppStateChange(tc.toState.String())
|
||||
assert.Equal(t, tc.expectedState.String(), backend.appState.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareTxArgs(t *testing.T) {
|
||||
var flagtests = []struct {
|
||||
description string
|
||||
|
|
|
@ -4,60 +4,61 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// ConnectionState represents device connection state and type,
|
||||
// connectionState represents device connection state and type,
|
||||
// as reported by mobile framework.
|
||||
//
|
||||
// Zero value represents default assumption about network (online and unknown type).
|
||||
type ConnectionState struct {
|
||||
type connectionState struct {
|
||||
Offline bool `json:"offline"`
|
||||
Type ConnectionType `json:"type"`
|
||||
Type connectionType `json:"type"`
|
||||
Expensive bool `json:"expensive"`
|
||||
}
|
||||
|
||||
// ConnectionType represents description of available
|
||||
// connectionType represents description of available
|
||||
// connection types as reported by React Native (see
|
||||
// https://facebook.github.io/react-native/docs/netinfo.html)
|
||||
// We're interested mainly in 'wifi' and 'cellular', but
|
||||
// other types are also may be used.
|
||||
type ConnectionType byte
|
||||
type connectionType byte
|
||||
|
||||
const (
|
||||
offline = "offline"
|
||||
wifi = "wifi"
|
||||
cellular = "cellular"
|
||||
unknown = "unknown"
|
||||
none = "none"
|
||||
)
|
||||
|
||||
// NewConnectionType creates new ConnectionType from string.
|
||||
func NewConnectionType(s string) ConnectionType {
|
||||
// newConnectionType creates new connectionType from string.
|
||||
func newConnectionType(s string) connectionType {
|
||||
switch s {
|
||||
case cellular:
|
||||
return ConnectionCellular
|
||||
return connectionCellular
|
||||
case wifi:
|
||||
return ConnectionWifi
|
||||
return connectionWifi
|
||||
}
|
||||
|
||||
return ConnectionUnknown
|
||||
return connectionUnknown
|
||||
}
|
||||
|
||||
// ConnectionType constants
|
||||
const (
|
||||
ConnectionUnknown ConnectionType = iota
|
||||
ConnectionCellular // cellular, LTE, 4G, 3G, EDGE, etc.
|
||||
ConnectionWifi // WIFI or iOS simulator
|
||||
connectionUnknown connectionType = iota
|
||||
connectionCellular // cellular, LTE, 4G, 3G, EDGE, etc.
|
||||
connectionWifi // WIFI or iOS simulator
|
||||
)
|
||||
|
||||
// String formats ConnectionState for logs. Implements Stringer.
|
||||
func (c ConnectionState) String() string {
|
||||
// string formats ConnectionState for logs. Implements Stringer.
|
||||
func (c connectionState) String() string {
|
||||
if c.Offline {
|
||||
return offline
|
||||
}
|
||||
|
||||
var typ string
|
||||
switch c.Type {
|
||||
case ConnectionWifi:
|
||||
case connectionWifi:
|
||||
typ = wifi
|
||||
case ConnectionCellular:
|
||||
case connectionCellular:
|
||||
typ = cellular
|
||||
default:
|
||||
typ = unknown
|
||||
|
|
|
@ -3,16 +3,16 @@ package api
|
|||
import "testing"
|
||||
|
||||
func TestConnectionType(t *testing.T) {
|
||||
c := NewConnectionType("wifi")
|
||||
if c != ConnectionWifi {
|
||||
c := newConnectionType("wifi")
|
||||
if c != connectionWifi {
|
||||
t.Fatalf("Wrong connection type: %v", c)
|
||||
}
|
||||
c = NewConnectionType("cellular")
|
||||
if c != ConnectionCellular {
|
||||
c = newConnectionType("cellular")
|
||||
if c != connectionCellular {
|
||||
t.Fatalf("Wrong connection type: %v", c)
|
||||
}
|
||||
c = NewConnectionType("bluetooth")
|
||||
if c != ConnectionUnknown {
|
||||
c = newConnectionType("bluetooth")
|
||||
if c != connectionUnknown {
|
||||
t.Fatalf("Wrong connection type: %v", c)
|
||||
}
|
||||
}
|
||||
|
@ -20,34 +20,39 @@ func TestConnectionType(t *testing.T) {
|
|||
func TestConnectionState(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
state ConnectionState
|
||||
state connectionState
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
"zero value",
|
||||
ConnectionState{},
|
||||
connectionState{},
|
||||
"unknown",
|
||||
},
|
||||
{
|
||||
"offline",
|
||||
ConnectionState{Offline: true},
|
||||
connectionState{Offline: true},
|
||||
"offline",
|
||||
},
|
||||
{
|
||||
"wifi",
|
||||
ConnectionState{Type: ConnectionWifi},
|
||||
connectionState{Type: connectionWifi},
|
||||
"wifi",
|
||||
},
|
||||
{
|
||||
"wifi tethered",
|
||||
ConnectionState{Type: ConnectionWifi, Expensive: true},
|
||||
connectionState{Type: connectionWifi, Expensive: true},
|
||||
"wifi (expensive)",
|
||||
},
|
||||
{
|
||||
"unknown",
|
||||
ConnectionState{Type: ConnectionUnknown},
|
||||
connectionState{Type: connectionUnknown},
|
||||
"unknown",
|
||||
},
|
||||
{
|
||||
"cellular",
|
||||
connectionState{Type: connectionCellular},
|
||||
"cellular",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package api
|
||||
|
||||
// RunAsync runs the specified function asynchronously.
|
||||
func RunAsync(f func() error) <-chan error {
|
||||
resp := make(chan error, 1)
|
||||
go func() {
|
||||
|
|
Loading…
Reference in New Issue