status-go/params/config_test.go
Godfrain Jacques 4584de34b0
fix(settings): It's not possible to switch the log level (#4667)
Closes #13139

Previously it was not possible to change the state of the Debug toggle.
This is because the code forced the setting the default value, ignoring
the database setup, hence always setting the DEBUG as LogLevel.

This PR adds :

- A RuntimeLogLevel to enable setting ephemeral loggig strategy on status-go
2024-02-02 13:08:48 -08:00

356 lines
10 KiB
Go

package params_test
import (
"fmt"
"io/ioutil"
"path"
"path/filepath"
"testing"
validator "gopkg.in/go-playground/validator.v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/t/utils"
)
func TestNewNodeConfigWithDefaults(t *testing.T) {
c, err := params.NewNodeConfigWithDefaults(
"/some/data/path",
params.GoerliNetworkID,
params.WithFleet(params.FleetProd),
params.WithLES(),
params.WithMailserver(),
)
require.NoError(t, err)
assert.Equal(t, "/some/data/path", c.DataDir)
assert.Equal(t, "/some/data/path/keystore", c.KeyStoreDir)
// assert Whisper
assert.Equal(t, true, c.WakuConfig.Enabled)
assert.Equal(t, "/some/data/path/waku", c.WakuConfig.DataDir)
// assert MailServer
assert.Equal(t, false, c.WakuConfig.EnableMailServer)
// assert cluster
assert.Equal(t, false, c.NoDiscovery)
assert.Equal(t, params.FleetProd, c.ClusterConfig.Fleet)
assert.NotEmpty(t, c.ClusterConfig.BootNodes)
assert.NotEmpty(t, c.ClusterConfig.StaticNodes)
assert.NotEmpty(t, c.ClusterConfig.PushNotificationsServers)
// assert LES
assert.Equal(t, true, c.LightEthConfig.Enabled)
// assert other
assert.Equal(t, false, c.HTTPEnabled)
assert.Equal(t, false, c.IPCEnabled)
assert.Equal(t, "", c.RuntimeLogLevel)
assert.Equal(t, "/some/data/path/archivedata", c.TorrentConfig.DataDir)
assert.Equal(t, "/some/data/path/torrents", c.TorrentConfig.TorrentDir)
assert.Equal(t, 9025, c.TorrentConfig.Port)
assert.Equal(t, false, c.TorrentConfig.Enabled)
assert.NoError(t, c.UpdateWithDefaults())
assert.NotEmpty(t, c.ShhextConfig.DefaultPushNotificationsServers)
}
func TestNewConfigFromJSON(t *testing.T) {
tmpDir := t.TempDir()
json := `{
"NetworkId": 3,
"DataDir": "` + tmpDir + `",
"KeyStoreDir": "` + tmpDir + `",
"KeycardPairingDataFile": "` + path.Join(tmpDir, "keycard/pairings.json") + `",
"NoDiscovery": true,
"TorrentConfig": {
"Port": 9025,
"Enabled": false,
"DataDir": "` + tmpDir + `/archivedata",
"TorrentDir": "` + tmpDir + `/torrents"
},
"RuntimeLogLevel": "DEBUG"
}`
c, err := params.NewConfigFromJSON(json)
require.NoError(t, err)
require.Equal(t, uint64(3), c.NetworkID)
require.Equal(t, tmpDir, c.DataDir)
require.Equal(t, tmpDir, c.KeyStoreDir)
require.Equal(t, false, c.TorrentConfig.Enabled)
require.Equal(t, 9025, c.TorrentConfig.Port)
require.Equal(t, tmpDir+"/archivedata", c.TorrentConfig.DataDir)
require.Equal(t, tmpDir+"/torrents", c.TorrentConfig.TorrentDir)
require.Equal(t, "DEBUG", c.RuntimeLogLevel)
}
func TestConfigWriteRead(t *testing.T) {
tmpDir := t.TempDir()
nodeConfig, err := utils.MakeTestNodeConfigWithDataDir("", tmpDir, params.GoerliNetworkID)
require.Nil(t, err, "cannot create new config object")
err = nodeConfig.Save()
require.Nil(t, err, "cannot persist configuration")
loadedConfigData, err := ioutil.ReadFile(filepath.Join(nodeConfig.DataDir, "config.json"))
require.Nil(t, err, "cannot read configuration from disk")
loadedConfig := string(loadedConfigData)
require.Contains(t, loadedConfig, fmt.Sprintf(`"NetworkId": %d`, params.GoerliNetworkID))
require.Contains(t, loadedConfig, fmt.Sprintf(`"DataDir": "%s"`, tmpDir))
require.Contains(t, loadedConfig, fmt.Sprintf(`"BackupDisabledDataDir": "%s"`, tmpDir))
}
// TestNodeConfigValidate checks validation of individual fields.
func TestNodeConfigValidate(t *testing.T) {
testCases := []struct {
Name string
Config string
Error string
FieldErrors map[string]string // map[Field]Tag
CheckFunc func(*testing.T, *params.NodeConfig)
}{
{
Name: "Valid JSON config",
Config: `{
"NetworkId": 1,
"DataDir": "/tmp/data",
"BackupDisabledDataDir": "/tmp/data",
"KeyStoreDir": "/tmp/data",
"KeycardPairingDataFile": "/tmp/data/keycard/pairings.json",
"NoDiscovery": true
}`,
},
{
Name: "Invalid JSON config",
Config: `{"NetworkId": }`,
Error: "invalid character '}'",
},
{
Name: "Invalid field type",
Config: `{"NetworkId": "abc"}`,
Error: "json: cannot unmarshal string into Go struct field",
},
{
Name: "Validate all required fields",
Config: `{}`,
FieldErrors: map[string]string{
"NetworkID": "required",
"DataDir": "required",
"KeyStoreDir": "required",
"KeycardPairingDataFile": "required",
},
},
{
Name: "Validate that Name does not contain slash",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"Name": "invalid/name"
}`,
FieldErrors: map[string]string{
"Name": "excludes",
},
},
{
Name: "Validate that NodeKey is checked for validity",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"NodeKey": "foo"
}`,
Error: "NodeKey is invalid",
},
{
Name: "Validate that UpstreamConfig.URL is validated if UpstreamConfig is enabled",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"UpstreamConfig": {
"Enabled": true,
"URL": "[bad.url]"
}
}`,
Error: "'[bad.url]' is invalid",
},
{
Name: "Validate that UpstreamConfig.URL is not validated if UpstreamConfig is disabled",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"UpstreamConfig": {
"Enabled": false,
"URL": "[bad.url]"
}
}`,
},
{
Name: "Validate that UpstreamConfig.URL validation passes if UpstreamConfig.URL is valid",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"UpstreamConfig": {
"Enabled": true,
"URL": "` + params.MainnetEthereumNetworkURL + `"
}
}`,
},
{
Name: "Validate that ClusterConfig.BootNodes is verified to not be empty if discovery is disabled",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": false
}`,
Error: "NoDiscovery is false, but ClusterConfig.BootNodes is empty",
},
{
Name: "Validate that ClusterConfig.RendezvousNodes is verified to be empty if Rendezvous is disabled",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"Rendezvous": true
}`,
Error: "Rendezvous is enabled, but ClusterConfig.RendezvousNodes is empty",
},
{
Name: "Validate that PFSEnabled & InstallationID are checked for validity",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"NoDiscovery": true,
"WakuConfig": {
"Enabled": true,
"DataDir": "/foo"
},
"ShhextConfig": {
"BackupDisabledDataDir": "/some/dir",
"PFSEnabled": true
}
}`,
Error: "PFSEnabled is true, but InstallationID is empty",
},
{
Name: "Default HTTP virtual hosts is localhost and CORS is empty",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json"
}`,
CheckFunc: func(t *testing.T, config *params.NodeConfig) {
require.Equal(t, []string{"localhost"}, config.HTTPVirtualHosts)
require.Nil(t, config.HTTPCors)
},
},
{
Name: "Set HTTP virtual hosts and CORS",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"HTTPVirtualHosts": ["my.domain.com"],
"HTTPCors": ["http://my.domain.com:8080"]
}`,
CheckFunc: func(t *testing.T, config *params.NodeConfig) {
require.Equal(t, []string{"my.domain.com"}, config.HTTPVirtualHosts)
require.Equal(t, []string{"http://my.domain.com:8080"}, config.HTTPCors)
},
},
{
Name: "ShhextConfig is not required",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json"
}`,
},
{
Name: "BackupDisabledDataDir must be set if PFSEnabled is true",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"ShhextConfig": {
"PFSEnabled": true
}
}`,
Error: "field BackupDisabledDataDir is required if PFSEnabled is true",
},
{
Name: "Missing APIModules",
Config: `{"NetworkId": 1, "DataDir": "/tmp/data", "KeyStoreDir": "/tmp/data", "KeycardPairingDataFile": "/tmp/data/keycard/pairings.json", "APIModules" :""}`,
FieldErrors: map[string]string{
"APIModules": "required",
},
},
{
Name: "Validate that TorrentConfig.DataDir and TorrentConfig.TorrentDir can't be empty strings",
Config: `{
"NetworkId": 1,
"DataDir": "/some/dir",
"KeyStoreDir": "/some/dir",
"KeycardPairingDataFile": "/some/dir/keycard/pairings.json",
"TorrentConfig": {
"Enabled": true,
"Port": 9025,
"DataDir": "",
"TorrentDir": ""
}
}`,
Error: `TorrentConfig.DataDir and TorrentConfig.TorrentDir cannot be ""`,
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
config, err := params.NewConfigFromJSON(tc.Config)
switch err := err.(type) {
case validator.ValidationErrors:
for _, ve := range err {
require.Contains(t, tc.FieldErrors, ve.Field())
require.Equal(t, tc.FieldErrors[ve.Field()], ve.Tag())
}
case error:
if tc.Error == "" {
require.NoError(t, err)
} else {
fmt.Println(tc.Error)
require.Contains(t, err.Error(), tc.Error)
}
case nil:
if tc.Error != "" {
require.Error(t, err, "Error should be '%v'", tc.Error)
}
require.Nil(t, tc.FieldErrors)
if tc.CheckFunc != nil {
tc.CheckFunc(t, config)
}
}
})
}
}