Skip to content

Commit

Permalink
test: add tests for pruning store (#1406)
Browse files Browse the repository at this point in the history
  • Loading branch information
b00f authored Jul 12, 2024
1 parent 50b5eb5 commit 3c0844a
Show file tree
Hide file tree
Showing 24 changed files with 637 additions and 309 deletions.
4 changes: 2 additions & 2 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,8 +479,8 @@ func MakeConfig(workingDir string) (*config.Config, *genesis.Genesis, error) {
// Now we can update the private filed, if any
genParams := gen.Params()

conf.Store.TxCacheSize = genParams.TransactionToLiveInterval
conf.Store.SortitionCacheSize = genParams.SortitionInterval
conf.Store.TxCacheWindow = genParams.TransactionToLiveInterval
conf.Store.SeedCacheWindow = genParams.SortitionInterval
conf.Store.AccountCacheSize = 1024
conf.Store.PublicKeyCacheSize = 1024

Expand Down
54 changes: 54 additions & 0 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,67 @@ import (
"runtime"
"testing"

"github.com/pactus-project/pactus/config"
"github.com/pactus-project/pactus/genesis"
"github.com/pactus-project/pactus/util"
"github.com/pactus-project/pactus/util/testsuite"
"github.com/pactus-project/pactus/wallet"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestMakeConfig(t *testing.T) {
t.Run("No genesis file, Should return error", func(t *testing.T) {
workingDir := util.TempDirPath()

_, _, err := MakeConfig(workingDir)
assert.Error(t, err)
})

t.Run("No Config file, Should recover it", func(t *testing.T) {
workingDir := util.TempDirPath()
genPath := PactusGenesisPath(workingDir)
gen := genesis.MainnetGenesis()
err := gen.SaveToFile(genPath)
require.NoError(t, err)

_, _, err = MakeConfig(workingDir)
assert.NoError(t, err)
})

t.Run("Invalid Config file, Should recover it", func(t *testing.T) {
workingDir := util.TempDirPath()
genPath := PactusGenesisPath(workingDir)
confPath := PactusConfigPath(workingDir)

gen := genesis.MainnetGenesis()
err := gen.SaveToFile(genPath)
require.NoError(t, err)

err = util.WriteFile(confPath, []byte("invalid-config"))
require.NoError(t, err)

_, _, err = MakeConfig(workingDir)
assert.NoError(t, err)
})

t.Run("Everything is good", func(t *testing.T) {
workingDir := util.TempDirPath()
genPath := PactusGenesisPath(workingDir)
confPath := PactusConfigPath(workingDir)

gen := genesis.MainnetGenesis()
err := gen.SaveToFile(genPath)
require.NoError(t, err)

err = config.SaveMainnetConfig(confPath)
require.NoError(t, err)

_, _, err = MakeConfig(workingDir)
assert.NoError(t, err)
})
}

// captureOutput is a helper function to capture the printed output of a function.
func captureOutput(f func()) string {
// Redirect stdout to a buffer
Expand Down
45 changes: 27 additions & 18 deletions cmd/daemon/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package main
import (
"fmt"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"

"github.com/gofrs/flock"
"github.com/pactus-project/pactus/cmd"
Expand Down Expand Up @@ -66,37 +64,48 @@ func buildPruneCmd(parentCmd *cobra.Command) {
prunedCount := uint32(0)
skippedCount := uint32(0)
totalCount := uint32(0)
canceled := false
closed := make(chan bool, 1)

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

go func() {
<-interrupt
str.Close()
_ = fileLock.Unlock()
}()
cmd.TrapSignal(func() {
canceled = true
<-closed
})

err = str.Prune(func(pruned, skipped, pruningHeight uint32) {
prunedCount += pruned
skippedCount += skipped
err = str.Prune(func(pruned bool, pruningHeight uint32) bool {
if pruned {
prunedCount++
} else {
skippedCount++
}

if totalCount == 0 {
totalCount = pruningHeight
}

pruningProgressBar(prunedCount, skippedCount, totalCount)

return canceled
})
cmd.PrintLine()
cmd.FatalErrorCheck(err)

if canceled {
cmd.PrintLine()
cmd.PrintInfoMsgf("❌ The operation canceled.")
cmd.PrintLine()
} else {
cmd.PrintLine()
cmd.PrintInfoMsgf("✅ Your node successfully pruned and changed to prune mode.")
cmd.PrintLine()
cmd.PrintInfoMsgf("You can start the node by running this command:")
cmd.PrintInfoMsgf("./pactus-daemon start -w %v", workingDir)
}

str.Close()
_ = fileLock.Unlock()

cmd.PrintLine()
cmd.PrintInfoMsgf("✅ Your node successfully pruned and changed to prune mode.")
cmd.PrintLine()
cmd.PrintInfoMsgf("You can start the node by running this command:")
cmd.PrintInfoMsgf("./pactus-daemon start -w %v", workingDir)
closed <- true
}
}

Expand Down
3 changes: 2 additions & 1 deletion cmd/daemon/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ func buildStartCmd(parentCmd *cobra.Command) {
cmd.FatalErrorCheck(err)

cmd.TrapSignal(func() {
cmd.PrintInfoMsgf("Exiting...")

_ = fileLock.Unlock()
node.Stop()
cmd.PrintInfoMsgf("Exiting ...")
})

// run forever (the node will not be returned)
Expand Down
14 changes: 4 additions & 10 deletions cmd/gtk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import (
"flag"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"

"github.com/gofrs/flock"
"github.com/gotk3/gotk3/gdk"
Expand Down Expand Up @@ -123,21 +121,17 @@ func main() {

// Connect function to application shutdown event, this is not required.
app.Connect("shutdown", func() {
log.Println("Application shutdown")
n.Stop()
_ = fileLock.Unlock()
log.Println("application shutdown")
})

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
cmd.TrapSignal(func() {
cmd.PrintInfoMsgf("Exiting...")

go func() {
s := <-interrupt
log.Printf("signal %s received", s.String())
n.Stop()
_ = fileLock.Unlock()
os.Exit(0)
}()
})

// Launch the application
os.Exit(app.Run(nil))
Expand Down
98 changes: 63 additions & 35 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,40 +155,68 @@ func TestExampleConfig(t *testing.T) {

func TestNodeConfigBasicCheck(t *testing.T) {
ts := testsuite.NewTestSuite(t)
randValAddr := ts.RandValAddress()

testCases := []struct {
name string
expectedErr error
updateFn func(c *NodeConfig)
}{
{
name: "Invalid reward addresses",
expectedErr: NodeConfigError{
Reason: "invalid reward address: invalid bech32 string length 4",
},
updateFn: func(c *NodeConfig) {
c.RewardAddresses = []string{
"abcd",
}
},
},
{
name: "Validator address as reward address",
expectedErr: NodeConfigError{
Reason: "reward address is not an account address: " + randValAddr.String(),
},
updateFn: func(c *NodeConfig) {
c.RewardAddresses = []string{
randValAddr.String(),
}
},
},
{
name: "Two rewards addresses",
updateFn: func(c *NodeConfig) {
c.RewardAddresses = []string{
ts.RandAccAddress().String(),
ts.RandAccAddress().String(),
}
},
},
{
name: "No reward address",
updateFn: func(c *NodeConfig) {
c.RewardAddresses = []string{}
},
},
{
name: "DefaultConfig",
updateFn: func(*NodeConfig) {},
},
}

t.Run("invalid reward addresses", func(t *testing.T) {
conf := DefaultNodeConfig()
conf.RewardAddresses = []string{
ts.RandAccAddress().String(),
"abcd",
}

assert.Error(t, conf.BasicCheck())
})

t.Run("validator address as reward address", func(t *testing.T) {
conf := DefaultNodeConfig()
conf.RewardAddresses = []string{
ts.RandValAddress().String(),
}

assert.Error(t, conf.BasicCheck())
})

t.Run("ok", func(t *testing.T) {
conf := DefaultNodeConfig()
conf.RewardAddresses = []string{
ts.RandAccAddress().String(),
ts.RandAccAddress().String(),
}

assert.NoError(t, conf.BasicCheck())
})

t.Run("no reward addresses inside config, Ok", func(t *testing.T) {
conf := DefaultNodeConfig()
conf.RewardAddresses = []string{}

assert.NoError(t, conf.BasicCheck())
})
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
conf := DefaultNodeConfig()
tc.updateFn(conf)
if tc.expectedErr != nil {
err := conf.BasicCheck()
assert.ErrorIs(t, tc.expectedErr, err,
"Expected error not matched for test %d-%s, expected: %s, got: %s", i, tc.name, tc.expectedErr, err)
} else {
err := conf.BasicCheck()
assert.NoError(t, err, "Expected no error for test %d-%s, get: %s", i, tc.name, err)
}
})
}
}
82 changes: 61 additions & 21 deletions consensus/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,68 @@ import (
"github.com/stretchr/testify/assert"
)

func TestDefaultConfigCheck(t *testing.T) {
c1 := DefaultConfig()
c2 := DefaultConfig()
c3 := DefaultConfig()
c4 := DefaultConfig()
c5 := DefaultConfig()
assert.NoError(t, c1.BasicCheck())
func TestConfigBasicCheck(t *testing.T) {
testCases := []struct {
name string
expectedErr error
updateFn func(c *Config)
}{
{
name: "Invalid ChangeProposerDelta",
expectedErr: ConfigError{
Reason: "change proposer delta must be greater than zero",
},
updateFn: func(c *Config) {
c.ChangeProposerDelta = 0
},
},
{
name: "Invalid ChangeProposerTimeout",
expectedErr: ConfigError{
Reason: "change proposer timeout must be greater than zero",
},
updateFn: func(c *Config) {
c.ChangeProposerTimeout = -1 * time.Second
},
},
{
name: "Invalid MinimumAvailabilityScore",
expectedErr: ConfigError{
Reason: "minimum availability score can't be negative or more than 1",
},
updateFn: func(c *Config) {
c.MinimumAvailabilityScore = 1.5
},
},
{
name: "Invalid MinimumAvailabilityScore - Negative",
expectedErr: ConfigError{
Reason: "minimum availability score can't be negative or more than 1",
},
updateFn: func(c *Config) {
c.MinimumAvailabilityScore = -0.8
},
},
{
name: "DefaultConfig",
updateFn: func(*Config) {},
},
}

c2.ChangeProposerDelta = 0 * time.Second
assert.ErrorIs(t, c2.BasicCheck(), ConfigError{Reason: "change proposer delta must be greater than zero"})

c3.ChangeProposerTimeout = 0 * time.Second
assert.ErrorIs(t, c3.BasicCheck(), ConfigError{Reason: "change proposer timeout must be greater than zero"})

c4.ChangeProposerTimeout = -1 * time.Second
assert.ErrorIs(t, c4.BasicCheck(), ConfigError{Reason: "change proposer timeout must be greater than zero"})

c5.MinimumAvailabilityScore = 1.5
assert.ErrorIs(t, c5.BasicCheck(), ConfigError{Reason: "minimum availability score can't be negative or more than 1"})

c5.MinimumAvailabilityScore = -0.8
assert.ErrorIs(t, c5.BasicCheck(), ConfigError{Reason: "minimum availability score can't be negative or more than 1"})
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
conf := DefaultConfig()
tc.updateFn(conf)
if tc.expectedErr != nil {
err := conf.BasicCheck()
assert.ErrorIs(t, tc.expectedErr, err,
"Expected error not matched for test %d-%s, expected: %s, got: %s", i, tc.name, tc.expectedErr, err)
} else {
err := conf.BasicCheck()
assert.NoError(t, err, "Expected no error for test %d-%s, get: %s", i, tc.name, err)
}
})
}
}

func TestCalculateChangeProposerTimeout(t *testing.T) {
Expand Down
Loading

0 comments on commit 3c0844a

Please sign in to comment.