diff --git a/dot/build_spec_integration_test.go b/dot/build_spec_integration_test.go
new file mode 100644
index 0000000000..3eeb948c4d
--- /dev/null
+++ b/dot/build_spec_integration_test.go
@@ -0,0 +1,157 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "testing"
+
+ "github.com/ChainSafe/gossamer/lib/genesis"
+ "github.com/stretchr/testify/require"
+)
+
+const genesisLocation = "../chain/gssmr/genesis.json"
+
+func TestBuildFromGenesis_Integration(t *testing.T) {
+ file, err := genesis.CreateTestGenesisJSONFile(false)
+ defer os.Remove(file)
+ require.NoError(t, err)
+ bs, err := BuildFromGenesis(file, 0)
+
+ expectedChainType := "TESTCHAINTYPE"
+ expectedProperties := map[string]interface{}{
+ "ss58Format": 0.0,
+ "tokenDecimals": 0.0,
+ "tokenSymbol": "TEST",
+ }
+
+ bs.genesis.ChainType = expectedChainType
+ bs.genesis.Properties = expectedProperties
+
+ require.NoError(t, err)
+
+ // confirm human-readable fields
+ hr, err := bs.ToJSON()
+ require.NoError(t, err)
+ jGen := genesis.Genesis{}
+ err = json.Unmarshal(hr, &jGen)
+ require.NoError(t, err)
+ genesis.TestGenesis.Genesis = genesis.TestFieldsHR
+ require.Equal(t, genesis.TestGenesis.Genesis.Runtime, jGen.Genesis.Runtime)
+ require.Equal(t, expectedChainType, jGen.ChainType)
+ require.Equal(t, expectedProperties, jGen.Properties)
+
+ // confirm raw fields
+ raw, err := bs.ToJSONRaw()
+ require.NoError(t, err)
+ jGenRaw := genesis.Genesis{}
+ err = json.Unmarshal(raw, &jGenRaw)
+ require.NoError(t, err)
+ genesis.TestGenesis.Genesis = genesis.TestFieldsRaw
+ require.Equal(t, genesis.TestGenesis.Genesis.Raw, jGenRaw.Genesis.Raw)
+ require.Equal(t, expectedChainType, jGenRaw.ChainType)
+ require.Equal(t, expectedProperties, jGenRaw.Properties)
+}
+
+func TestBuildFromGenesis_WhenGenesisDoesNotExists(t *testing.T) {
+ bs, err := BuildFromGenesis("/not/exists/genesis.json", 0)
+ require.Nil(t, bs)
+ require.Error(t, err, os.ErrNotExist)
+}
+
+func TestWriteGenesisSpecFileWhenFileAlreadyExists(t *testing.T) {
+ f, err := ioutil.TempFile("", "existing file data")
+ require.NoError(t, err)
+ defer os.Remove(f.Name())
+
+ someBytes := []byte("Testing some bytes")
+ err = WriteGenesisSpecFile(someBytes, f.Name())
+
+ require.Error(t, err,
+ fmt.Sprintf("file %s already exists, rename to avoid overwritten", f.Name()))
+}
+
+func TestWriteGenesisSpecFile_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ cfg.Init.Genesis = genesisLocation
+
+ expected, err := genesis.NewGenesisFromJSONRaw(cfg.Init.Genesis)
+ require.NoError(t, err)
+
+ err = InitNode(cfg)
+ require.NoError(t, err)
+
+ bs, err := BuildFromGenesis(cfg.Init.Genesis, 0)
+ require.NoError(t, err)
+
+ data, err := bs.ToJSONRaw()
+ require.NoError(t, err)
+
+ tmpFiles := []string{
+ "/tmp/unique-raw-genesis.json",
+ "./unique-raw-genesis.json",
+ }
+
+ for _, tmpFile := range tmpFiles {
+ err = WriteGenesisSpecFile(data, tmpFile)
+ require.NoError(t, err)
+ require.FileExists(t, tmpFile)
+
+ defer os.Remove(tmpFile)
+
+ file, err := os.Open(tmpFile)
+ require.NoError(t, err)
+ defer file.Close()
+
+ genesisBytes, err := ioutil.ReadAll(file)
+ require.NoError(t, err)
+
+ gen := new(genesis.Genesis)
+ err = json.Unmarshal(genesisBytes, gen)
+ require.NoError(t, err)
+
+ require.Equal(t, expected.ChainType, gen.ChainType)
+ require.Equal(t, expected.Properties, gen.Properties)
+ }
+}
+
+func TestBuildFromDB_Integration(t *testing.T) {
+ // setup expected
+ cfg := NewTestConfig(t)
+ cfg.Init.Genesis = genesisLocation
+ expected, err := genesis.NewGenesisFromJSONRaw(cfg.Init.Genesis)
+ require.NoError(t, err)
+ // initialise node (initialise state database and load genesis data)
+ err = InitNode(cfg)
+ require.NoError(t, err)
+
+ bs, err := BuildFromDB(cfg.Global.BasePath)
+ require.NoError(t, err)
+ res, err := bs.ToJSON()
+ require.NoError(t, err)
+ jGen := genesis.Genesis{}
+ err = json.Unmarshal(res, &jGen)
+ require.NoError(t, err)
+
+ require.Equal(t, expected.Genesis.Raw["top"]["0x3a636f6465"], jGen.Genesis.Runtime["system"]["code"])
+}
diff --git a/dot/build_spec_test.go b/dot/build_spec_test.go
index b00683ccea..2dbedd5a2f 100644
--- a/dot/build_spec_test.go
+++ b/dot/build_spec_test.go
@@ -4,136 +4,345 @@
package dot
import (
- "encoding/json"
- "fmt"
- "io"
+ "errors"
"os"
"testing"
"github.com/ChainSafe/gossamer/lib/genesis"
- "github.com/stretchr/testify/require"
+ "github.com/stretchr/testify/assert"
)
-func TestBuildFromGenesis(t *testing.T) {
- file, err := genesis.CreateTestGenesisJSONFile(false)
- defer os.Remove(file)
- require.NoError(t, err)
- bs, err := BuildFromGenesis(file, 0)
-
- expectedChainType := "TESTCHAINTYPE"
- expectedProperties := map[string]interface{}{
- "ss58Format": 0.0,
- "tokenDecimals": 0.0,
- "tokenSymbol": "TEST",
+func TestBuildSpec_ToJSON(t *testing.T) {
+ type fields struct {
+ genesis *genesis.Genesis
}
-
- bs.genesis.ChainType = expectedChainType
- bs.genesis.Properties = expectedProperties
-
- require.NoError(t, err)
-
- // confirm human-readable fields
- hr, err := bs.ToJSON()
- require.NoError(t, err)
- jGen := genesis.Genesis{}
- err = json.Unmarshal(hr, &jGen)
- require.NoError(t, err)
- genesis.TestGenesis.Genesis = genesis.TestFieldsHR
- require.Equal(t, genesis.TestGenesis.Genesis.Runtime, jGen.Genesis.Runtime)
- require.Equal(t, expectedChainType, jGen.ChainType)
- require.Equal(t, expectedProperties, jGen.Properties)
-
- // confirm raw fields
- raw, err := bs.ToJSONRaw()
- require.NoError(t, err)
- jGenRaw := genesis.Genesis{}
- err = json.Unmarshal(raw, &jGenRaw)
- require.NoError(t, err)
- genesis.TestGenesis.Genesis = genesis.TestFieldsRaw
- require.Equal(t, genesis.TestGenesis.Genesis.Raw, jGenRaw.Genesis.Raw)
- require.Equal(t, expectedChainType, jGenRaw.ChainType)
- require.Equal(t, expectedProperties, jGenRaw.Properties)
-}
-
-func TestBuildFromGenesis_WhenGenesisDoesNotExists(t *testing.T) {
- bs, err := BuildFromGenesis("/not/exists/genesis.json", 0)
- require.Nil(t, bs)
- require.Error(t, err, os.ErrNotExist)
-}
-
-func TestWriteGenesisSpecFileWhenFileAlreadyExists(t *testing.T) {
- f, err := os.CreateTemp("", "existing file data")
- require.NoError(t, err)
- defer os.Remove(f.Name())
-
- someBytes := []byte("Testing some bytes")
- err = WriteGenesisSpecFile(someBytes, f.Name())
-
- require.Error(t, err,
- fmt.Sprintf("file %s already exists, rename to avoid overwritten", f.Name()))
+ tests := []struct {
+ name string
+ fields fields
+ want []byte
+ err error
+ }{
+ {
+ name: "name test",
+ fields: fields{genesis: &genesis.Genesis{Name: "test"}},
+ want: []byte{123, 10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 101, 115, 116, 34,
+ 44, 10, 32, 32, 32, 32, 34, 105, 100, 34, 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 99, 104, 97,
+ 105, 110, 84, 121, 112, 101, 34, 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 98, 111, 111, 116, 78,
+ 111, 100, 101, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32, 34, 116, 101, 108, 101,
+ 109, 101, 116, 114, 121, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 58, 32, 110, 117, 108, 108,
+ 44, 10, 32, 32, 32, 32, 34, 112, 114, 111, 116, 111, 99, 111, 108, 73, 100, 34, 58, 32, 34, 34, 44,
+ 10, 32, 32, 32, 32, 34, 103, 101, 110, 101, 115, 105, 115, 34, 58, 32, 123, 125, 44, 10, 32, 32, 32,
+ 32, 34, 112, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32,
+ 32, 32, 32, 34, 102, 111, 114, 107, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44,
+ 10, 32, 32, 32, 32, 34, 98, 97, 100, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44,
+ 10, 32, 32, 32, 32, 34, 99, 111, 110, 115, 101, 110, 115, 117, 115, 69, 110, 103, 105, 110, 101, 34,
+ 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 99, 111, 100, 101, 83, 117, 98, 115, 116, 105, 116, 117,
+ 116, 101, 115, 34, 58, 32, 110, 117, 108, 108, 10, 125},
+ },
+ {
+ name: "additional parameters test",
+ fields: fields{genesis: &genesis.Genesis{
+ Name: "test",
+ ID: "ID",
+ ChainType: "chainType",
+ ProtocolID: "protocol",
+ ConsensusEngine: "babe",
+ }},
+ want: []byte{123, 10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 101, 115, 116, 34, 44,
+ 10, 32, 32, 32, 32, 34, 105, 100, 34, 58, 32, 34, 73, 68, 34, 44, 10, 32, 32, 32, 32, 34, 99, 104,
+ 97, 105, 110, 84, 121, 112, 101, 34, 58, 32, 34, 99, 104, 97, 105, 110, 84, 121, 112, 101, 34, 44,
+ 10, 32, 32, 32, 32, 34, 98, 111, 111, 116, 78, 111, 100, 101, 115, 34, 58, 32, 110, 117, 108, 108,
+ 44, 10, 32, 32, 32, 32, 34, 116, 101, 108, 101, 109, 101, 116, 114, 121, 69, 110, 100, 112, 111, 105,
+ 110, 116, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32, 34, 112, 114, 111, 116, 111,
+ 99, 111, 108, 73, 100, 34, 58, 32, 34, 112, 114, 111, 116, 111, 99, 111, 108, 34, 44, 10, 32, 32, 32,
+ 32, 34, 103, 101, 110, 101, 115, 105, 115, 34, 58, 32, 123, 125, 44, 10, 32, 32, 32, 32, 34, 112,
+ 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32,
+ 34, 102, 111, 114, 107, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32,
+ 32, 32, 34, 98, 97, 100, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32,
+ 32, 32, 34, 99, 111, 110, 115, 101, 110, 115, 117, 115, 69, 110, 103, 105, 110, 101, 34, 58, 32, 34,
+ 34, 44, 10, 32, 32, 32, 32, 34, 99, 111, 100, 101, 83, 117, 98, 115, 116, 105, 116, 117, 116, 101,
+ 115, 34, 58, 32, 110, 117, 108, 108, 10, 125},
+ },
+ {
+ name: "normal conditions",
+ fields: fields{genesis: &genesis.Genesis{
+ Name: "test",
+ ID: "ID",
+ ChainType: "chainType",
+ Bootnodes: []string{"node1", "node2"},
+ TelemetryEndpoints: []interface{}{"endpoint"},
+ ProtocolID: "protocol",
+ Genesis: genesis.Fields{},
+ Properties: map[string]interface{}{"key": "value"},
+ ForkBlocks: []string{"1", "2"},
+ BadBlocks: []string{"3", "4"},
+ ConsensusEngine: "babe",
+ CodeSubstitutes: map[string]string{"key": "value"},
+ }},
+ want: []byte{123, 10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 101, 115, 116, 34, 44,
+ 10, 32, 32, 32, 32, 34, 105, 100, 34, 58, 32, 34, 73, 68, 34, 44, 10, 32, 32, 32, 32, 34, 99, 104,
+ 97, 105, 110, 84, 121, 112, 101, 34, 58, 32, 34, 99, 104, 97, 105, 110, 84, 121, 112, 101, 34, 44,
+ 10, 32, 32, 32, 32, 34, 98, 111, 111, 116, 78, 111, 100, 101, 115, 34, 58, 32, 91, 10, 32, 32, 32,
+ 32, 32, 32, 32, 32, 34, 110, 111, 100, 101, 49, 34, 44, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 110,
+ 111, 100, 101, 50, 34, 10, 32, 32, 32, 32, 93, 44, 10, 32, 32, 32, 32, 34, 116, 101, 108, 101, 109,
+ 101, 116, 114, 121, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 58, 32, 110, 117, 108, 108, 44,
+ 10, 32, 32, 32, 32, 34, 112, 114, 111, 116, 111, 99, 111, 108, 73, 100, 34, 58, 32, 34, 112, 114,
+ 111, 116, 111, 99, 111, 108, 34, 44, 10, 32, 32, 32, 32, 34, 103, 101, 110, 101, 115, 105, 115, 34,
+ 58, 32, 123, 125, 44, 10, 32, 32, 32, 32, 34, 112, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34,
+ 58, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 34, 107, 101, 121, 34, 58, 32, 34, 118, 97, 108,
+ 117, 101, 34, 10, 32, 32, 32, 32, 125, 44, 10, 32, 32, 32, 32, 34, 102, 111, 114, 107, 66, 108, 111,
+ 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32, 34, 98, 97, 100, 66, 108, 111,
+ 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32, 34, 99, 111, 110, 115, 101,
+ 110, 115, 117, 115, 69, 110, 103, 105, 110, 101, 34, 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 99,
+ 111, 100, 101, 83, 117, 98, 115, 116, 105, 116, 117, 116, 101, 115, 34, 58, 32, 110, 117, 108, 108,
+ 10, 125},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ b := &BuildSpec{
+ genesis: tt.fields.genesis,
+ }
+ got, err := b.ToJSON()
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ assert.Equal(t, tt.want, got)
+ })
+ }
+ //<<<<<<< HEAD
+ //=======
+ //
+ // bs.genesis.ChainType = expectedChainType
+ // bs.genesis.Properties = expectedProperties
+ //
+ // require.NoError(t, err)
+ //
+ // // confirm human-readable fields
+ // hr, err := bs.ToJSON()
+ // require.NoError(t, err)
+ // jGen := genesis.Genesis{}
+ // err = json.Unmarshal(hr, &jGen)
+ // require.NoError(t, err)
+ // genesis.TestGenesis.Genesis = genesis.TestFieldsHR
+ // require.Equal(t, genesis.TestGenesis.Genesis.Runtime, jGen.Genesis.Runtime)
+ // require.Equal(t, expectedChainType, jGen.ChainType)
+ // require.Equal(t, expectedProperties, jGen.Properties)
+ //
+ // // confirm raw fields
+ // raw, err := bs.ToJSONRaw()
+ // require.NoError(t, err)
+ // jGenRaw := genesis.Genesis{}
+ // err = json.Unmarshal(raw, &jGenRaw)
+ // require.NoError(t, err)
+ // genesis.TestGenesis.Genesis = genesis.TestFieldsRaw
+ // require.Equal(t, genesis.TestGenesis.Genesis.Raw, jGenRaw.Genesis.Raw)
+ // require.Equal(t, expectedChainType, jGenRaw.ChainType)
+ // require.Equal(t, expectedProperties, jGenRaw.Properties)
+ //}
+ //
+ //func TestBuildFromGenesis_WhenGenesisDoesNotExists(t *testing.T) {
+ // bs, err := BuildFromGenesis("/not/exists/genesis.json", 0)
+ // require.Nil(t, bs)
+ // require.Error(t, err, os.ErrNotExist)
+ //}
+ //
+ //func TestWriteGenesisSpecFileWhenFileAlreadyExists(t *testing.T) {
+ // f, err := os.CreateTemp("", "existing file data")
+ // require.NoError(t, err)
+ // defer os.Remove(f.Name())
+ //
+ // someBytes := []byte("Testing some bytes")
+ // err = WriteGenesisSpecFile(someBytes, f.Name())
+ //
+ // require.Error(t, err,
+ // fmt.Sprintf("file %s already exists, rename to avoid overwritten", f.Name()))
+ //>>>>>>> development
}
-func TestWriteGenesisSpecFile(t *testing.T) {
+func TestBuildFromDB(t *testing.T) {
+ // initialise node (initialise state database and load genesis data)
cfg := NewTestConfig(t)
cfg.Init.Genesis = "../chain/gssmr/genesis.json"
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
+ assert.NoError(t, err)
- expected, err := genesis.NewGenesisFromJSONRaw(cfg.Init.Genesis)
- require.NoError(t, err)
-
- err = InitNode(cfg)
- require.NoError(t, err)
-
- bs, err := BuildFromGenesis(cfg.Init.Genesis, 0)
- require.NoError(t, err)
-
- data, err := bs.ToJSONRaw()
- require.NoError(t, err)
-
- tmpFiles := []string{
- "/tmp/unique-raw-genesis.json",
- "./unique-raw-genesis.json",
+ type args struct {
+ path string
}
+ tests := []struct {
+ name string
+ args args
+ want *BuildSpec
+ err error
+ }{
+ {name: "normal conditions", args: args{path: "test_data/TestBuildFromDB"},
+ want: &BuildSpec{genesis: &genesis.Genesis{Name: "Gossamer"}}},
+ {name: "invalid db path", args: args{path: "foo/bar"},
+ err: errors.New("failed to create block state: cannot get block 0: Key not found")},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := BuildFromDB(tt.args.path)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ if tt.want != nil {
+ assert.Equal(t, tt.want.genesis.Name, got.genesis.Name)
+ }
+ // remove files created for tests
+ err = os.RemoveAll(tt.args.path)
+ assert.NoError(t, err)
+ })
+ }
+}
- for _, tmpFile := range tmpFiles {
- err = WriteGenesisSpecFile(data, tmpFile)
- require.NoError(t, err)
- require.FileExists(t, tmpFile)
-
- defer os.Remove(tmpFile)
-
- file, err := os.Open(tmpFile)
- require.NoError(t, err)
- defer file.Close()
-
- genesisBytes, err := io.ReadAll(file)
- require.NoError(t, err)
-
- gen := new(genesis.Genesis)
- err = json.Unmarshal(genesisBytes, gen)
- require.NoError(t, err)
+func TestBuildFromGenesis(t *testing.T) {
+ // setup test file
+ file, err := genesis.CreateTestGenesisJSONFile(false)
+ assert.NoError(t, err)
+ defer os.Remove(file)
+ //=======
+ // for _, tmpFile := range tmpFiles {
+ // err = WriteGenesisSpecFile(data, tmpFile)
+ // require.NoError(t, err)
+ // require.FileExists(t, tmpFile)
+ //
+ // defer os.Remove(tmpFile)
+ //
+ // file, err := os.Open(tmpFile)
+ // require.NoError(t, err)
+ // defer file.Close()
+ //
+ // genesisBytes, err := io.ReadAll(file)
+ // require.NoError(t, err)
+ //
+ // gen := new(genesis.Genesis)
+ // err = json.Unmarshal(genesisBytes, gen)
+ // require.NoError(t, err)
+ //>>>>>>> development
- require.Equal(t, expected.ChainType, gen.ChainType)
- require.Equal(t, expected.Properties, gen.Properties)
+ type args struct {
+ path string
+ authCount int
+ }
+ tests := []struct {
+ name string
+ args args
+ want *BuildSpec
+ err error
+ }{
+ {
+ name: "invalid file path",
+ args: args{
+ path: "/invalid/path",
+ },
+ err: errors.New("open /invalid/path: no such file or directory"),
+ },
+ {
+ name: "normal conditions",
+ args: args{
+ path: file,
+ },
+ want: &BuildSpec{genesis: &genesis.Genesis{Name: "test"}},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := BuildFromGenesis(tt.args.path, tt.args.authCount)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ if tt.want != nil {
+ assert.Equal(t, tt.want.genesis.Name, got.genesis.Name)
+ }
+ })
}
}
-func TestBuildFromDB(t *testing.T) {
- // setup expected
- cfg := NewTestConfig(t)
- cfg.Init.Genesis = "../chain/gssmr/genesis.json"
- expected, err := genesis.NewGenesisFromJSONRaw(cfg.Init.Genesis)
- require.NoError(t, err)
- // initialise node (initialise state database and load genesis data)
- err = InitNode(cfg)
- require.NoError(t, err)
+func TestBuildSpec_ToJSONRaw(t *testing.T) {
+ type fields struct {
+ genesis *genesis.Genesis
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want []byte
+ err error
+ }{
+ {
+ name: "normal conditions",
+ fields: fields{genesis: &genesis.Genesis{Name: "test"}},
+ want: []byte{123, 10, 32, 32, 32, 32, 34, 110, 97, 109, 101, 34, 58, 32, 34, 116, 101, 115, 116, 34,
+ 44, 10, 32, 32, 32, 32, 34, 105, 100, 34, 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 99, 104, 97,
+ 105, 110, 84, 121, 112, 101, 34, 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 98, 111, 111, 116, 78,
+ 111, 100, 101, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32, 32, 32, 32, 34, 116, 101, 108, 101,
+ 109, 101, 116, 114, 121, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 58, 32, 110, 117, 108, 108,
+ 44, 10, 32, 32, 32, 32, 34, 112, 114, 111, 116, 111, 99, 111, 108, 73, 100, 34, 58, 32, 34, 34, 44,
+ 10, 32, 32, 32, 32, 34, 103, 101, 110, 101, 115, 105, 115, 34, 58, 32, 123, 125, 44, 10, 32, 32, 32,
+ 32, 34, 112, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 58, 32, 110, 117, 108, 108, 44, 10, 32,
+ 32, 32, 32, 34, 102, 111, 114, 107, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44,
+ 10, 32, 32, 32, 32, 34, 98, 97, 100, 66, 108, 111, 99, 107, 115, 34, 58, 32, 110, 117, 108, 108, 44,
+ 10, 32, 32, 32, 32, 34, 99, 111, 110, 115, 101, 110, 115, 117, 115, 69, 110, 103, 105, 110, 101, 34,
+ 58, 32, 34, 34, 44, 10, 32, 32, 32, 32, 34, 99, 111, 100, 101, 83, 117, 98, 115, 116, 105, 116, 117,
+ 116, 101, 115, 34, 58, 32, 110, 117, 108, 108, 10, 125},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ b := &BuildSpec{
+ genesis: tt.fields.genesis,
+ }
+ got, err := b.ToJSONRaw()
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
- bs, err := BuildFromDB(cfg.Global.BasePath)
- require.NoError(t, err)
- res, err := bs.ToJSON()
- require.NoError(t, err)
- jGen := genesis.Genesis{}
- err = json.Unmarshal(res, &jGen)
- require.NoError(t, err)
+func TestWriteGenesisSpecFile(t *testing.T) {
+ file, err := os.Create("test.txt")
+ assert.NoError(t, err)
+ defer os.Remove(file.Name())
- require.Equal(t, expected.Genesis.Raw["top"]["0x3a636f6465"], jGen.Genesis.Runtime["system"]["code"])
+ type args struct {
+ data []byte
+ fp string
+ }
+ tests := []struct {
+ name string
+ args args
+ err error
+ }{
+ {name: "normal conditions", args: args{
+ data: []byte{1},
+ fp: "test.file",
+ }},
+ {name: "existing file", args: args{
+ data: []byte{1},
+ fp: file.Name(),
+ }, err: errors.New("file test.txt already exists, rename to avoid overwriting")},
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := WriteGenesisSpecFile(tt.args.data, tt.args.fp)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ os.Remove(tt.args.fp)
+ })
+ }
}
diff --git a/dot/config_integration_test.go b/dot/config_integration_test.go
new file mode 100644
index 0000000000..8beceafe9d
--- /dev/null
+++ b/dot/config_integration_test.go
@@ -0,0 +1,47 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "testing"
+
+ "github.com/ChainSafe/gossamer/lib/utils"
+
+ "github.com/stretchr/testify/require"
+)
+
+// TestExportConfig tests exporting a toml configuration file
+func TestExportConfig_Integration(t *testing.T) {
+ cfg, cfgFile := NewTestConfigWithFile(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.Nil(t, err)
+
+ file := ExportConfig(cfg, cfgFile.Name())
+ require.NotNil(t, file)
+}
diff --git a/dot/config_test.go b/dot/config_test.go
index e0631f2683..a255f1b35a 100644
--- a/dot/config_test.go
+++ b/dot/config_test.go
@@ -6,26 +6,287 @@ package dot
import (
"testing"
- "github.com/ChainSafe/gossamer/lib/utils"
-
- "github.com/stretchr/testify/require"
+ "github.com/stretchr/testify/assert"
)
-// TestExportConfig tests exporting a toml configuration file
-func TestExportConfig(t *testing.T) {
- cfg, cfgFile := NewTestConfigWithFile(t)
- require.NotNil(t, cfg)
+func TestDevConfig(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ want *Config
+ }{
+ {
+ name: "dev default",
+ want: &Config{
+ Global: GlobalConfig{
+ ID: "dev",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := DevConfig()
+ assert.Equal(t, tt.want.Global.ID, got.Global.ID)
+ })
+ }
+}
+
+func TestGssmrConfig(t *testing.T) {
+ t.Parallel()
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
+ tests := []struct {
+ name string
+ want *Config
+ }{
+ {
+ name: "gossamer default",
+ want: &Config{
+ Global: GlobalConfig{
+ ID: "gssmr",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := GssmrConfig()
+ assert.Equal(t, tt.want.Global.ID, got.Global.ID)
+ })
+ }
+}
+
+func TestKusamaConfig(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ want *Config
+ }{
+ {
+ name: "kusama default",
+ want: &Config{
+ Global: GlobalConfig{
+ ID: "ksmcc3",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := KusamaConfig()
+ assert.Equal(t, tt.want.Global.ID, got.Global.ID)
+ })
+ }
+}
- defer utils.RemoveTestDir(t)
+func TestPolkadotConfig(t *testing.T) {
+ t.Parallel()
- cfg.Init.Genesis = genFile.Name()
+ tests := []struct {
+ name string
+ want *Config
+ }{
+ {
+ name: "polkadot default",
+ want: &Config{
+ Global: GlobalConfig{
+ ID: "polkadot",
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := PolkadotConfig()
+ assert.Equal(t, tt.want.Global.ID, got.Global.ID)
+ })
+ }
+}
+
+func TestRPCConfig_isRPCEnabled(t *testing.T) {
+ t.Parallel()
+
+ type fields struct {
+ Enabled bool
+ External bool
+ Unsafe bool
+ UnsafeExternal bool
+ Port uint32
+ Host string
+ Modules []string
+ WSPort uint32
+ WS bool
+ WSExternal bool
+ WSUnsafe bool
+ WSUnsafeExternal bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want bool
+ }{
+ {
+ name: "default",
+ want: false,
+ },
+ {
+ name: "enabled true",
+ fields: fields{Enabled: true},
+ want: true,
+ },
+ {
+ name: "external true",
+ fields: fields{External: true},
+ want: true,
+ },
+ {
+ name: "unsafe true",
+ fields: fields{Unsafe: true},
+ want: true,
+ },
+ {
+ name: "unsafe external true",
+ fields: fields{UnsafeExternal: true},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := &RPCConfig{
+ Enabled: tt.fields.Enabled,
+ External: tt.fields.External,
+ Unsafe: tt.fields.Unsafe,
+ UnsafeExternal: tt.fields.UnsafeExternal,
+ Port: tt.fields.Port,
+ Host: tt.fields.Host,
+ Modules: tt.fields.Modules,
+ WSPort: tt.fields.WSPort,
+ WS: tt.fields.WS,
+ WSExternal: tt.fields.WSExternal,
+ WSUnsafe: tt.fields.WSUnsafe,
+ WSUnsafeExternal: tt.fields.WSUnsafeExternal,
+ }
+ got := r.isRPCEnabled()
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
+
+func TestRPCConfig_isWSEnabled(t *testing.T) {
+ t.Parallel()
+
+ type fields struct {
+ Enabled bool
+ External bool
+ Unsafe bool
+ UnsafeExternal bool
+ Port uint32
+ Host string
+ Modules []string
+ WSPort uint32
+ WS bool
+ WSExternal bool
+ WSUnsafe bool
+ WSUnsafeExternal bool
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want bool
+ }{
+ {
+ name: "default",
+ want: false,
+ },
+ {
+ name: "ws true",
+ fields: fields{WS: true},
+ want: true,
+ },
+ {
+ name: "ws external true",
+ fields: fields{WSExternal: true},
+ want: true,
+ },
+ {
+ name: "ws unsafe true",
+ fields: fields{WSUnsafe: true},
+ want: true,
+ },
+ {
+ name: "ws unsafe external true",
+ fields: fields{WSUnsafeExternal: true},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := &RPCConfig{
+ Enabled: tt.fields.Enabled,
+ External: tt.fields.External,
+ Unsafe: tt.fields.Unsafe,
+ UnsafeExternal: tt.fields.UnsafeExternal,
+ Port: tt.fields.Port,
+ Host: tt.fields.Host,
+ Modules: tt.fields.Modules,
+ WSPort: tt.fields.WSPort,
+ WS: tt.fields.WS,
+ WSExternal: tt.fields.WSExternal,
+ WSUnsafe: tt.fields.WSUnsafe,
+ WSUnsafeExternal: tt.fields.WSUnsafeExternal,
+ }
+ got := r.isWSEnabled()
+ assert.Equal(t, tt.want, got)
+ })
+ }
+}
- err := InitNode(cfg)
- require.Nil(t, err)
+func Test_networkServiceEnabled(t *testing.T) {
+ t.Parallel()
- file := ExportConfig(cfg, cfgFile.Name())
- require.NotNil(t, file)
+ type args struct {
+ cfg *Config
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "dev config",
+ args: args{cfg: DevConfig()},
+ want: true,
+ },
+ {
+ name: "empty config",
+ args: args{cfg: &Config{}},
+ want: false,
+ },
+ {
+ name: "core roles 0",
+ args: args{cfg: &Config{
+ Core: CoreConfig{
+ Roles: 0,
+ },
+ }},
+ want: false,
+ },
+ {
+ name: "core roles 1",
+ args: args{cfg: &Config{
+ Core: CoreConfig{
+ Roles: 1,
+ },
+ }},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := networkServiceEnabled(tt.args.cfg)
+ assert.Equal(t, tt.want, got)
+ })
+ }
}
diff --git a/dot/core/service.go b/dot/core/service.go
index 91b97aff49..b1d7088ee7 100644
--- a/dot/core/service.go
+++ b/dot/core/service.go
@@ -7,6 +7,7 @@ import (
"context"
"fmt"
"math/big"
+ "reflect"
"sync"
"github.com/ChainSafe/gossamer/dot/network"
@@ -89,7 +90,14 @@ func NewService(cfg *Config) (*Service, error) {
return nil, ErrNilStorageState
}
- if cfg.Network == nil {
+ var isNilNetwork bool
+ switch cfg.Network.(type) {
+ case Network:
+ isNilNetwork = cfg.Network == (*network.Service)(nil)
+ default:
+ isNilNetwork = reflect.ValueOf(cfg.Network).IsNil()
+ }
+ if isNilNetwork {
return nil, ErrNilNetwork
}
diff --git a/dot/import_integration_test.go b/dot/import_integration_test.go
new file mode 100644
index 0000000000..c390a8017d
--- /dev/null
+++ b/dot/import_integration_test.go
@@ -0,0 +1,93 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "io/ioutil"
+ "math/big"
+ "testing"
+
+ "github.com/ChainSafe/gossamer/dot/types"
+ "github.com/ChainSafe/gossamer/lib/common"
+ "github.com/ChainSafe/gossamer/lib/utils"
+ "github.com/ChainSafe/gossamer/pkg/scale"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewTrieFromPairs(t *testing.T) {
+ fp := setupStateFile(t)
+ tr, err := newTrieFromPairs(fp)
+ require.NoError(t, err)
+
+ expectedRoot := common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb")
+ require.Equal(t, expectedRoot, tr.MustHash())
+}
+
+func TestNewHeaderFromFile(t *testing.T) {
+ fp := setupHeaderFile(t)
+ header, err := newHeaderFromFile(fp)
+ require.NoError(t, err)
+
+ digestBytes := common.MustHexToBytes("0x080642414245b501013c0000009659bd0f0000000070edad1c9064fff78cb18435223d8" +
+ "adaf5ea04c24b1a8766e3dc01eb03cc6a0c11b79793d4e31cc0990838229c44fed1669a7c7c79e1e6d0a96374d6496728069d1ef739e2" +
+ "90497a0e3b728fa88fcbdd3a5504e0efde0242e7a806dd4fa9260c054241424501019e7f28dddcf27c1e6b328d5694c368d5b2ec5dbe0e" +
+ "412ae1c98f88d53be4d8502fac571f3f19c9caaf281a673319241e0c5095a683ad34316204088a36a4bd86")
+ digest := types.NewDigest()
+ err = scale.Unmarshal(digestBytes, &digest)
+ require.NoError(t, err)
+ require.Equal(t, 2, len(digest.Types))
+
+ expected := &types.Header{
+ ParentHash: common.MustHexToHash("0x3b45c9c22dcece75a30acc9c2968cb311e6b0557350f83b430f47559db786975"),
+ Number: big.NewInt(1482002),
+ StateRoot: common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb"),
+ ExtrinsicsRoot: common.MustHexToHash("0xda26dc8c1455f8f81cae12e4fc59e23ce961b2c837f6d3f664283af906d344e0"),
+ Digest: digest,
+ }
+
+ require.Equal(t, expected, header)
+}
+
+func TestImportState_Integration(t *testing.T) {
+ basepath, err := ioutil.TempDir("", "gossamer-test-*")
+ require.NoError(t, err)
+
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ cfg.Global.BasePath = basepath
+ err = InitNode(cfg)
+ require.NoError(t, err)
+
+ stateFP := setupStateFile(t)
+ headerFP := setupHeaderFile(t)
+
+ firstSlot := uint64(262493679)
+ err = ImportState(basepath, stateFP, headerFP, firstSlot)
+ require.NoError(t, err)
+}
diff --git a/dot/import_test.go b/dot/import_test.go
index 94448eaa17..8aa9ba295e 100644
--- a/dot/import_test.go
+++ b/dot/import_test.go
@@ -5,6 +5,8 @@ package dot
import (
"encoding/json"
+ "errors"
+ "io/ioutil"
"math/big"
"os"
"testing"
@@ -12,11 +14,157 @@ import (
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/utils"
- "github.com/ChainSafe/gossamer/pkg/scale"
-
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
+func TestImportState(t *testing.T) {
+ t.Parallel()
+
+ // setup node for test
+ basepath, err := ioutil.TempDir("", "gossamer-test-*")
+ require.NoError(t, err)
+
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ cfg.Global.BasePath = basepath
+ ni := nodeInterface{}
+ err = ni.initNode(cfg)
+ require.NoError(t, err)
+
+ stateFP := setupStateFile(t)
+ headerFP := setupHeaderFile(t)
+
+ type args struct {
+ basepath string
+ stateFP string
+ headerFP string
+ firstSlot uint64
+ }
+ tests := []struct {
+ name string
+ args args
+ err error
+ }{
+ {
+ name: "no arguments",
+ err: errors.New("read .: is a directory"),
+ },
+ {
+ name: "working example",
+ args: args{
+ basepath: basepath,
+ stateFP: stateFP,
+ headerFP: headerFP,
+ firstSlot: 262493679,
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := ImportState(tt.args.basepath, tt.args.stateFP, tt.args.headerFP, tt.args.firstSlot)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ })
+ }
+}
+
+func Test_newHeaderFromFile(t *testing.T) {
+ t.Parallel()
+
+ type args struct {
+ filename string
+ }
+ tests := []struct {
+ name string
+ args args
+ want *types.Header
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{filename: setupHeaderFile(t)},
+ want: &types.Header{
+ ParentHash: common.MustHexToHash("0x3b45c9c22dcece75a30acc9c2968cb311e6b0557350f83b430f47559db786975"),
+ Number: big.NewInt(1482002),
+ StateRoot: common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb"),
+ ExtrinsicsRoot: common.MustHexToHash("0xda26dc8c1455f8f81cae12e4fc59e23ce961b2c837f6d3f664283af906d344e0"),
+ },
+ },
+ {
+ name: "no arguments",
+ err: errors.New("read .: is a directory"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := newHeaderFromFile(tt.args.filename)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.Equal(t, tt.want.ParentHash, got.ParentHash)
+ assert.Equal(t, tt.want.Number, got.Number)
+ assert.Equal(t, tt.want.StateRoot, got.StateRoot)
+ assert.Equal(t, tt.want.ExtrinsicsRoot, got.ExtrinsicsRoot)
+ }
+ })
+ }
+}
+
+func Test_newTrieFromPairs(t *testing.T) {
+ t.Parallel()
+
+ type args struct {
+ filename string
+ }
+ tests := []struct {
+ name string
+ args args
+ want common.Hash
+ err error
+ }{
+ {
+ name: "no arguments",
+ err: errors.New("read .: is a directory"),
+ want: common.Hash{},
+ },
+ {
+ name: "working example",
+ args: args{filename: setupStateFile(t)},
+ want: common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := newTrieFromPairs(tt.args.filename)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if !tt.want.IsEmpty() {
+ assert.Equal(t, tt.want, got.MustHash())
+ }
+ })
+ }
+}
+
func setupStateFile(t *testing.T) string {
filename := "../lib/runtime/test_data/kusama/block1482002.out"
@@ -53,59 +201,3 @@ func setupHeaderFile(t *testing.T) string {
require.NoError(t, err)
return fp
}
-
-func TestNewTrieFromPairs(t *testing.T) {
- fp := setupStateFile(t)
- tr, err := newTrieFromPairs(fp)
- require.NoError(t, err)
-
- expectedRoot := common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb")
- require.Equal(t, expectedRoot, tr.MustHash())
-}
-
-func TestNewHeaderFromFile(t *testing.T) {
- fp := setupHeaderFile(t)
- header, err := newHeaderFromFile(fp)
- require.NoError(t, err)
-
- digestBytes := common.MustHexToBytes("0x080642414245b501013c0000009659bd0f0000000070edad1c9064fff78cb18435223d8adaf5ea04c24b1a8766e3dc01eb03cc6a0c11b79793d4e31cc0990838229c44fed1669a7c7c79e1e6d0a96374d6496728069d1ef739e290497a0e3b728fa88fcbdd3a5504e0efde0242e7a806dd4fa9260c054241424501019e7f28dddcf27c1e6b328d5694c368d5b2ec5dbe0e412ae1c98f88d53be4d8502fac571f3f19c9caaf281a673319241e0c5095a683ad34316204088a36a4bd86") //nolint:lll
- digest := types.NewDigest()
- err = scale.Unmarshal(digestBytes, &digest)
- require.NoError(t, err)
- require.Equal(t, 2, len(digest.Types))
-
- expected := &types.Header{
- ParentHash: common.MustHexToHash("0x3b45c9c22dcece75a30acc9c2968cb311e6b0557350f83b430f47559db786975"),
- Number: big.NewInt(1482002),
- StateRoot: common.MustHexToHash("0x09f9ca28df0560c2291aa16b56e15e07d1e1927088f51356d522722aa90ca7cb"),
- ExtrinsicsRoot: common.MustHexToHash("0xda26dc8c1455f8f81cae12e4fc59e23ce961b2c837f6d3f664283af906d344e0"),
- Digest: digest,
- }
-
- require.Equal(t, expected, header)
-}
-
-func TestImportState(t *testing.T) {
- basepath := t.TempDir()
-
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
-
- cfg.Global.BasePath = basepath
- err := InitNode(cfg)
- require.NoError(t, err)
-
- stateFP := setupStateFile(t)
- headerFP := setupHeaderFile(t)
-
- firstSlot := uint64(262493679)
- err = ImportState(basepath, stateFP, headerFP, firstSlot)
- require.NoError(t, err)
-}
diff --git a/dot/mock_node_test.go b/dot/mock_node_test.go
new file mode 100644
index 0000000000..76e56ba222
--- /dev/null
+++ b/dot/mock_node_test.go
@@ -0,0 +1,266 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: node.go
+
+// Package dot is a generated GoMock package.
+package dot
+
+import (
+ reflect "reflect"
+
+ core "github.com/ChainSafe/gossamer/dot/core"
+ digest "github.com/ChainSafe/gossamer/dot/digest"
+ network "github.com/ChainSafe/gossamer/dot/network"
+ rpc "github.com/ChainSafe/gossamer/dot/rpc"
+ modules "github.com/ChainSafe/gossamer/dot/rpc/modules"
+ state "github.com/ChainSafe/gossamer/dot/state"
+ sync "github.com/ChainSafe/gossamer/dot/sync"
+ system "github.com/ChainSafe/gossamer/dot/system"
+ types "github.com/ChainSafe/gossamer/dot/types"
+ babe "github.com/ChainSafe/gossamer/lib/babe"
+ grandpa "github.com/ChainSafe/gossamer/lib/grandpa"
+ keystore "github.com/ChainSafe/gossamer/lib/keystore"
+ runtime "github.com/ChainSafe/gossamer/lib/runtime"
+ gomock "github.com/golang/mock/gomock"
+)
+
+// MocknewNodeIface is a mock of newNodeIface interface.
+type MocknewNodeIface struct {
+ ctrl *gomock.Controller
+ recorder *MocknewNodeIfaceMockRecorder
+}
+
+// MocknewNodeIfaceMockRecorder is the mock recorder for MocknewNodeIface.
+type MocknewNodeIfaceMockRecorder struct {
+ mock *MocknewNodeIface
+}
+
+// NewMocknewNodeIface creates a new mock instance.
+func NewMocknewNodeIface(ctrl *gomock.Controller) *MocknewNodeIface {
+ mock := &MocknewNodeIface{ctrl: ctrl}
+ mock.recorder = &MocknewNodeIfaceMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MocknewNodeIface) EXPECT() *MocknewNodeIfaceMockRecorder {
+ return m.recorder
+}
+
+// createBABEService mocks base method.
+func (m *MocknewNodeIface) createBABEService(cfg *Config, st *state.Service, ks keystore.Keystore, cs *core.Service) (*babe.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createBABEService", cfg, st, ks, cs)
+ ret0, _ := ret[0].(*babe.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createBABEService indicates an expected call of createBABEService.
+func (mr *MocknewNodeIfaceMockRecorder) createBABEService(cfg, st, ks, cs interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createBABEService", reflect.TypeOf((*MocknewNodeIface)(nil).createBABEService), cfg, st, ks, cs)
+}
+
+// createBlockVerifier mocks base method.
+func (m *MocknewNodeIface) createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createBlockVerifier", st)
+ ret0, _ := ret[0].(*babe.VerificationManager)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createBlockVerifier indicates an expected call of createBlockVerifier.
+func (mr *MocknewNodeIfaceMockRecorder) createBlockVerifier(st interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createBlockVerifier", reflect.TypeOf((*MocknewNodeIface)(nil).createBlockVerifier), st)
+}
+
+// createCoreService mocks base method.
+func (m *MocknewNodeIface) createCoreService(cfg *Config, ks *keystore.GlobalKeystore, st *state.Service, net *network.Service, dh *digest.Handler) (*core.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createCoreService", cfg, ks, st, net, dh)
+ ret0, _ := ret[0].(*core.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createCoreService indicates an expected call of createCoreService.
+func (mr *MocknewNodeIfaceMockRecorder) createCoreService(cfg, ks, st, net, dh interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createCoreService", reflect.TypeOf((*MocknewNodeIface)(nil).createCoreService), cfg, ks, st, net, dh)
+}
+
+// createDigestHandler mocks base method.
+func (m *MocknewNodeIface) createDigestHandler(st *state.Service) (*digest.Handler, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createDigestHandler", st)
+ ret0, _ := ret[0].(*digest.Handler)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createDigestHandler indicates an expected call of createDigestHandler.
+func (mr *MocknewNodeIfaceMockRecorder) createDigestHandler(st interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createDigestHandler", reflect.TypeOf((*MocknewNodeIface)(nil).createDigestHandler), st)
+}
+
+// createGRANDPAService mocks base method.
+func (m *MocknewNodeIface) createGRANDPAService(cfg *Config, st *state.Service, dh *digest.Handler, ks keystore.Keystore, net *network.Service) (*grandpa.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createGRANDPAService", cfg, st, dh, ks, net)
+ ret0, _ := ret[0].(*grandpa.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createGRANDPAService indicates an expected call of createGRANDPAService.
+func (mr *MocknewNodeIfaceMockRecorder) createGRANDPAService(cfg, st, dh, ks, net interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createGRANDPAService", reflect.TypeOf((*MocknewNodeIface)(nil).createGRANDPAService), cfg, st, dh, ks, net)
+}
+
+// createNetworkService mocks base method.
+func (m *MocknewNodeIface) createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createNetworkService", cfg, stateSrvc)
+ ret0, _ := ret[0].(*network.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createNetworkService indicates an expected call of createNetworkService.
+func (mr *MocknewNodeIfaceMockRecorder) createNetworkService(cfg, stateSrvc interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createNetworkService", reflect.TypeOf((*MocknewNodeIface)(nil).createNetworkService), cfg, stateSrvc)
+}
+
+// createRPCService mocks base method.
+func (m *MocknewNodeIface) createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, coreSrvc *core.Service, networkSrvc *network.Service, bp modules.BlockProducerAPI, sysSrvc *system.Service, finSrvc *grandpa.Service) (*rpc.HTTPServer, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createRPCService", cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, finSrvc)
+ ret0, _ := ret[0].(*rpc.HTTPServer)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createRPCService indicates an expected call of createRPCService.
+func (mr *MocknewNodeIfaceMockRecorder) createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, finSrvc interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createRPCService", reflect.TypeOf((*MocknewNodeIface)(nil).createRPCService), cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, finSrvc)
+}
+
+// createRuntimeStorage mocks base method.
+func (m *MocknewNodeIface) createRuntimeStorage(st *state.Service) (*runtime.NodeStorage, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createRuntimeStorage", st)
+ ret0, _ := ret[0].(*runtime.NodeStorage)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createRuntimeStorage indicates an expected call of createRuntimeStorage.
+func (mr *MocknewNodeIfaceMockRecorder) createRuntimeStorage(st interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createRuntimeStorage", reflect.TypeOf((*MocknewNodeIface)(nil).createRuntimeStorage), st)
+}
+
+// createStateService mocks base method.
+func (m *MocknewNodeIface) createStateService(config *Config) (*state.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createStateService", config)
+ ret0, _ := ret[0].(*state.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createStateService indicates an expected call of createStateService.
+func (mr *MocknewNodeIfaceMockRecorder) createStateService(config interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createStateService", reflect.TypeOf((*MocknewNodeIface)(nil).createStateService), config)
+}
+
+// createSystemService mocks base method.
+func (m *MocknewNodeIface) createSystemService(cfg *types.SystemInfo, stateSrvc *state.Service) (*system.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "createSystemService", cfg, stateSrvc)
+ ret0, _ := ret[0].(*system.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// createSystemService indicates an expected call of createSystemService.
+func (mr *MocknewNodeIfaceMockRecorder) createSystemService(cfg, stateSrvc interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "createSystemService", reflect.TypeOf((*MocknewNodeIface)(nil).createSystemService), cfg, stateSrvc)
+}
+
+// initNode mocks base method.
+func (m *MocknewNodeIface) initNode(config *Config) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "initNode", config)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// initNode indicates an expected call of initNode.
+func (mr *MocknewNodeIfaceMockRecorder) initNode(config interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "initNode", reflect.TypeOf((*MocknewNodeIface)(nil).initNode), config)
+}
+
+// initialiseTelemetry mocks base method.
+func (m *MocknewNodeIface) initialiseTelemetry(cfg *Config, stateSrvc *state.Service, networkSrvc *network.Service, sysSrvc *system.Service) {
+ m.ctrl.T.Helper()
+ m.ctrl.Call(m, "initialiseTelemetry", cfg, stateSrvc, networkSrvc, sysSrvc)
+}
+
+// initialiseTelemetry indicates an expected call of initialiseTelemetry.
+func (mr *MocknewNodeIfaceMockRecorder) initialiseTelemetry(cfg, stateSrvc, networkSrvc, sysSrvc interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "initialiseTelemetry", reflect.TypeOf((*MocknewNodeIface)(nil).initialiseTelemetry), cfg, stateSrvc, networkSrvc, sysSrvc)
+}
+
+// loadRuntime mocks base method.
+func (m *MocknewNodeIface) loadRuntime(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, ks *keystore.GlobalKeystore, net *network.Service) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "loadRuntime", cfg, ns, stateSrvc, ks, net)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// loadRuntime indicates an expected call of loadRuntime.
+func (mr *MocknewNodeIfaceMockRecorder) loadRuntime(cfg, ns, stateSrvc, ks, net interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "loadRuntime", reflect.TypeOf((*MocknewNodeIface)(nil).loadRuntime), cfg, ns, stateSrvc, ks, net)
+}
+
+// newSyncService mocks base method.
+func (m *MocknewNodeIface) newSyncService(cfg *Config, st *state.Service, fg sync.FinalityGadget, verifier *babe.VerificationManager, cs *core.Service, net *network.Service) (*sync.Service, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "newSyncService", cfg, st, fg, verifier, cs, net)
+ ret0, _ := ret[0].(*sync.Service)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// newSyncService indicates an expected call of newSyncService.
+func (mr *MocknewNodeIfaceMockRecorder) newSyncService(cfg, st, fg, verifier, cs, net interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "newSyncService", reflect.TypeOf((*MocknewNodeIface)(nil).newSyncService), cfg, st, fg, verifier, cs, net)
+}
+
+// nodeInitialised mocks base method.
+func (m *MocknewNodeIface) nodeInitialised(arg0 string) bool {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "nodeInitialised", arg0)
+ ret0, _ := ret[0].(bool)
+ return ret0
+}
+
+// nodeInitialised indicates an expected call of nodeInitialised.
+func (mr *MocknewNodeIfaceMockRecorder) nodeInitialised(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "nodeInitialised", reflect.TypeOf((*MocknewNodeIface)(nil).nodeInitialised), arg0)
+}
diff --git a/dot/node.go b/dot/node.go
index 057aad7794..95dc27d01a 100644
--- a/dot/node.go
+++ b/dot/node.go
@@ -15,16 +15,23 @@ import (
"syscall"
"time"
+ "github.com/ChainSafe/gossamer/dot/core"
+ "github.com/ChainSafe/gossamer/dot/digest"
"github.com/ChainSafe/gossamer/dot/metrics"
"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/rpc"
+ "github.com/ChainSafe/gossamer/dot/rpc/modules"
"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/dot/state/pruner"
+ gsync "github.com/ChainSafe/gossamer/dot/sync"
+ "github.com/ChainSafe/gossamer/dot/system"
"github.com/ChainSafe/gossamer/dot/telemetry"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/log"
+ "github.com/ChainSafe/gossamer/lib/babe"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/genesis"
+ "github.com/ChainSafe/gossamer/lib/grandpa"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/lib/runtime"
"github.com/ChainSafe/gossamer/lib/services"
@@ -41,9 +48,87 @@ type Node struct {
started chan struct{}
}
+//go:generate mockgen -source=node.go -destination=mock_node_test.go -package=$GOPACKAGE
+
+type newNodeIface interface {
+ nodeInitialised(string) bool
+ initNode(config *Config) error
+ createStateService(config *Config) (*state.Service, error)
+ createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Service, error)
+ createRuntimeStorage(st *state.Service) (*runtime.NodeStorage, error)
+ loadRuntime(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, ks *keystore.GlobalKeystore,
+ net *network.Service) error
+ createBlockVerifier(st *state.Service) (*babe.VerificationManager, error)
+ createDigestHandler(st *state.Service) (*digest.Handler, error)
+ createCoreService(cfg *Config, ks *keystore.GlobalKeystore, st *state.Service, net *network.Service,
+ dh *digest.Handler) (*core.Service, error)
+ createGRANDPAService(cfg *Config, st *state.Service, dh *digest.Handler, ks keystore.Keystore,
+ net *network.Service) (*grandpa.Service, error)
+ newSyncService(cfg *Config, st *state.Service, fg gsync.FinalityGadget, verifier *babe.VerificationManager,
+ cs *core.Service, net *network.Service) (*gsync.Service, error)
+ createBABEService(cfg *Config, st *state.Service, ks keystore.Keystore, cs *core.Service) (*babe.Service, error)
+ createSystemService(cfg *types.SystemInfo, stateSrvc *state.Service) (*system.Service, error)
+ createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service, coreSrvc *core.Service,
+ networkSrvc *network.Service, bp modules.BlockProducerAPI, sysSrvc *system.Service,
+ finSrvc *grandpa.Service) (*rpc.HTTPServer, error)
+ initialiseTelemetry(cfg *Config, stateSrvc *state.Service, networkSrvc *network.Service, sysSrvc *system.Service)
+}
+
+type nodeInterface struct{}
+
+// NodeInitialized returns true if, within the configured data directory for the
+// node, the state database has been created and the genesis data has been loaded
+func NodeInitialized(basepath string) bool {
+ nodeI := nodeInterface{}
+ return nodeI.nodeInitialised(basepath)
+}
+
+func (nodeInterface) nodeInitialised(basepath string) bool {
+ // check if key registry exists
+ registry := path.Join(basepath, utils.DefaultDatabaseDir, "KEYREGISTRY")
+
+ _, err := os.Stat(registry)
+ if os.IsNotExist(err) {
+ logger.Debug("node has not been initialised from base path " + basepath +
+ ": failed to locate KEYREGISTRY file in data directory")
+
+ return false
+ }
+
+ // initialise database using data directory
+ db, err := utils.SetupDatabase(basepath, false)
+ if err != nil {
+ logger.Debugf("failed to create database from base path %s: %s", basepath, err)
+ return false
+ }
+
+ defer func() {
+ // close database
+ err = db.Close()
+ if err != nil {
+ logger.Errorf("failed to close database: %s", err)
+ }
+ }()
+
+ // load genesis data from initialised node database
+ _, err = state.NewBaseState(db).LoadGenesisData()
+ if err != nil {
+ logger.Errorf("node has not been initialised from base path %s: %s", basepath, err)
+ return false
+ }
+
+ return true
+}
+
+// InitNode initialise the node with given Config
+func InitNode(cfg *Config) error {
+ nodeI := nodeInterface{}
+ return nodeI.initNode(cfg)
+}
+
// InitNode initialises a new dot node from the provided dot node configuration
// and JSON formatted genesis file.
-func InitNode(cfg *Config) error {
+func (nodeInterface) initNode(cfg *Config) error {
logger.Patch(log.SetLevel(cfg.Global.LogLvl))
logger.Infof(
"🕸️ initialising node with name %s, id %s, base path %s and genesis %s...",
@@ -105,45 +190,6 @@ func InitNode(cfg *Config) error {
return nil
}
-// NodeInitialized returns true if, within the configured data directory for the
-// node, the state database has been created and the genesis data has been loaded
-func NodeInitialized(basepath string) bool {
- // check if key registry exists
- registry := path.Join(basepath, utils.DefaultDatabaseDir, "KEYREGISTRY")
-
- _, err := os.Stat(registry)
- if os.IsNotExist(err) {
- logger.Debug("node has not been initialised from base path " + basepath +
- ": failed to locate KEYREGISTRY file in data directory")
-
- return false
- }
-
- // initialise database using data directory
- db, err := utils.SetupDatabase(basepath, false)
- if err != nil {
- logger.Debugf("failed to create database from base path %s: %s", basepath, err)
- return false
- }
-
- defer func() {
- // close database
- err = db.Close()
- if err != nil {
- logger.Errorf("failed to close database: %s", err)
- }
- }()
-
- // load genesis data from initialised node database
- _, err = state.NewBaseState(db).LoadGenesisData()
- if err != nil {
- logger.Errorf("node has not been initialised from base path %s: %s", basepath, err)
- return false
- }
-
- return true
-}
-
// LoadGlobalNodeName returns the stored global node name from database
func LoadGlobalNodeName(basepath string) (nodename string, err error) {
// initialise database using data directory
@@ -153,9 +199,9 @@ func LoadGlobalNodeName(basepath string) (nodename string, err error) {
}
defer func() {
- err = db.Close()
- if err != nil {
- logger.Errorf("failed to close database: %s", err)
+ closeErr := db.Close()
+ if closeErr != nil {
+ logger.Errorf("failed to close database: %s", closeErr)
return
}
}()
@@ -164,14 +210,16 @@ func LoadGlobalNodeName(basepath string) (nodename string, err error) {
nodename, err = basestate.LoadNodeGlobalName()
if err != nil {
logger.Warnf("failed to load global node name from base path %s: %s", basepath, err)
- return "", err
}
-
return nodename, err
}
-// NewNode creates a new dot node from a dot node configuration
+// NewNode to create node
func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
+ return newNode(cfg, ks, nodeInterface{})
+}
+
+func newNode(cfg *Config, ks *keystore.GlobalKeystore, nn newNodeIface) (*Node, error) {
// set garbage collection percent to 10%
// can be overwritten by setting the GOGC env variable, which defaults to 100
prev := debug.SetGCPercent(10)
@@ -179,13 +227,15 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
debug.SetGCPercent(prev)
}
- logger.Patch(log.SetLevel(cfg.Global.LogLvl))
-
- // if authority node, should have at least 1 key in keystore
- if cfg.Core.Roles == types.AuthorityRole && (ks.Babe.Size() == 0 || ks.Gran.Size() == 0) {
- return nil, ErrNoKeysProvided
+ if !nn.nodeInitialised(cfg.Global.BasePath) {
+ err := nn.initNode(cfg)
+ if err != nil {
+ return nil, err
+ }
}
+ logger.Patch(log.SetLevel(cfg.Global.LogLvl))
+
logger.Infof(
"🕸️ initialising node services with global configuration name %s, id %s and base path %s...",
cfg.Global.Name, cfg.Global.ID, cfg.Global.BasePath)
@@ -195,11 +245,7 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
networkSrvc *network.Service
)
- if cfg.Pprof.Enabled {
- nodeSrvcs = append(nodeSrvcs, createPprofService(cfg.Pprof.Settings))
- }
-
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := nn.createStateService(cfg)
if err != nil {
return nil, fmt.Errorf("failed to create state service: %s", err)
}
@@ -207,7 +253,7 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
// check if network service is enabled
if enabled := networkServiceEnabled(cfg); enabled {
// create network service and append network service to node services
- networkSrvc, err = createNetworkService(cfg, stateSrvc)
+ networkSrvc, err = nn.createNetworkService(cfg, stateSrvc)
if err != nil {
return nil, fmt.Errorf("failed to create network service: %s", err)
}
@@ -218,40 +264,40 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
}
// create runtime
- ns, err := createRuntimeStorage(stateSrvc)
+ ns, err := nn.createRuntimeStorage(stateSrvc)
if err != nil {
return nil, err
}
- err = loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
+ err = nn.loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
if err != nil {
return nil, err
}
- ver, err := createBlockVerifier(stateSrvc)
+ ver, err := nn.createBlockVerifier(stateSrvc)
if err != nil {
return nil, err
}
- dh, err := createDigestHandler(stateSrvc)
+ dh, err := nn.createDigestHandler(stateSrvc)
if err != nil {
return nil, err
}
nodeSrvcs = append(nodeSrvcs, dh)
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ coreSrvc, err := nn.createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
if err != nil {
return nil, fmt.Errorf("failed to create core service: %s", err)
}
nodeSrvcs = append(nodeSrvcs, coreSrvc)
- fg, err := createGRANDPAService(cfg, stateSrvc, dh, ks.Gran, networkSrvc)
+ fg, err := nn.createGRANDPAService(cfg, stateSrvc, dh, ks.Gran, networkSrvc)
if err != nil {
return nil, err
}
nodeSrvcs = append(nodeSrvcs, fg)
- syncer, err := newSyncService(cfg, stateSrvc, fg, ver, coreSrvc, networkSrvc)
+ syncer, err := nn.newSyncService(cfg, stateSrvc, fg, ver, coreSrvc, networkSrvc)
if err != nil {
return nil, err
}
@@ -262,13 +308,13 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
}
nodeSrvcs = append(nodeSrvcs, syncer)
- bp, err := createBABEService(cfg, stateSrvc, ks.Babe, coreSrvc)
+ bp, err := nn.createBABEService(cfg, stateSrvc, ks.Babe, coreSrvc)
if err != nil {
return nil, err
}
nodeSrvcs = append(nodeSrvcs, bp)
- sysSrvc, err := createSystemService(&cfg.System, stateSrvc)
+ sysSrvc, err := nn.createSystemService(&cfg.System, stateSrvc)
if err != nil {
return nil, fmt.Errorf("failed to create system service: %s", err)
}
@@ -277,7 +323,7 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
// check if rpc service is enabled
if enabled := cfg.RPC.isRPCEnabled() || cfg.RPC.isWSEnabled(); enabled {
var rpcSrvc *rpc.HTTPServer
- rpcSrvc, err = createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg)
+ rpcSrvc, err = nn.createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, bp, sysSrvc, fg)
if err != nil {
return nil, fmt.Errorf("failed to create rpc service: %s", err)
}
@@ -313,9 +359,16 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
metrics.PublishMetrics(address)
}
+ nn.initialiseTelemetry(cfg, stateSrvc, networkSrvc, sysSrvc)
+
+ return node, nil
+}
+
+func (nodeInterface) initialiseTelemetry(cfg *Config, stateSrvc *state.Service, networkSrvc *network.Service,
+ sysSrvc *system.Service) {
gd, err := stateSrvc.Base.LoadGenesisData()
if err != nil {
- return nil, err
+ logger.Debugf("problem initialising telemetry: %s", err)
}
telemetry.GetInstance().Initialise(!cfg.Global.NoTelemetry)
@@ -333,19 +386,52 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore) (*Node, error) {
telemetry.GetInstance().AddConnections(telemetryEndpoints)
genesisHash := stateSrvc.Block.GenesisHash()
+ peerID := ""
+ if networkSrvc != nil {
+ peerID = networkSrvc.NetworkState().PeerID
+ }
err = telemetry.GetInstance().SendMessage(telemetry.NewSystemConnectedTM(
cfg.Core.GrandpaAuthority,
sysSrvc.ChainName(),
&genesisHash,
sysSrvc.SystemName(),
cfg.Global.Name,
- networkSrvc.NetworkState().PeerID,
+ peerID,
strconv.FormatInt(time.Now().UnixNano(), 10),
sysSrvc.SystemVersion()))
if err != nil {
logger.Debugf("problem sending system.connected telemetry message: %s", err)
}
- return node, nil
+}
+
+//InitKeystore to initialize node keystore
+func InitKeystore(cfg *Config) (*keystore.GlobalKeystore, error) {
+ ks := keystore.NewGlobalKeystore()
+ // load built-in test keys if specified by `cfg.Account.Key`
+ err := keystore.LoadKeystore(cfg.Account.Key, ks.Acco)
+ if err != nil {
+ logger.Errorf("failed to load account keystore: %s", err)
+ return nil, err
+ }
+
+ err = keystore.LoadKeystore(cfg.Account.Key, ks.Babe)
+ if err != nil {
+ logger.Errorf("failed to load BABE keystore: %s", err)
+ return nil, err
+ }
+
+ err = keystore.LoadKeystore(cfg.Account.Key, ks.Gran)
+ if err != nil {
+ logger.Errorf("failed to load grandpa keystore: %s", err)
+ return nil, err
+ }
+
+ // if authority node, should have at least 1 key in keystore
+ if cfg.Core.Roles == types.AuthorityRole && (ks.Babe.Size() == 0 || ks.Gran.Size() == 0) {
+ return nil, ErrNoKeysProvided
+ }
+
+ return ks, nil
}
// stores the global node name to reuse
@@ -402,7 +488,7 @@ func (n *Node) Stop() {
n.wg.Done()
}
-func loadRuntime(cfg *Config, ns *runtime.NodeStorage,
+func (nodeInterface) loadRuntime(cfg *Config, ns *runtime.NodeStorage,
stateSrvc *state.Service, ks *keystore.GlobalKeystore,
net *network.Service) error {
blocks := stateSrvc.Block.GetNonFinalisedBlocks()
diff --git a/dot/node_integration_test.go b/dot/node_integration_test.go
new file mode 100644
index 0000000000..1356db02d9
--- /dev/null
+++ b/dot/node_integration_test.go
@@ -0,0 +1,415 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "math/big"
+ "reflect"
+ "sync"
+ "testing"
+
+ "github.com/ChainSafe/gossamer/dot/core"
+ "github.com/ChainSafe/gossamer/dot/state"
+ "github.com/ChainSafe/gossamer/dot/types"
+ "github.com/ChainSafe/gossamer/lib/babe"
+ "github.com/ChainSafe/gossamer/lib/common"
+ "github.com/ChainSafe/gossamer/lib/crypto/sr25519"
+ "github.com/ChainSafe/gossamer/lib/genesis"
+ "github.com/ChainSafe/gossamer/lib/grandpa"
+ "github.com/ChainSafe/gossamer/lib/keystore"
+ "github.com/ChainSafe/gossamer/lib/services"
+ "github.com/ChainSafe/gossamer/lib/trie"
+ "github.com/ChainSafe/gossamer/lib/utils"
+
+ log "github.com/ChainSafe/gossamer/internal/log"
+ "github.com/stretchr/testify/require"
+)
+
+func TestInitNode_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+}
+
+func TestInitNode_GenesisSpec(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+}
+
+// TestNodeInitialized
+func TestNodeInitialized_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ expected := NodeInitialized(cfg.Global.BasePath)
+ require.Equal(t, expected, false)
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ expected = NodeInitialized(cfg.Global.BasePath)
+ require.Equal(t, expected, true)
+}
+
+// TestNewNode
+func TestNewNode_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ err = keystore.LoadKeystore("alice", ks.Gran)
+ require.NoError(t, err)
+ err = keystore.LoadKeystore("alice", ks.Babe)
+ require.NoError(t, err)
+
+ cfg.Core.Roles = types.FullNodeRole
+
+ node, err := NewNode(cfg, ks)
+ require.NoError(t, err)
+
+ bp := node.Services.Get(&babe.Service{})
+ require.NotNil(t, bp)
+ fg := node.Services.Get(&grandpa.Service{})
+ require.NotNil(t, fg)
+}
+
+func TestNewNode_Authority(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ err = keystore.LoadKeystore("alice", ks.Gran)
+ require.NoError(t, err)
+ require.Equal(t, 1, ks.Gran.Size())
+ err = keystore.LoadKeystore("alice", ks.Babe)
+ require.NoError(t, err)
+ require.Equal(t, 1, ks.Babe.Size())
+
+ cfg.Core.Roles = types.AuthorityRole
+
+ node, err := NewNode(cfg, ks)
+ require.NoError(t, err)
+
+ bp := node.Services.Get(&babe.Service{})
+ require.NotNil(t, bp)
+ fg := node.Services.Get(&grandpa.Service{})
+ require.NotNil(t, fg)
+}
+
+// TestInitNode_LoadGenesisData
+func TestInitNode_LoadGenesisData(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genPath := NewTestGenesisAndRuntime(t)
+ require.NotNil(t, genPath)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genPath
+ cfg.Core.GrandpaAuthority = false
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ config := state.Config{
+ Path: cfg.Global.BasePath,
+ LogLevel: log.Info,
+ }
+ stateSrvc := state.NewService(config)
+
+ gen, err := genesis.NewGenesisFromJSONRaw(genPath)
+ require.NoError(t, err)
+
+ genTrie, err := genesis.NewTrieFromGenesis(gen)
+ require.NoError(t, err)
+
+ genesisHeader, err := types.NewHeader(common.NewHash([]byte{0}), genTrie.MustHash(), trie.EmptyHash,
+ big.NewInt(0), types.NewDigest())
+ require.NoError(t, err)
+
+ err = stateSrvc.Initialise(gen, genesisHeader, genTrie)
+ require.NoError(t, err)
+
+ err = stateSrvc.Start()
+ require.NoError(t, err)
+
+ defer func() {
+ err = stateSrvc.Stop()
+ require.NoError(t, err)
+ }()
+
+ gendata, err := stateSrvc.Base.LoadGenesisData()
+ require.NoError(t, err)
+
+ testGenesis := NewTestGenesis(t)
+
+ expected := &genesis.Data{
+ Name: testGenesis.Name,
+ ID: testGenesis.ID,
+ Bootnodes: common.StringArrayToBytes(testGenesis.Bootnodes),
+ ProtocolID: testGenesis.ProtocolID,
+ }
+ require.Equal(t, expected, gendata)
+
+ genesisHeader, err = stateSrvc.Block.BestBlockHeader()
+ require.NoError(t, err)
+
+ stateRoot := genesisHeader.StateRoot
+ expectedHeader, err := types.NewHeader(common.NewHash([]byte{0}), stateRoot, trie.EmptyHash, big.NewInt(0),
+ types.NewDigest())
+ require.NoError(t, err)
+ require.Equal(t, expectedHeader.Hash(), genesisHeader.Hash())
+}
+
+// TestInitNode_LoadStorageRoot
+func TestInitNode_LoadStorageRoot(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genPath := NewTestGenesisAndRuntime(t)
+ require.NotNil(t, genPath)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genPath
+
+ gen, err := genesis.NewGenesisFromJSONRaw(genPath)
+ require.NoError(t, err)
+
+ err = InitNode(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
+ sr25519Keyring, _ := keystore.NewSr25519Keyring()
+ ks.Babe.Insert(sr25519Keyring.Alice())
+ node, err := NewNode(cfg, ks)
+ require.NoError(t, err)
+
+ if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) {
+ t.Fatalf("failed to return correct type: got %v expected %v", reflect.TypeOf(node), reflect.TypeOf(&Node{}))
+ }
+
+ expected := &trie.Trie{}
+ err = expected.LoadFromMap(gen.GenesisFields().Raw["top"])
+ require.NoError(t, err)
+
+ expectedRoot, err := expected.Hash()
+ require.NoError(t, err)
+
+ mgr := node.Services.Get(&core.Service{})
+
+ var coreSrvc *core.Service
+ var ok bool
+
+ if coreSrvc, ok = mgr.(*core.Service); !ok {
+ t.Fatal("could not find core service")
+ }
+ require.NotNil(t, coreSrvc)
+
+ stateRoot, err := coreSrvc.StorageRoot()
+ require.NoError(t, err)
+ require.Equal(t, expectedRoot, stateRoot)
+}
+
+// balanceKey returns the storage trie key for the balance of the account with the given public key
+func balanceKey(t *testing.T, key [32]byte) []byte {
+ accKey := append([]byte("balance:"), key[:]...)
+ hash, err := common.Blake2bHash(accKey)
+ require.NoError(t, err)
+ return hash[:]
+}
+
+func TestInitNode_LoadBalances(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genPath := NewTestGenesisAndRuntime(t)
+ require.NotNil(t, genPath)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genPath
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
+
+ node, err := NewNode(cfg, ks)
+ require.NoError(t, err)
+
+ if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) {
+ t.Fatalf("failed to return correct type: got %v expected %v", reflect.TypeOf(node), reflect.TypeOf(&Node{}))
+ }
+
+ mgr := node.Services.Get(&state.Service{})
+
+ var stateSrv *state.Service
+ var ok bool
+
+ if stateSrv, ok = mgr.(*state.Service); !ok {
+ t.Fatal("could not find core service")
+ }
+ require.NotNil(t, stateSrv)
+
+ kr, _ := keystore.NewSr25519Keyring()
+ alice := kr.Alice().Public().(*sr25519.PublicKey).AsBytes()
+
+ bal, err := stateSrv.Storage.GetStorage(nil, balanceKey(t, alice))
+ require.NoError(t, err)
+
+ genbal := "0x0000000000000001"
+ expected, _ := common.HexToBytes(genbal)
+ require.Equal(t, expected, bal)
+}
+
+// TestStartNode
+func TestStartNode(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+ cfg.Core.GrandpaAuthority = false
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ err = keystore.LoadKeystore("alice", ks.Gran)
+ require.NoError(t, err)
+ err = keystore.LoadKeystore("alice", ks.Babe)
+ require.NoError(t, err)
+
+ cfg.Core.Roles = types.FullNodeRole
+
+ node, err := NewNode(cfg, ks)
+ require.NoError(t, err)
+
+ go func() {
+ <-node.started
+ node.Stop()
+ }()
+
+ err = node.Start()
+ require.NoError(t, err)
+}
+
+func TestNode_StopFunc(t *testing.T) {
+ testvar := "before"
+ //stopFunc := func() {
+ // testvar = "after"
+ //}
+
+ node := &Node{
+ Services: &services.ServiceRegistry{},
+ wg: sync.WaitGroup{},
+ }
+ node.wg.Add(1)
+
+ node.Stop()
+ require.Equal(t, testvar, "after")
+}
+
+func TestNode_PersistGlobalName_WhenInitialize(t *testing.T) {
+ globalName := RandomNodeName()
+
+ cfg := NewTestConfig(t)
+ cfg.Global.Name = globalName
+ require.NotNil(t, cfg)
+
+ genPath := NewTestGenesisAndRuntime(t)
+ require.NotNil(t, genPath)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genPath
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ storedName, err := LoadGlobalNodeName(cfg.Global.BasePath)
+ require.Nil(t, err)
+ require.Equal(t, globalName, storedName)
+}
diff --git a/dot/node_test.go b/dot/node_test.go
index 1d589486a9..e5ba149cf7 100644
--- a/dot/node_test.go
+++ b/dot/node_test.go
@@ -4,30 +4,30 @@
package dot
import (
- "math/big"
- "reflect"
+ "errors"
+ "os"
"testing"
"github.com/ChainSafe/gossamer/dot/core"
+ "github.com/ChainSafe/gossamer/dot/digest"
+ "github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/state"
+ gsync "github.com/ChainSafe/gossamer/dot/sync"
+ "github.com/ChainSafe/gossamer/dot/system"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/babe"
"github.com/ChainSafe/gossamer/lib/common"
- "github.com/ChainSafe/gossamer/lib/crypto/sr25519"
- "github.com/ChainSafe/gossamer/lib/genesis"
"github.com/ChainSafe/gossamer/lib/grandpa"
- "github.com/ChainSafe/gossamer/lib/keystore"
- "github.com/ChainSafe/gossamer/lib/trie"
+ "github.com/ChainSafe/gossamer/lib/runtime"
+ "github.com/ChainSafe/gossamer/lib/runtime/wasmer"
"github.com/ChainSafe/gossamer/lib/utils"
-
- "github.com/ChainSafe/gossamer/internal/log"
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestInitNode(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
genFile := NewTestGenesisRawFile(t, cfg)
require.NotNil(t, genFile)
@@ -35,348 +35,250 @@ func TestInitNode(t *testing.T) {
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
- require.NoError(t, err)
-}
-
-func TestInitNode_GenesisSpec(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
-
- err := InitNode(cfg)
- require.NoError(t, err)
+ type args struct {
+ cfg *Config
+ }
+ tests := []struct {
+ name string
+ args args
+ err error
+ }{
+ {
+ name: "test config",
+ args: args{cfg: cfg},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ni := nodeInterface{}
+ err := ni.initNode(tt.args.cfg)
+
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ })
+ }
}
-// TestNodeInitialized
-func TestNodeInitialized(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
+func TestLoadGlobalNodeName(t *testing.T) {
+ t.Parallel()
- cfg.Init.Genesis = genFile.Name()
-
- expected := NodeInitialized(cfg.Global.BasePath)
- require.Equal(t, expected, false)
-
- err := InitNode(cfg)
+ // initialise database using data directory
+ basePath := utils.NewTestBasePath(t, "tmpBase")
+ db, err := utils.SetupDatabase(basePath, false)
require.NoError(t, err)
- expected = NodeInitialized(cfg.Global.BasePath)
- require.Equal(t, expected, true)
-}
+ basestate := state.NewBaseState(db)
+ basestate.Put(common.NodeNameKey, []byte(`nodeName`))
-// TestNewNode
-func TestNewNode(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
-
- err := InitNode(cfg)
+ err = db.Close()
require.NoError(t, err)
- ks := keystore.NewGlobalKeystore()
- err = keystore.LoadKeystore("alice", ks.Gran)
- require.NoError(t, err)
- err = keystore.LoadKeystore("alice", ks.Babe)
- require.NoError(t, err)
-
- cfg.Core.Roles = types.FullNodeRole
-
- node, err := NewNode(cfg, ks)
- require.NoError(t, err)
-
- bp := node.Services.Get(&babe.Service{})
- require.NotNil(t, bp)
- fg := node.Services.Get(&grandpa.Service{})
- require.NotNil(t, fg)
+ type args struct {
+ basepath string
+ }
+ tests := []struct {
+ name string
+ args args
+ wantNodename string
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{basepath: basePath},
+ wantNodename: "nodeName",
+ },
+ {
+ name: "wrong basepath test",
+ args: args{basepath: "wrong_path"},
+ err: errors.New("Key not found"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ gotNodename, err := LoadGlobalNodeName(tt.args.basepath)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ err := os.RemoveAll(tt.args.basepath)
+ require.NoError(t, err)
+ } else {
+ assert.NoError(t, err)
+ }
+
+ assert.Equal(t, tt.wantNodename, gotNodename)
+ })
+ }
}
-func TestNewNode_Authority(t *testing.T) {
+func TestNewNodeC(t *testing.T) {
cfg := NewTestConfig(t)
require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
defer utils.RemoveTestDir(t)
- cfg.Init.Genesis = genFile.Name()
-
- err := InitNode(cfg)
- require.NoError(t, err)
-
- ks := keystore.NewGlobalKeystore()
- err = keystore.LoadKeystore("alice", ks.Gran)
- require.NoError(t, err)
- require.Equal(t, 1, ks.Gran.Size())
- err = keystore.LoadKeystore("alice", ks.Babe)
- require.NoError(t, err)
- require.Equal(t, 1, ks.Babe.Size())
-
- cfg.Core.Roles = types.AuthorityRole
-
- node, err := NewNode(cfg, ks)
- require.NoError(t, err)
-
- bp := node.Services.Get(&babe.Service{})
- require.NotNil(t, bp)
- fg := node.Services.Get(&grandpa.Service{})
- require.NotNil(t, fg)
-}
-
-// TestStartNode
-func TestStartNode(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
genFile := NewTestGenesisRawFile(t, cfg)
require.NotNil(t, genFile)
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
- cfg.Core.GrandpaAuthority = false
- cfg.Core.BABELead = true
-
- err := InitNode(cfg)
- require.NoError(t, err)
-
- ks := keystore.NewGlobalKeystore()
- err = keystore.LoadKeystore("alice", ks.Gran)
- require.NoError(t, err)
- err = keystore.LoadKeystore("alice", ks.Babe)
- require.NoError(t, err)
-
- cfg.Core.Roles = types.FullNodeRole
-
- node, err := NewNode(cfg, ks)
- require.NoError(t, err)
-
- go func() {
- <-node.started
- node.Stop()
- }()
-
- err = node.Start()
- require.NoError(t, err)
-}
-
-// TestInitNode_LoadGenesisData
-func TestInitNode_LoadGenesisData(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genPath := NewTestGenesisAndRuntime(t)
- require.NotNil(t, genPath)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genPath
- cfg.Core.GrandpaAuthority = false
-
- err := InitNode(cfg)
- require.NoError(t, err)
-
- config := state.Config{
- Path: cfg.Global.BasePath,
- LogLevel: log.Info,
+ type args struct {
+ cfg *Config
}
- stateSrvc := state.NewService(config)
-
- gen, err := genesis.NewGenesisFromJSONRaw(genPath)
- require.NoError(t, err)
-
- genTrie, err := genesis.NewTrieFromGenesis(gen)
- require.NoError(t, err)
-
- genesisHeader, err := types.NewHeader(common.NewHash([]byte{0}),
- genTrie.MustHash(), trie.EmptyHash, big.NewInt(0), types.NewDigest())
- require.NoError(t, err)
-
- err = stateSrvc.Initialise(gen, genesisHeader, genTrie)
- require.NoError(t, err)
-
- err = stateSrvc.Start()
- require.NoError(t, err)
-
- defer func() {
- err = stateSrvc.Stop()
- require.NoError(t, err)
- }()
-
- gendata, err := stateSrvc.Base.LoadGenesisData()
- require.NoError(t, err)
-
- testGenesis := NewTestGenesis(t)
-
- expected := &genesis.Data{
- Name: testGenesis.Name,
- ID: testGenesis.ID,
- Bootnodes: common.StringArrayToBytes(testGenesis.Bootnodes),
- ProtocolID: testGenesis.ProtocolID,
- }
- require.Equal(t, expected, gendata)
-
- genesisHeader, err = stateSrvc.Block.BestBlockHeader()
- require.NoError(t, err)
-
- stateRoot := genesisHeader.StateRoot
- expectedHeader, err := types.NewHeader(common.NewHash([]byte{0}),
- stateRoot, trie.EmptyHash, big.NewInt(0), types.NewDigest())
- require.NoError(t, err)
- require.Equal(t, expectedHeader.Hash(), genesisHeader.Hash())
-}
-
-// TestInitNode_LoadStorageRoot
-func TestInitNode_LoadStorageRoot(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genPath := NewTestGenesisAndRuntime(t)
- require.NotNil(t, genPath)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
- cfg.Init.Genesis = genPath
-
- gen, err := genesis.NewGenesisFromJSONRaw(genPath)
- require.NoError(t, err)
-
- err = InitNode(cfg)
- require.NoError(t, err)
-
- ks := keystore.NewGlobalKeystore()
- ed25519Keyring, _ := keystore.NewEd25519Keyring()
- ks.Gran.Insert(ed25519Keyring.Alice())
- sr25519Keyring, _ := keystore.NewSr25519Keyring()
- ks.Babe.Insert(sr25519Keyring.Alice())
- node, err := NewNode(cfg, ks)
- require.NoError(t, err)
-
- if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) {
- t.Fatalf("failed to return correct type: got %v expected %v", reflect.TypeOf(node), reflect.TypeOf(&Node{}))
+ tests := []struct {
+ name string
+ args args
+ want *Node
+ err error
+ }{
+ {
+ name: "minimal config",
+ args: args{
+ cfg: &Config{
+ Global: GlobalConfig{BasePath: cfg.Global.BasePath},
+ Init: InitConfig{Genesis: genFile.Name()},
+ Account: AccountConfig{Key: "alice"},
+ Core: CoreConfig{
+ Roles: types.FullNodeRole,
+ WasmInterpreter: wasmer.Name,
+ },
+ },
+ },
+ },
}
-
- expected := &trie.Trie{}
- err = expected.LoadFromMap(gen.GenesisFields().Raw["top"])
- require.NoError(t, err)
-
- expectedRoot, err := expected.Hash()
- require.NoError(t, err)
-
- mgr := node.Services.Get(&core.Service{})
-
- var coreSrvc *core.Service
- var ok bool
-
- if coreSrvc, ok = mgr.(*core.Service); !ok {
- t.Fatal("could not find core service")
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ks, err := InitKeystore(tt.args.cfg)
+ assert.NoError(t, err)
+ got, err := NewNode(tt.args.cfg, ks)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ utils.RemoveTestDir(t)
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.Equal(t, tt.want.Name, got.Name)
+ }
+ })
}
- require.NotNil(t, coreSrvc)
-
- stateRoot, err := coreSrvc.StorageRoot()
- require.NoError(t, err)
- require.Equal(t, expectedRoot, stateRoot)
}
-// balanceKey returns the storage trie key for the balance of the account with the given public key
-func balanceKey(t *testing.T, key [32]byte) []byte {
- accKey := append([]byte("balance:"), key[:]...)
- hash, err := common.Blake2bHash(accKey)
- require.NoError(t, err)
- return hash[:]
-}
+func TestNewNodeMock(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
-func TestInitNode_LoadBalances(t *testing.T) {
cfg := NewTestConfig(t)
require.NotNil(t, cfg)
-
- genPath := NewTestGenesisAndRuntime(t)
- require.NotNil(t, genPath)
-
defer utils.RemoveTestDir(t)
- cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
- cfg.Init.Genesis = genPath
-
- err := InitNode(cfg)
- require.NoError(t, err)
-
- ks := keystore.NewGlobalKeystore()
- ed25519Keyring, _ := keystore.NewEd25519Keyring()
- ks.Gran.Insert(ed25519Keyring.Alice())
-
- node, err := NewNode(cfg, ks)
- require.NoError(t, err)
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
- if reflect.TypeOf(node) != reflect.TypeOf(&Node{}) {
- t.Fatalf("failed to return correct type: got %v expected %v", reflect.TypeOf(node), reflect.TypeOf(&Node{}))
+ type args struct {
+ cfg *Config
}
-
- mgr := node.Services.Get(&state.Service{})
-
- var stateSrv *state.Service
- var ok bool
-
- if stateSrv, ok = mgr.(*state.Service); !ok {
- t.Fatal("could not find core service")
+ tests := []struct {
+ name string
+ args args
+ want *Node
+ err error
+ }{
+ {
+ name: "minimal config",
+ args: args{
+ cfg: &Config{
+ Global: GlobalConfig{BasePath: cfg.Global.BasePath},
+ Init: InitConfig{Genesis: genFile.Name()},
+ Account: AccountConfig{Key: "alice"},
+ Core: CoreConfig{
+ Roles: types.FullNodeRole,
+ WasmInterpreter: wasmer.Name,
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ ks, err := InitKeystore(tt.args.cfg)
+ assert.NoError(t, err)
+ m := NewMocknewNodeIface(ctrl)
+ m.EXPECT().nodeInitialised(tt.args.cfg.Global.BasePath).Return(true)
+ m.EXPECT().createStateService(tt.args.cfg).Return(&state.Service{}, nil)
+ m.EXPECT().createRuntimeStorage(&state.Service{}).Return(&runtime.NodeStorage{}, nil)
+ m.EXPECT().loadRuntime(tt.args.cfg, &runtime.NodeStorage{}, &state.Service{}, ks, &network.Service{}).Return(nil)
+ m.EXPECT().createBlockVerifier(&state.Service{}).Return(&babe.VerificationManager{}, nil)
+ m.EXPECT().createDigestHandler(&state.Service{}).Return(&digest.Handler{}, nil)
+ m.EXPECT().createCoreService(tt.args.cfg, ks, &state.Service{}, &network.Service{},
+ &digest.Handler{}).Return(&core.Service{}, nil)
+ m.EXPECT().createGRANDPAService(tt.args.cfg, &state.Service{}, &digest.Handler{}, ks.Gran,
+ &network.Service{}).Return(&grandpa.Service{}, nil)
+ m.EXPECT().newSyncService(tt.args.cfg, &state.Service{}, &grandpa.Service{}, &babe.VerificationManager{},
+ &core.Service{}, &network.Service{}).Return(&gsync.Service{}, nil)
+ m.EXPECT().createBABEService(tt.args.cfg, &state.Service{}, ks.Babe,
+ &core.Service{}).Return(&babe.Service{}, nil)
+ m.EXPECT().createSystemService(&tt.args.cfg.System, &state.Service{}).Return(&system.Service{}, nil)
+ netA := &network.Service{}
+ netA.SetTransactionHandler(&core.Service{})
+ netA.SetSyncer(&gsync.Service{})
+ m.EXPECT().initialiseTelemetry(tt.args.cfg, &state.Service{}, netA,
+ &system.Service{})
+ m.EXPECT().createNetworkService(tt.args.cfg, &state.Service{}).Return(&network.Service{}, nil)
+
+ got, err := newNode(tt.args.cfg, ks, m)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ utils.RemoveTestDir(t)
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.Equal(t, tt.want, got)
+ }
+ })
}
- require.NotNil(t, stateSrv)
-
- kr, _ := keystore.NewSr25519Keyring()
- alice := kr.Alice().Public().(*sr25519.PublicKey).AsBytes()
-
- bal, err := stateSrv.Storage.GetStorage(nil, balanceKey(t, alice))
- require.NoError(t, err)
-
- genbal := "0x0000000000000001"
- expected, _ := common.HexToBytes(genbal)
- require.Equal(t, expected, bal)
}
-func TestNode_PersistGlobalName_WhenInitialize(t *testing.T) {
- globalName := RandomNodeName()
-
+func TestNodeInitialized(t *testing.T) {
cfg := NewTestConfig(t)
- cfg.Global.Name = globalName
require.NotNil(t, cfg)
- genPath := NewTestGenesisAndRuntime(t)
- require.NotNil(t, genPath)
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
- cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
- cfg.Init.Genesis = genPath
+ cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- storedName, err := LoadGlobalNodeName(cfg.Global.BasePath)
- require.Nil(t, err)
- require.Equal(t, globalName, storedName)
+ type args struct {
+ basepath string
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ }{
+ {
+ name: "blank base path",
+ args: args{basepath: ""},
+ want: false,
+ },
+ {
+ name: "working example",
+ args: args{basepath: cfg.Global.BasePath},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NodeInitialized(tt.args.basepath); got != tt.want {
+ t.Errorf("NodeInitialized() = %v, want %v", got, tt.want)
+ }
+ })
+ }
}
diff --git a/dot/services.go b/dot/services.go
index aacf37f279..e0173861f7 100644
--- a/dot/services.go
+++ b/dot/services.go
@@ -42,7 +42,7 @@ func newInMemoryDB(path string) (chaindb.Database, error) {
// State Service
// createStateService creates the state service and initialise state database
-func createStateService(cfg *Config) (*state.Service, error) {
+func (nodeInterface) createStateService(cfg *Config) (*state.Service, error) {
logger.Debug("creating state service...")
config := state.Config{
@@ -68,7 +68,7 @@ func createStateService(cfg *Config) (*state.Service, error) {
return stateSrvc, nil
}
-func createRuntimeStorage(st *state.Service) (*runtime.NodeStorage, error) {
+func (nodeInterface) createRuntimeStorage(st *state.Service) (*runtime.NodeStorage, error) {
localStorage, err := newInMemoryDB(st.DB().Path())
if err != nil {
return nil, err
@@ -112,6 +112,7 @@ func createRuntime(cfg *Config, ns runtime.NodeStorage, st *state.Service,
var rt runtime.Instance
switch cfg.Core.WasmInterpreter {
+ // TODO no default case to handle if cfg.Core.WasmInterpreter is not set or set incorrectly
case wasmer.Name:
rtCfg := &wasmer.Config{
Imports: wasmer.ImportsNodeRuntime,
@@ -159,7 +160,8 @@ func asAuthority(authority bool) string {
return ""
}
-func createBABEService(cfg *Config, st *state.Service, ks keystore.Keystore, cs *core.Service) (*babe.Service, error) {
+func (nodeInterface) createBABEService(cfg *Config, st *state.Service, ks keystore.Keystore,
+ cs *core.Service) (*babe.Service, error) {
logger.Info("creating BABE service" +
asAuthority(cfg.Core.BabeAuthority) + "...")
@@ -202,7 +204,7 @@ func createBABEService(cfg *Config, st *state.Service, ks keystore.Keystore, cs
// Core Service
// createCoreService creates the core service from the provided core configuration
-func createCoreService(cfg *Config, ks *keystore.GlobalKeystore,
+func (nodeInterface) createCoreService(cfg *Config, ks *keystore.GlobalKeystore,
st *state.Service, net *network.Service, dh *digest.Handler) (
*core.Service, error) {
logger.Debug("creating core service" +
@@ -246,7 +248,7 @@ func createCoreService(cfg *Config, ks *keystore.GlobalKeystore,
// Network Service
// createNetworkService creates a network service from the command configuration and genesis data
-func createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Service, error) {
+func (nodeInterface) createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Service, error) {
logger.Debugf(
"creating network service with roles %d, port %d, bootnodes %s, protocol ID %s, nobootstrap=%t and noMDNS=%t...",
cfg.Core.Roles, cfg.Network.Port, strings.Join(cfg.Network.Bootnodes, ","), cfg.Network.ProtocolID,
@@ -289,7 +291,7 @@ func createNetworkService(cfg *Config, stateSrvc *state.Service) (*network.Servi
// RPC Service
// createRPCService creates the RPC service from the provided core configuration
-func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service,
+func (nodeInterface) createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Service,
coreSrvc *core.Service, networkSrvc *network.Service, bp modules.BlockProducerAPI,
sysSrvc *system.Service, finSrvc *grandpa.Service) (*rpc.HTTPServer, error) {
logger.Infof(
@@ -340,7 +342,7 @@ func createRPCService(cfg *Config, ns *runtime.NodeStorage, stateSrvc *state.Ser
}
// createSystemService creates a systemService for providing system related information
-func createSystemService(cfg *types.SystemInfo, stateSrvc *state.Service) (*system.Service, error) {
+func (nodeInterface) createSystemService(cfg *types.SystemInfo, stateSrvc *state.Service) (*system.Service, error) {
genesisData, err := stateSrvc.Base.LoadGenesisData()
if err != nil {
return nil, err
@@ -350,7 +352,7 @@ func createSystemService(cfg *types.SystemInfo, stateSrvc *state.Service) (*syst
}
// createGRANDPAService creates a new GRANDPA service
-func createGRANDPAService(cfg *Config, st *state.Service, dh *digest.Handler,
+func (nodeInterface) createGRANDPAService(cfg *Config, st *state.Service, dh *digest.Handler,
ks keystore.Keystore, net *network.Service) (*grandpa.Service, error) {
rt, err := st.Block.GetRuntime(nil)
if err != nil {
@@ -391,7 +393,7 @@ func createGRANDPAService(cfg *Config, st *state.Service, dh *digest.Handler,
return grandpa.NewService(gsCfg)
}
-func createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
+func (nodeInterface) createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
ver, err := babe.NewVerificationManager(st.Block, st.Epoch)
if err != nil {
return nil, err
@@ -400,7 +402,7 @@ func createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
return ver, nil
}
-func newSyncService(cfg *Config, st *state.Service, fg sync.FinalityGadget,
+func (nodeInterface) newSyncService(cfg *Config, st *state.Service, fg sync.FinalityGadget,
verifier *babe.VerificationManager, cs *core.Service, net *network.Service) (
*sync.Service, error) {
slotDuration, err := st.Epoch.GetSlotDuration()
@@ -425,7 +427,7 @@ func newSyncService(cfg *Config, st *state.Service, fg sync.FinalityGadget,
return sync.NewService(syncCfg)
}
-func createDigestHandler(st *state.Service) (*digest.Handler, error) {
+func (nodeInterface) createDigestHandler(st *state.Service) (*digest.Handler, error) {
return digest.NewHandler(st.Block, st.Epoch, st.Grandpa)
}
diff --git a/dot/services_integration_test.go b/dot/services_integration_test.go
new file mode 100644
index 0000000000..e7687ad749
--- /dev/null
+++ b/dot/services_integration_test.go
@@ -0,0 +1,384 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "flag"
+ "net/url"
+ "testing"
+ "time"
+
+ "github.com/ChainSafe/gossamer/dot/network"
+ "github.com/ChainSafe/gossamer/dot/types"
+ "github.com/ChainSafe/gossamer/lib/grandpa"
+ "github.com/ChainSafe/gossamer/lib/keystore"
+ "github.com/ChainSafe/gossamer/lib/utils"
+
+ "github.com/gorilla/websocket"
+ "github.com/stretchr/testify/require"
+)
+
+// TestCreateStateService tests the createStateService method
+func TestCreateStateService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.Nil(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.Nil(t, err)
+ require.NotNil(t, stateSrvc)
+}
+
+// TestCreateCoreService tests the createCoreService method
+func TestCreateCoreService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ require.NotNil(t, ks)
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
+
+ networkSrvc := &network.Service{}
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ coreSrvc, err := nodeI.createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ require.NoError(t, err)
+ require.NotNil(t, coreSrvc)
+}
+
+func TestCreateBlockVerifier(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ _, err = nodeI.createBlockVerifier(stateSrvc)
+ require.NoError(t, err)
+}
+
+func TestCreateSyncService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ require.NotNil(t, ks)
+
+ ver, err := nodeI.createBlockVerifier(stateSrvc)
+ require.NoError(t, err)
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ coreSrvc, err := nodeI.createCoreService(cfg, ks, stateSrvc, &network.Service{}, dh)
+ require.NoError(t, err)
+
+ _, err = nodeI.newSyncService(cfg, stateSrvc, &grandpa.Service{}, ver, coreSrvc, &network.Service{})
+ require.NoError(t, err)
+}
+
+// TestCreateNetworkService tests the createNetworkService method
+func TestCreateNetworkService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ networkSrvc, err := nodeI.createNetworkService(cfg, stateSrvc)
+ require.NoError(t, err)
+ require.NotNil(t, networkSrvc)
+}
+
+// TestCreateRPCService tests the createRPCService method
+func TestCreateRPCService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ networkSrvc := &network.Service{}
+
+ ks := keystore.NewGlobalKeystore()
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
+
+ ns, err := nodeI.createRuntimeStorage(stateSrvc)
+ require.NoError(t, err)
+ err = nodeI.loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
+ require.NoError(t, err)
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ coreSrvc, err := nodeI.createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ require.NoError(t, err)
+
+ sysSrvc, err := nodeI.createSystemService(&cfg.System, stateSrvc)
+ require.NoError(t, err)
+
+ rpcSrvc, err := nodeI.createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil)
+ require.NoError(t, err)
+ require.NotNil(t, rpcSrvc)
+}
+
+func TestCreateBABEService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ kr, err := keystore.NewSr25519Keyring()
+ require.NoError(t, err)
+ ks.Babe.Insert(kr.Alice())
+
+ ns, err := nodeI.createRuntimeStorage(stateSrvc)
+ require.NoError(t, err)
+ err = nodeI.loadRuntime(cfg, ns, stateSrvc, ks, &network.Service{})
+ require.NoError(t, err)
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ coreSrvc, err := nodeI.createCoreService(cfg, ks, stateSrvc, &network.Service{}, dh)
+ require.NoError(t, err)
+
+ bs, err := nodeI.createBABEService(cfg, stateSrvc, ks.Babe, coreSrvc)
+ require.NoError(t, err)
+ require.NotNil(t, bs)
+}
+
+func TestCreateGrandpaService(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.AuthorityRole
+ cfg.Init.Genesis = genFile.Name()
+
+ err := InitNode(cfg)
+ require.NoError(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.NoError(t, err)
+
+ ks := keystore.NewGlobalKeystore()
+ kr, err := keystore.NewEd25519Keyring()
+ require.NoError(t, err)
+ ks.Gran.Insert(kr.Alice())
+
+ ns, err := nodeI.createRuntimeStorage(stateSrvc)
+ require.NoError(t, err)
+
+ err = nodeI.loadRuntime(cfg, ns, stateSrvc, ks, &network.Service{})
+ require.NoError(t, err)
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ gs, err := nodeI.createGRANDPAService(cfg, stateSrvc, dh, ks.Gran, &network.Service{})
+ require.NoError(t, err)
+ require.NotNil(t, gs)
+}
+
+var addr = flag.String("addr", "localhost:8546", "http service address")
+var testCalls = []struct {
+ call []byte
+ expected []byte
+}{
+ {[]byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`), []byte(`{"id":1,"jsonrpc":"2.0",
+"result":"gossamer"}` + "\n")}, // working request
+ {[]byte(`{"jsonrpc":"2.0","method":"unknown","params":[],"id":2}`), []byte(`{"error":{"code":-32000,"data":null,
+"message":"rpc error method unknown not found"},"id":2,"jsonrpc":"2.0"}` + "\n")}, // unknown method
+ {[]byte{}, []byte(`{"jsonrpc":"2.0","error":{"code":-32600,"message":"Invalid request"},"id":0}` + "\n")},
+ // empty request
+ {[]byte(`{"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":[],"id":3}`), []byte(`{"jsonrpc":"2.0",
+"result":1,"id":3}` + "\n")},
+ {[]byte(`{"jsonrpc":"2.0","method":"state_subscribeStorage","params":[],"id":4}`), []byte(`{"jsonrpc":"2.0",
+"result":2,"id":4}` + "\n")},
+}
+
+func TestNewWebSocketServer(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
+ cfg.Init.Genesis = genFile.Name()
+ cfg.RPC.External = false
+ cfg.RPC.WS = true
+ cfg.RPC.WSExternal = false
+ cfg.System.SystemName = "gossamer"
+
+ err := InitNode(cfg)
+ require.Nil(t, err)
+
+ nodeI := nodeInterface{}
+ stateSrvc, err := nodeI.createStateService(cfg)
+ require.Nil(t, err)
+
+ networkSrvc := &network.Service{}
+
+ ks := keystore.NewGlobalKeystore()
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
+
+ ns, err := nodeI.createRuntimeStorage(stateSrvc)
+ require.NoError(t, err)
+ err = nodeI.loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
+ require.NoError(t, err)
+
+ dh, err := nodeI.createDigestHandler(stateSrvc)
+ require.NoError(t, err)
+
+ coreSrvc, err := nodeI.createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ require.Nil(t, err)
+
+ sysSrvc, err := nodeI.createSystemService(&cfg.System, stateSrvc)
+ require.NoError(t, err)
+
+ rpcSrvc, err := nodeI.createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil)
+ require.NoError(t, err)
+ err = rpcSrvc.Start()
+ require.Nil(t, err)
+
+ time.Sleep(time.Second) // give server a second to start
+
+ u := url.URL{Scheme: "ws", Host: *addr, Path: "/"}
+
+ c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
+ require.NoError(t, err)
+ defer c.Close()
+
+ for _, item := range testCalls {
+ err = c.WriteMessage(websocket.TextMessage, item.call)
+ require.Nil(t, err)
+
+ _, message, err := c.ReadMessage()
+ require.Nil(t, err)
+ require.Equal(t, item.expected, message)
+ }
+}
diff --git a/dot/services_test.go b/dot/services_test.go
index b1a939a38a..7f225c8c36 100644
--- a/dot/services_test.go
+++ b/dot/services_test.go
@@ -4,371 +4,823 @@
package dot
import (
- "flag"
- "net/url"
+ "errors"
+ "io/ioutil"
+ "path/filepath"
"testing"
- "time"
+ "github.com/ChainSafe/gossamer/dot/core"
+ "github.com/ChainSafe/gossamer/dot/digest"
"github.com/ChainSafe/gossamer/dot/network"
+ "github.com/ChainSafe/gossamer/dot/rpc"
+ "github.com/ChainSafe/gossamer/dot/rpc/modules"
+ "github.com/ChainSafe/gossamer/dot/state"
+ "github.com/ChainSafe/gossamer/dot/sync"
+ "github.com/ChainSafe/gossamer/dot/system"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/internal/pprof"
+ "github.com/ChainSafe/gossamer/lib/babe"
+ "github.com/ChainSafe/gossamer/lib/crypto"
"github.com/ChainSafe/gossamer/lib/grandpa"
"github.com/ChainSafe/gossamer/lib/keystore"
+ "github.com/ChainSafe/gossamer/lib/runtime"
+ "github.com/ChainSafe/gossamer/lib/runtime/wasmer"
"github.com/ChainSafe/gossamer/lib/utils"
-
- "github.com/gorilla/websocket"
+ "github.com/golang/mock/gomock"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
-// TestCreateStateService tests the createStateService method
-func TestCreateStateService(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
-
- err := InitNode(cfg)
- require.Nil(t, err)
-
- stateSrvc, err := createStateService(cfg)
- require.Nil(t, err)
- require.NotNil(t, stateSrvc)
-}
+func Test_createBABEService(t *testing.T) {
+ t.Parallel()
-// TestCreateCoreService tests the createCoreService method
-func TestCreateCoreService(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
ks := keystore.NewGlobalKeystore()
- require.NotNil(t, ks)
- ed25519Keyring, _ := keystore.NewEd25519Keyring()
- ks.Gran.Insert(ed25519Keyring.Alice())
+ kr, err := keystore.NewSr25519Keyring()
+ require.NoError(t, err)
+ ks.Babe.Insert(kr.Alice())
- networkSrvc := &network.Service{}
+ ns, err := ni.createRuntimeStorage(stateSrvc)
+ require.NoError(t, err)
+ err = ni.loadRuntime(cfg, ns, stateSrvc, ks, &network.Service{})
+ require.NoError(t, err)
- dh, err := createDigestHandler(stateSrvc)
+ dh, err := ni.createDigestHandler(stateSrvc)
require.NoError(t, err)
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ coreSrvc, err := ni.createCoreService(cfg, ks, stateSrvc, &network.Service{}, dh)
require.NoError(t, err)
- require.NotNil(t, coreSrvc)
+
+ type args struct {
+ cfg *Config
+ st *state.Service
+ ks keystore.Keystore
+ cs *core.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *babe.Service
+ err error
+ }{
+ {
+ name: "invalid keystore type test",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ ks: ks.Gran,
+ cs: coreSrvc,
+ },
+ err: errors.New("invalid keystore type"),
+ },
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ ks: ks.Babe,
+ cs: coreSrvc,
+ },
+ want: &babe.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createBABEService(tt.args.cfg, tt.args.st, tt.args.ks, tt.args.cs)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-func TestCreateBlockVerifier(t *testing.T) {
+func Test_createBlockVerifier(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- _, err = createBlockVerifier(stateSrvc)
- require.NoError(t, err)
+ type args struct {
+ st *state.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *babe.VerificationManager
+ err error
+ }{
+ {
+ name: "nil BlockState test",
+ args: args{st: &state.Service{}},
+ err: errors.New("cannot have nil BlockState"),
+ },
+ {
+ name: "working example",
+ args: args{st: stateSrvc},
+ want: &babe.VerificationManager{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createBlockVerifier(tt.args.st)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-func TestCreateSyncService(t *testing.T) {
+func Test_createCoreService(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
- genFile := NewTestGenesisFile(t, cfg)
- require.NotNil(t, genFile)
+ genFile := NewTestGenesisRawFile(t, cfg)
defer utils.RemoveTestDir(t)
+ cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
- require.NoError(t, err)
-
- ks := keystore.NewGlobalKeystore()
- require.NotNil(t, ks)
-
- ver, err := createBlockVerifier(stateSrvc)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- dh, err := createDigestHandler(stateSrvc)
+ networkSrvc, err := ni.createNetworkService(cfg, stateSrvc)
require.NoError(t, err)
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, &network.Service{}, dh)
- require.NoError(t, err)
+ ks := keystore.NewGlobalKeystore()
+ require.NotNil(t, ks)
+ ed25519Keyring, _ := keystore.NewEd25519Keyring()
+ ks.Gran.Insert(ed25519Keyring.Alice())
- _, err = newSyncService(cfg, stateSrvc, &grandpa.Service{}, ver, coreSrvc, &network.Service{})
- require.NoError(t, err)
+ type args struct {
+ cfg *Config
+ ks *keystore.GlobalKeystore
+ st *state.Service
+ net *network.Service
+ dh *digest.Handler
+ }
+ tests := []struct {
+ name string
+ args args
+ want *core.Service
+ err error
+ }{
+ {
+ name: "missing keystore test",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ },
+ err: errors.New("cannot have nil keystore"),
+ },
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ ks: ks,
+ st: stateSrvc,
+ net: networkSrvc,
+ },
+ want: &core.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createCoreService(tt.args.cfg, tt.args.ks, tt.args.st, tt.args.net, tt.args.dh)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-// TestCreateNetworkService tests the createNetworkService method
-func TestCreateNetworkService(t *testing.T) {
+func Test_createDigestHandler(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
+ genFile := NewTestGenesisFile(t, cfg)
defer utils.RemoveTestDir(t)
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- networkSrvc, err := createNetworkService(cfg, stateSrvc)
- require.NoError(t, err)
- require.NotNil(t, networkSrvc)
+ type args struct {
+ st *state.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *digest.Handler
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{st: stateSrvc},
+ want: &digest.Handler{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createDigestHandler(tt.args.st)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-// TestCreateRPCService tests the createRPCService method
-func TestCreateRPCService(t *testing.T) {
+func Test_createGRANDPAService(t *testing.T) {
+ ctrl := gomock.NewController(t)
+ defer ctrl.Finish()
+
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
- cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
+ cfg.Core.Roles = types.AuthorityRole
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ks := keystore.NewGlobalKeystore()
+ kr, err := keystore.NewEd25519Keyring()
require.NoError(t, err)
+ ks.Gran.Insert(kr.Alice())
- stateSrvc, err := createStateService(cfg)
- require.NoError(t, err)
+ type args struct {
+ cfg *Config
+ st *state.Service
+ dh *digest.Handler
+ ks keystore.Keystore
+ net *network.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *grandpa.Service
+ err error
+ }{
+ {
+ name: "invalid key type test",
+ args: args{
+ cfg: cfg,
+ ks: ks.Babe,
+ },
+ err: errors.New("invalid keystore type"),
+ },
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ ks: ks.Gran,
+ },
+ want: &grandpa.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mockNodeIface := NewMocknewNodeIface(ctrl)
+ mockNodeIface.EXPECT().createGRANDPAService(tt.args.cfg, nil, nil, tt.args.ks,
+ nil).DoAndReturn(func(cfg *Config, st *state.Service, dh *digest.Handler, ks keystore.Keystore,
+ net *network.Service) (*grandpa.Service, error) {
+ if ks.Name() != "gran" || ks.Type() != crypto.Ed25519Type {
+ return nil, ErrInvalidKeystoreType
+ }
+ return &grandpa.Service{}, nil
+ })
+ got, err := mockNodeIface.createGRANDPAService(tt.args.cfg, tt.args.st, tt.args.dh, tt.args.ks, tt.args.net)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
+}
- networkSrvc := &network.Service{}
+func Test_createNetworkService(t *testing.T) {
+ cfg := NewTestConfig(t)
- ks := keystore.NewGlobalKeystore()
- ed25519Keyring, _ := keystore.NewEd25519Keyring()
- ks.Gran.Insert(ed25519Keyring.Alice())
+ genFile := NewTestGenesisRawFile(t, cfg)
- ns, err := createRuntimeStorage(stateSrvc)
- require.NoError(t, err)
- err = loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
- require.NoError(t, err)
+ defer utils.RemoveTestDir(t)
- dh, err := createDigestHandler(stateSrvc)
- require.NoError(t, err)
+ cfg.Init.Genesis = genFile.Name()
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- sysSrvc, err := createSystemService(&cfg.System, stateSrvc)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil)
- require.NoError(t, err)
- require.NotNil(t, rpcSrvc)
+ type args struct {
+ cfg *Config
+ stateSrvc *state.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *network.Service
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ stateSrvc: stateSrvc,
+ },
+ want: &network.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createNetworkService(tt.args.cfg, tt.args.stateSrvc)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-func TestCreateBABEService(t *testing.T) {
+func Test_createRPCService(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
cfg.Core.Roles = types.FullNodeRole
+ cfg.Core.BabeAuthority = false
+ cfg.Core.GrandpaAuthority = false
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- ks := keystore.NewGlobalKeystore()
- kr, err := keystore.NewSr25519Keyring()
- require.NoError(t, err)
- ks.Babe.Insert(kr.Alice())
+ type args struct {
+ cfg *Config
+ ns *runtime.NodeStorage
+ stateSrvc *state.Service
+ coreSrvc *core.Service
+ networkSrvc *network.Service
+ bp modules.BlockProducerAPI
+ sysSrvc *system.Service
+ finSrvc *grandpa.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *rpc.HTTPServer
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ stateSrvc: stateSrvc,
+ },
+ want: &rpc.HTTPServer{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createRPCService(tt.args.cfg, tt.args.ns, tt.args.stateSrvc, tt.args.coreSrvc,
+ tt.args.networkSrvc, tt.args.bp, tt.args.sysSrvc, tt.args.finSrvc)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
+}
- ns, err := createRuntimeStorage(stateSrvc)
- require.NoError(t, err)
- err = loadRuntime(cfg, ns, stateSrvc, ks, &network.Service{})
- require.NoError(t, err)
+func Test_createRuntime(t *testing.T) {
+ cfg := NewTestConfig(t)
- dh, err := createDigestHandler(stateSrvc)
- require.NoError(t, err)
+ genFile := NewTestGenesisRawFile(t, cfg)
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, &network.Service{}, dh)
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- bs, err := createBABEService(cfg, stateSrvc, ks.Babe, coreSrvc)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- require.NotNil(t, bs)
+
+ _ = wasmer.NewTestInstance(t, runtime.NODE_RUNTIME)
+ runtimeFilePath := runtime.GetAbsolutePath(runtime.NODE_RUNTIME_FP)
+
+ runtimeData, err := ioutil.ReadFile(filepath.Clean(runtimeFilePath))
+ require.Nil(t, err)
+
+ type args struct {
+ cfg *Config
+ ns runtime.NodeStorage
+ st *state.Service
+ ks *keystore.GlobalKeystore
+ net *network.Service
+ code []byte
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ err error
+ }{
+ {
+ name: "empty code test",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ },
+ err: errors.New("failed to create runtime executor: code is empty"),
+ },
+ {
+ name: "bad code test",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ code: []byte(`fake code`),
+ },
+ err: errors.New("failed to create runtime executor: Failed to instantiate the module:\n compile error" +
+ ": Validation error \"Bad magic number\""),
+ },
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ code: runtimeData,
+ },
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := createRuntime(tt.args.cfg, tt.args.ns, tt.args.st, tt.args.ks, tt.args.net, tt.args.code)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-func TestCreateGrandpaService(t *testing.T) {
+func Test_createRuntimeStorage(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
- cfg.Core.Roles = types.AuthorityRole
cfg.Init.Genesis = genFile.Name()
- err := InitNode(cfg)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- stateSrvc, err := createStateService(cfg)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- ks := keystore.NewGlobalKeystore()
- kr, err := keystore.NewEd25519Keyring()
- require.NoError(t, err)
- ks.Gran.Insert(kr.Alice())
+ type args struct {
+ st *state.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *runtime.NodeStorage
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{st: stateSrvc},
+ want: &runtime.NodeStorage{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createRuntimeStorage(tt.args.st)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
+}
- ns, err := createRuntimeStorage(stateSrvc)
- require.NoError(t, err)
+func Test_createStateService(t *testing.T) {
+ cfg := NewTestConfig(t)
- err = loadRuntime(cfg, ns, stateSrvc, ks, &network.Service{})
- require.NoError(t, err)
+ genFile := NewTestGenesisRawFile(t, cfg)
- dh, err := createDigestHandler(stateSrvc)
- require.NoError(t, err)
+ defer utils.RemoveTestDir(t)
- networkSrvc, err := createNetworkService(cfg, stateSrvc)
- require.NoError(t, err)
+ cfg.Init.Genesis = genFile.Name()
- gs, err := createGRANDPAService(cfg, stateSrvc, dh, ks.Gran, networkSrvc)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- require.NotNil(t, gs)
-}
-var addr = flag.String("addr", "localhost:8546", "http service address")
-var testCalls = []struct {
- call []byte
- expected []byte
-}{
- {
- call: []byte(`{"jsonrpc":"2.0","method":"system_name","params":[],"id":1}`),
- expected: []byte(`{"id":1,"jsonrpc":"2.0","result":"gossamer"}` + "\n")}, // working request
- {
- call: []byte(`{"jsonrpc":"2.0","method":"unknown","params":[],"id":2}`),
- // unknown method
- expected: []byte(`{"error":{"code":-32000,"data":null,` +
- `"message":"rpc error method unknown not found"},"id":2,` +
- `"jsonrpc":"2.0"}` + "\n")},
- {
- call: []byte{},
- // empty request
- expected: []byte(`{"jsonrpc":"2.0","error":{"code":-32600,` +
- `"message":"Invalid request"},"id":0}` + "\n")},
- {
- call: []byte(`{"jsonrpc":"2.0","method":"chain_subscribeNewHeads","params":[],"id":3}`),
- expected: []byte(`{"jsonrpc":"2.0","result":1,"id":3}` + "\n")},
- {
- call: []byte(`{"jsonrpc":"2.0","method":"state_subscribeStorage","params":[],"id":4}`),
- expected: []byte(`{"jsonrpc":"2.0","result":2,"id":4}` + "\n")},
+ cfg2 := NewTestConfig(t)
+ cfg2.Global.BasePath = "test_data"
+
+ type args struct {
+ cfg *Config
+ }
+ tests := []struct {
+ name string
+ args args
+ want *state.Service
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{cfg: cfg},
+ want: &state.Service{},
+ },
+ {
+ name: "broken config test",
+ args: args{cfg: cfg2},
+ err: errors.New("failed to start state service: failed to create block state: cannot get block 0: Key not found"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createStateService(tt.args.cfg)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
}
-func TestNewWebSocketServer(t *testing.T) {
+func Test_createSystemService(t *testing.T) {
cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
defer utils.RemoveTestDir(t)
- cfg.Core.Roles = types.FullNodeRole
- cfg.Core.BabeAuthority = false
- cfg.Core.GrandpaAuthority = false
cfg.Init.Genesis = genFile.Name()
- cfg.RPC.External = false
- cfg.RPC.WS = true
- cfg.RPC.WSExternal = false
- cfg.System.SystemName = "gossamer"
- err := InitNode(cfg)
- require.Nil(t, err)
-
- stateSrvc, err := createStateService(cfg)
- require.Nil(t, err)
-
- networkSrvc := &network.Service{}
-
- ks := keystore.NewGlobalKeystore()
- ed25519Keyring, _ := keystore.NewEd25519Keyring()
- ks.Gran.Insert(ed25519Keyring.Alice())
-
- ns, err := createRuntimeStorage(stateSrvc)
- require.NoError(t, err)
- err = loadRuntime(cfg, ns, stateSrvc, ks, networkSrvc)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- dh, err := createDigestHandler(stateSrvc)
+ stateSrvc, err := ni.createStateService(cfg)
require.NoError(t, err)
- coreSrvc, err := createCoreService(cfg, ks, stateSrvc, networkSrvc, dh)
- require.Nil(t, err)
+ type args struct {
+ cfg *types.SystemInfo
+ stateSrvc *state.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *system.Service
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{
+ stateSrvc: stateSrvc,
+ },
+ want: &system.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.createSystemService(tt.args.cfg, tt.args.stateSrvc)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
+}
- sysSrvc, err := createSystemService(&cfg.System, stateSrvc)
- require.NoError(t, err)
+func Test_newInMemoryDB(t *testing.T) {
+ type args struct {
+ path string
+ }
+ tests := []struct {
+ name string
+ args args
+ want bool
+ err error
+ }{
+ {
+ name: "working example",
+ args: args{path: "test_data"},
+ want: true,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := newInMemoryDB(tt.args.path)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
+ }
+}
- rpcSrvc, err := createRPCService(cfg, ns, stateSrvc, coreSrvc, networkSrvc, nil, sysSrvc, nil)
- require.NoError(t, err)
- err = rpcSrvc.Start()
- require.Nil(t, err)
+func Test_newSyncService(t *testing.T) {
+ cfg := NewTestConfig(t)
+
+ genFile := NewTestGenesisFile(t, cfg)
- time.Sleep(time.Second) // give server a second to start
+ defer utils.RemoveTestDir(t)
- u := url.URL{Scheme: "ws", Host: *addr, Path: "/"}
+ cfg.Init.Genesis = genFile.Name()
- c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
+ ni := nodeInterface{}
+ err := ni.initNode(cfg)
require.NoError(t, err)
- defer c.Close()
- for _, item := range testCalls {
- err = c.WriteMessage(websocket.TextMessage, item.call)
- require.Nil(t, err)
+ stateSrvc, err := ni.createStateService(cfg)
+ require.NoError(t, err)
- _, message, err := c.ReadMessage()
- require.Nil(t, err)
- require.Equal(t, item.expected, message)
+ type args struct {
+ cfg *Config
+ st *state.Service
+ fg sync.FinalityGadget
+ verifier *babe.VerificationManager
+ cs *core.Service
+ net *network.Service
+ }
+ tests := []struct {
+ name string
+ args args
+ want *sync.Service
+ err error
+ }{
+ {
+ name: "missing FinalityGadget test",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ },
+ err: errors.New("cannot have nil FinalityGadget"),
+ },
+ {
+ name: "working example",
+ args: args{
+ cfg: cfg,
+ st: stateSrvc,
+ fg: &grandpa.Service{},
+ },
+ want: &sync.Service{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := ni.newSyncService(tt.args.cfg, tt.args.st, tt.args.fg, tt.args.verifier, tt.args.cs, tt.args.net)
+ if tt.err != nil {
+ assert.EqualError(t, err, tt.err.Error())
+ } else {
+ assert.NoError(t, err)
+ }
+
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ } else {
+ assert.Nil(t, got)
+ }
+ })
}
}
diff --git a/dot/utils_integration_test.go b/dot/utils_integration_test.go
new file mode 100644
index 0000000000..baa78183ab
--- /dev/null
+++ b/dot/utils_integration_test.go
@@ -0,0 +1,198 @@
+//go:build integration
+// +build integration
+
+// Copyright 2020 ChainSafe Systems (ON) Corp.
+// This file is part of gossamer.
+//
+// The gossamer library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The gossamer library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the gossamer library. If not, see .
+
+package dot
+
+import (
+ "log"
+ "os"
+ "runtime"
+ "testing"
+ "time"
+
+ "github.com/ChainSafe/gossamer/lib/genesis"
+ "github.com/ChainSafe/gossamer/lib/trie"
+ "github.com/ChainSafe/gossamer/lib/utils"
+ "github.com/stretchr/testify/require"
+)
+
+// TestNewConfig tests the NewTestConfig method
+func TestNewConfig(t *testing.T) {
+ cfg := NewTestConfig(t)
+ defer utils.RemoveTestDir(t)
+ require.NotNil(t, cfg)
+}
+
+// TestNewConfigAndFile tests the NewTestConfigWithFile method
+func TestNewConfigAndFile(t *testing.T) {
+ testCfg, testCfgFile := NewTestConfigWithFile(t)
+ defer utils.RemoveTestDir(t)
+ require.NotNil(t, testCfg)
+ require.NotNil(t, testCfgFile)
+}
+
+// TestInitNode
+func TestNewTestGenesis_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genFile)
+
+ defer utils.RemoveTestDir(t)
+
+ cfg.Init.Genesis = genFile.Name()
+}
+
+func TestNewTestGenesisFile_Integration(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genHRFile := NewTestGenesisFile(t, cfg)
+ require.NotNil(t, genHRFile)
+ defer os.Remove(genHRFile.Name())
+
+ genRawFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genRawFile)
+ defer os.Remove(genRawFile.Name())
+
+ genHR, err := genesis.NewGenesisFromJSON(genHRFile.Name(), 0)
+ require.NoError(t, err)
+ genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
+ require.NoError(t, err)
+
+ // values from raw genesis file should equal values generated from human readable genesis file
+ require.Equal(t, genRaw.Genesis.Raw["top"], genHR.Genesis.Raw["top"])
+}
+
+func TestDeepCopyVsSnapshot(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genRawFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genRawFile)
+
+ defer os.Remove(genRawFile.Name())
+
+ genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
+ require.NoError(t, err)
+
+ tri := trie.NewEmptyTrie()
+ var ttlLenght int
+ for k, v := range genRaw.Genesis.Raw["top"] {
+ val := []byte(v)
+ ttlLenght += len(val)
+ tri.Put([]byte(k), val)
+ }
+
+ testCases := []struct {
+ name string
+ fn func(tri *trie.Trie) (*trie.Trie, error)
+ }{
+ {"DeepCopy", func(tri *trie.Trie) (*trie.Trie, error) {
+ return tri.DeepCopy()
+ }},
+ {"Snapshot", func(tri *trie.Trie) (*trie.Trie, error) {
+ return tri.Snapshot(), nil
+ }},
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ trieMap := make(map[int]*trie.Trie)
+ start := time.Now()
+ var m runtime.MemStats
+ for i := 0; i <= 200; i++ {
+ newTrie, err := tc.fn(tri)
+ require.NoError(t, err)
+
+ runtime.ReadMemStats(&m)
+ trieMap[i] = newTrie
+ }
+
+ log.Printf("\nAlloc = %v MB \nTotalAlloc = %v MB \nSys = %v MB \nNumGC = %v \n\n", m.Alloc/(1024*1024),
+ m.TotalAlloc/(1024*1024), m.Sys/(1024*1024), m.NumGC)
+ elapsed := time.Since(start)
+ log.Printf("DeepCopy to trie took %s", elapsed)
+ runtime.GC()
+ })
+ }
+}
+
+func TestTrieSnapshot(t *testing.T) {
+ cfg := NewTestConfig(t)
+ require.NotNil(t, cfg)
+
+ genRawFile := NewTestGenesisRawFile(t, cfg)
+ require.NotNil(t, genRawFile)
+
+ defer os.Remove(genRawFile.Name())
+
+ genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
+ require.NoError(t, err)
+
+ tri := trie.NewEmptyTrie()
+ key := []byte("key")
+ value := []byte("value")
+
+ for k, v := range genRaw.Genesis.Raw["top"] {
+ val := []byte(v)
+ tri.Put([]byte(k), val)
+ }
+
+ // DeepCopy the trie.
+ dcTrie, err := tri.DeepCopy()
+ require.NoError(t, err)
+
+ // Take Snapshot of the trie.
+ newTrie := tri.Snapshot()
+
+ // Get the Trie root hash for all the 3 tries.
+ tHash, err := tri.Hash()
+ require.NoError(t, err)
+
+ dcTrieHash, err := dcTrie.Hash()
+ require.NoError(t, err)
+
+ newTrieHash, err := newTrie.Hash()
+ require.NoError(t, err)
+
+ // Root hash for the 3 tries should be equal.
+ require.Equal(t, tHash, dcTrieHash)
+ require.Equal(t, tHash, newTrieHash)
+
+ // Modify the current trie.
+ value[0] = 'w'
+ newTrie.Put(key, value)
+
+ // Get the updated root hash of all tries.
+ tHash, err = tri.Hash()
+ require.NoError(t, err)
+
+ dcTrieHash, err = dcTrie.Hash()
+ require.NoError(t, err)
+
+ newTrieHash, err = newTrie.Hash()
+ require.NoError(t, err)
+
+ // Only the current trie should have a different root hash since it is updated.
+ require.NotEqual(t, newTrieHash, dcTrieHash)
+ require.NotEqual(t, newTrieHash, tHash)
+ require.Equal(t, dcTrieHash, tHash)
+}
diff --git a/dot/utils_test.go b/dot/utils_test.go
index 1d66a46efc..0ce7bd8f24 100644
--- a/dot/utils_test.go
+++ b/dot/utils_test.go
@@ -4,179 +4,426 @@
package dot
import (
- "log"
"os"
- "runtime"
+ "strings"
"testing"
- "time"
+ ctoml "github.com/ChainSafe/gossamer/dot/config/toml"
+ "github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/genesis"
- "github.com/ChainSafe/gossamer/lib/trie"
- "github.com/ChainSafe/gossamer/lib/utils"
- "github.com/stretchr/testify/require"
+ "github.com/stretchr/testify/assert"
)
-// TestNewConfig tests the NewTestConfig method
-func TestNewConfig(t *testing.T) {
- cfg := NewTestConfig(t)
- defer utils.RemoveTestDir(t)
- require.NotNil(t, cfg)
+func TestCreateJSONRawFile(t *testing.T) {
+ type args struct {
+ bs *BuildSpec
+ fp string
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ bs: &BuildSpec{genesis: NewTestGenesis(t)},
+ fp: "test_data/test.json",
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := CreateJSONRawFile(tt.args.bs, tt.args.fp)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
}
-// TestNewConfigAndFile tests the NewTestConfigWithFile method
-func TestNewConfigAndFile(t *testing.T) {
- testCfg, testCfgFile := NewTestConfigWithFile(t)
- defer utils.RemoveTestDir(t)
- require.NotNil(t, testCfg)
- require.NotNil(t, testCfgFile)
+func TestExportConfig(t *testing.T) {
+ type args struct {
+ cfg *Config
+ fp string
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ cfg: &Config{},
+ fp: "test_data/test.json",
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := ExportConfig(tt.args.cfg, tt.args.fp)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
}
-// TestInitNode
-func TestNewTestGenesis(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genFile)
-
- defer utils.RemoveTestDir(t)
-
- cfg.Init.Genesis = genFile.Name()
+func TestExportTomlConfig(t *testing.T) {
+ type args struct {
+ cfg *ctoml.Config
+ fp string
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ cfg: &ctoml.Config{},
+ fp: "test_data/test.json",
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := ExportTomlConfig(tt.args.cfg, tt.args.fp)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
}
-func TestNewTestGenesisFile(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genHRFile := NewTestGenesisFile(t, cfg)
- require.NotNil(t, genHRFile)
- defer os.Remove(genHRFile.Name())
-
- genRawFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genRawFile)
- defer os.Remove(genRawFile.Name())
-
- genHR, err := genesis.NewGenesisFromJSON(genHRFile.Name(), 0)
- require.NoError(t, err)
- genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
- require.NoError(t, err)
-
- // values from raw genesis file should equal values generated from human readable genesis file
- require.Equal(t, genRaw.Genesis.Raw["top"], genHR.Genesis.Raw["top"])
+func TestNewTestConfig(t *testing.T) {
+ type args struct {
+ t *testing.T
+ }
+ tests := []struct {
+ name string
+ args args
+ want *Config
+ }{
+ {
+ name: "working example",
+ args: args{t: t},
+ want: &Config{
+ Global: GlobalConfig{
+ Name: "Gossamer",
+ ID: "gssmr",
+ BasePath: "test_data/TestNewTestConfig",
+ LogLvl: 3,
+ PublishMetrics: false,
+ MetricsPort: 0,
+ NoTelemetry: false,
+ TelemetryURLs: nil,
+ RetainBlocks: 0,
+ Pruning: "",
+ },
+ Log: LogConfig{
+ CoreLvl: 3,
+ SyncLvl: 3,
+ NetworkLvl: 3,
+ RPCLvl: 3,
+ StateLvl: 3,
+ RuntimeLvl: 3,
+ BlockProducerLvl: 3,
+ FinalityGadgetLvl: 3,
+ },
+ Init: InitConfig{Genesis: "./chain/gssmr/genesis-spec.json"},
+ Core: CoreConfig{
+ Roles: 4,
+ BabeAuthority: true,
+ BABELead: false,
+ GrandpaAuthority: true,
+ WasmInterpreter: "wasmer",
+ GrandpaInterval: 1000000000,
+ },
+ Network: NetworkConfig{
+ Port: 7001,
+ Bootnodes: nil,
+ ProtocolID: "",
+ NoBootstrap: false,
+ NoMDNS: false,
+ MinPeers: 1,
+ MaxPeers: 50,
+ PersistentPeers: nil,
+ DiscoveryInterval: 10000000000,
+ },
+ RPC: RPCConfig{
+ Enabled: false,
+ External: false,
+ Unsafe: false,
+ UnsafeExternal: false,
+ Port: 8545,
+ Host: "localhost",
+ Modules: []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain",
+ "childstate", "syncstate", "payment"},
+ WSPort: 8546,
+ WS: false,
+ WSExternal: false,
+ WSUnsafe: false,
+ WSUnsafeExternal: false,
+ },
+ System: types.SystemInfo{},
+ State: StateConfig{},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := NewTestConfig(tt.args.t)
+ if tt.want != nil {
+ assert.Equal(t, tt.want, got)
+ assert.NotNil(t, got)
+ }
+ })
+ }
}
-func TestDeepCopyVsSnapshot(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genRawFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genRawFile)
-
- defer os.Remove(genRawFile.Name())
-
- genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
- require.NoError(t, err)
+func TestNewTestConfigWithFile(t *testing.T) {
+ type args struct {
+ t *testing.T
+ }
+ tests := []struct {
+ name string
+ args args
+ want *Config
+ want1 *os.File
+ }{
+ {
+ name: "working example",
+ args: args{t: t},
+ want: &Config{
+ Global: GlobalConfig{
+ Name: "Gossamer",
+ ID: "gssmr",
+ BasePath: "test_data/TestNewTestConfigWithFile",
+ LogLvl: 3,
+ PublishMetrics: false,
+ MetricsPort: 0,
+ NoTelemetry: false,
+ TelemetryURLs: nil,
+ RetainBlocks: 0,
+ Pruning: "",
+ },
+ Log: LogConfig{
+ CoreLvl: 3,
+ SyncLvl: 3,
+ NetworkLvl: 3,
+ RPCLvl: 3,
+ StateLvl: 3,
+ RuntimeLvl: 3,
+ BlockProducerLvl: 3,
+ FinalityGadgetLvl: 3,
+ },
+ Init: InitConfig{Genesis: "./chain/gssmr/genesis-spec.json"},
+ Core: CoreConfig{
+ Roles: 4,
+ BabeAuthority: true,
+ BABELead: false,
+ GrandpaAuthority: true,
+ WasmInterpreter: "wasmer",
+ GrandpaInterval: 1000000000,
+ },
+ Network: NetworkConfig{
+ Port: 7001,
+ Bootnodes: nil,
+ ProtocolID: "",
+ NoBootstrap: false,
+ NoMDNS: false,
+ MinPeers: 1,
+ MaxPeers: 50,
+ PersistentPeers: nil,
+ DiscoveryInterval: 10000000000,
+ },
+ RPC: RPCConfig{
+ Enabled: false,
+ External: false,
+ Unsafe: false,
+ UnsafeExternal: false,
+ Port: 8545,
+ Host: "localhost",
+ Modules: []string{"system", "author", "chain", "state", "rpc", "grandpa", "offchain",
+ "childstate", "syncstate", "payment"},
+ WSPort: 8546,
+ WS: false,
+ WSExternal: false,
+ WSUnsafe: false,
+ WSUnsafeExternal: false,
+ },
+ System: types.SystemInfo{},
+ State: StateConfig{},
+ },
+ want1: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, got1 := NewTestConfigWithFile(tt.args.t)
- tri := trie.NewEmptyTrie()
- var ttlLenght int
- for k, v := range genRaw.Genesis.Raw["top"] {
- val := []byte(v)
- ttlLenght += len(val)
- tri.Put([]byte(k), val)
+ assert.Equal(t, tt.want, got)
+ if tt.want1 != nil {
+ assert.NotNil(t, got1)
+ }
+ })
}
+}
- testCases := []struct {
+func TestNewTestGenesis(t *testing.T) {
+ type args struct {
+ t *testing.T
+ }
+ tests := []struct {
name string
- fn func(tri *trie.Trie) (*trie.Trie, error)
+ args args
+ want *genesis.Genesis
}{
- {"DeepCopy", func(tri *trie.Trie) (*trie.Trie, error) {
- return tri.DeepCopy()
- }},
- {"Snapshot", func(tri *trie.Trie) (*trie.Trie, error) {
- return tri.Snapshot(), nil
- }},
+ {
+ name: "working example",
+ args: args{t: t},
+ want: &genesis.Genesis{},
+ },
}
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- trieMap := make(map[int]*trie.Trie)
- start := time.Now()
- var m runtime.MemStats
- for i := 0; i <= 200; i++ {
- newTrie, err := tc.fn(tri)
- require.NoError(t, err)
-
- runtime.ReadMemStats(&m)
- trieMap[i] = newTrie
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := NewTestGenesis(tt.args.t)
+ if tt.want != nil {
+ assert.NotNil(t, got)
}
-
- log.Printf("\nAlloc = %v MB \nTotalAlloc = %v MB \nSys = %v MB \nNumGC = %v \n\n",
- m.Alloc/(1024*1024), m.TotalAlloc/(1024*1024), m.Sys/(1024*1024), m.NumGC)
- elapsed := time.Since(start)
- log.Printf("DeepCopy to trie took %s", elapsed)
- runtime.GC()
})
}
}
-func TestTrieSnapshot(t *testing.T) {
- cfg := NewTestConfig(t)
- require.NotNil(t, cfg)
-
- genRawFile := NewTestGenesisRawFile(t, cfg)
- require.NotNil(t, genRawFile)
-
- defer os.Remove(genRawFile.Name())
-
- genRaw, err := genesis.NewGenesisFromJSONRaw(genRawFile.Name())
- require.NoError(t, err)
-
- tri := trie.NewEmptyTrie()
- key := []byte("key")
- value := []byte("value")
-
- for k, v := range genRaw.Genesis.Raw["top"] {
- val := []byte(v)
- tri.Put([]byte(k), val)
+func TestNewTestGenesisAndRuntime(t *testing.T) {
+ type args struct {
+ t *testing.T
}
+ tests := []struct {
+ name string
+ args args
+ want string
+ }{
+ {
+ name: "working example",
+ args: args{t: t},
+ want: "",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := NewTestGenesisAndRuntime(tt.args.t)
+ assert.True(t, strings.HasPrefix(got, "test_data/TestNewTestGenesisAndRuntime/genesis"))
+ })
+ }
+}
- // DeepCopy the trie.
- dcTrie, err := tri.DeepCopy()
- require.NoError(t, err)
-
- // Take Snapshot of the trie.
- newTrie := tri.Snapshot()
-
- // Get the Trie root hash for all the 3 tries.
- tHash, err := tri.Hash()
- require.NoError(t, err)
-
- dcTrieHash, err := dcTrie.Hash()
- require.NoError(t, err)
-
- newTrieHash, err := newTrie.Hash()
- require.NoError(t, err)
-
- // Root hash for the 3 tries should be equal.
- require.Equal(t, tHash, dcTrieHash)
- require.Equal(t, tHash, newTrieHash)
-
- // Modify the current trie.
- value[0] = 'w'
- newTrie.Put(key, value)
-
- // Get the updated root hash of all tries.
- tHash, err = tri.Hash()
- require.NoError(t, err)
+func TestNewTestGenesisFile(t *testing.T) {
+ type args struct {
+ t *testing.T
+ cfg *Config
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ t: t,
+ cfg: &Config{},
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := NewTestGenesisFile(tt.args.t, tt.args.cfg)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
+}
- dcTrieHash, err = dcTrie.Hash()
- require.NoError(t, err)
+func TestNewTestGenesisRawFile(t *testing.T) {
+ type args struct {
+ t *testing.T
+ cfg *Config
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ t: t,
+ cfg: &Config{},
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := NewTestGenesisRawFile(tt.args.t, tt.args.cfg)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
+}
- newTrieHash, err = newTrie.Hash()
- require.NoError(t, err)
+func TestRandomNodeName(t *testing.T) {
+ tests := []struct {
+ name string
+ want string
+ }{
+ {
+ name: "working example",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := RandomNodeName()
+ assert.Greater(t, len(got), 3)
+ })
+ }
+}
- // Only the current trie should have a different root hash since it is updated.
- require.NotEqual(t, newTrieHash, dcTrieHash)
- require.NotEqual(t, newTrieHash, tHash)
- require.Equal(t, dcTrieHash, tHash)
+func TestWriteConfig(t *testing.T) {
+ type args struct {
+ data []byte
+ fp string
+ }
+ tests := []struct {
+ name string
+ args args
+ want *os.File
+ }{
+ {
+ name: "working example",
+ args: args{
+ data: nil,
+ fp: "test_data/test.json",
+ },
+ want: &os.File{},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got := WriteConfig(tt.args.data, tt.args.fp)
+ if tt.want != nil {
+ assert.NotNil(t, got)
+ }
+ })
+ }
}
diff --git a/lib/babe/verify.go b/lib/babe/verify.go
index 15fd8c8591..426bf4c6fc 100644
--- a/lib/babe/verify.go
+++ b/lib/babe/verify.go
@@ -7,8 +7,10 @@ import (
"errors"
"fmt"
"math/big"
+ "reflect"
"sync"
+ "github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/common"
"github.com/ChainSafe/gossamer/lib/crypto/sr25519"
@@ -47,11 +49,25 @@ type VerificationManager struct {
// NewVerificationManager returns a new NewVerificationManager
func NewVerificationManager(blockState BlockState, epochState EpochState) (*VerificationManager, error) {
- if blockState == nil {
+ var isNilBlock bool
+ switch blockState.(type) {
+ case *state.BlockState:
+ isNilBlock = blockState == (*state.BlockState)(nil)
+ default:
+ isNilBlock = reflect.ValueOf(blockState).IsNil()
+ }
+ if isNilBlock {
return nil, errNilBlockState
}
- if epochState == nil {
+ var isNilEpoch bool
+ switch epochState.(type) {
+ case *state.EpochState:
+ isNilEpoch = epochState == (*state.EpochState)(nil)
+ default:
+ isNilEpoch = reflect.ValueOf(epochState).IsNil()
+ }
+ if isNilEpoch {
return nil, errNilEpochState
}
diff --git a/lib/blocktree/blocktree.go b/lib/blocktree/blocktree.go
index f3aaf88da7..73f20f1587 100644
--- a/lib/blocktree/blocktree.go
+++ b/lib/blocktree/blocktree.go
@@ -403,7 +403,7 @@ func (bt *BlockTree) StoreRuntime(hash common.Hash, in runtime.Instance) {
// GetBlockRuntime returns block runtime for corresponding block hash.
func (bt *BlockTree) GetBlockRuntime(hash common.Hash) (runtime.Instance, error) {
ins, ok := bt.runtime.Load(hash)
- if !ok {
+ if !ok || ins == nil {
return nil, ErrFailedToGetRuntime
}
return ins.(runtime.Instance), nil