Skip to content

Commit

Permalink
fix(btcdctrl): handle & test for flaky edge-cases
Browse files Browse the repository at this point in the history
1. killing a process then waiting for it can return an error depending on state, instead just exit the loop.
2. websockets hang indefinitely every 20 tests or so, use HTTP POST instead.
3. handle the RPC/P2P message being the last line in the log.
  • Loading branch information
linden committed Oct 9, 2024
1 parent 70fb0df commit 069afc4
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 59 deletions.
15 changes: 9 additions & 6 deletions btcdctrl/btcdctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func (c *Controller) Stop() error {
for {
exit, err := c.cmd.Process.Wait()
if err != nil {
return err
break
}

// Check if the program exited.
Expand Down Expand Up @@ -139,9 +139,9 @@ func (c *Controller) RPCConnConfig() (*rpcclient.ConnConfig, error) {
User: c.cfg.RPCUser,
Pass: c.cfg.RPCPass,

Endpoint: "ws",

Certificates: cert,

HTTPPostMode: true,
}, nil
}

Expand Down Expand Up @@ -288,21 +288,24 @@ func (c *Controller) Start() error {
p2p := false

// Scan each line until both RPC (if enabled) and P2P addresses are found.
for scan.Scan() && (!rpc || !p2p) {
for !rpc || !p2p {
line := scan.Text()

_, addr, ok := strings.Cut(line, "RPC server listening on ")

Check failure on line 294 in btcdctrl/btcdctrl.go

View workflow job for this annotation

GitHub Actions / Unit race

undefined: strings.Cut
if ok {
c.rpc = addr
rpc = true
continue
}

_, addr, ok = strings.Cut(line, "Server listening on ")

Check failure on line 300 in btcdctrl/btcdctrl.go

View workflow job for this annotation

GitHub Actions / Unit race

undefined: strings.Cut
if !ok {
c.p2p = addr
p2p = true
continue
}

// Ensure we've not found the RPC and P2P addresses, so we can continue scanning.
if (!rpc || !p2p) && !scan.Scan() {
break
}
}

Expand Down
83 changes: 30 additions & 53 deletions btcdctrl/btcdctrl_test.go
Original file line number Diff line number Diff line change
@@ -1,60 +1,37 @@
package btcdctrl_test
package btcdctrl

import (
"fmt"
"os"

"github.com/btcsuite/btcd/btcdctrl"
"testing"
)

func ExampleController() {
// Create a temporary directory for the wallet data.
tmp, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}

// Create a new test-oriented configration.
cfg, err := btcdctrl.NewTestConfig(tmp)
if err != nil {
panic(err)
}

// Create a new controller.
c := btcdctrl.New(&btcdctrl.ControllerConfig{
Stderr: os.Stderr,
Stdout: os.Stdout,

Config: cfg,
})

// Start btcd.
err = c.Start()
if err != nil {
panic(err)
func TestFail(t *testing.T) {
for i := 0; i < 100; i++ {
cfg, err := NewTestConfig(t.TempDir())
if err != nil {
t.Fatal(err)
}

cfg.DebugLevel = "trace"

// Create a new controller.
c := New(&ControllerConfig{
Stderr: os.Stderr,
Stdout: os.Stdout,

Config: cfg,
})

// Start btcd.
err = c.Start()
if err != nil {
t.Fatal(err)
}

// Stop btcd.
err = c.Stop()
if err != nil {
t.Fatal(err)
}
}

// Stop btcd on exit.
defer c.Stop()

// Enable generation.
err = c.SetGenerate(true, 0)
if err != nil {
panic(err)
}

// Generate 100 blocks.
_, err = c.Generate(100)
if err != nil {
panic(err)
}

// Query info.
info, err := c.GetInfo()
if err != nil {
panic(err)
}

fmt.Println(info.Blocks)
// Output: 100
}
57 changes: 57 additions & 0 deletions btcdctrl/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package btcdctrl_test

import (
"fmt"
"os"

"github.com/btcsuite/btcd/btcdctrl"
)

func ExampleController() {
// Create a temporary directory for the wallet data.
tmp, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}

// Create a new test-oriented configration.
cfg, err := btcdctrl.NewTestConfig(tmp)
if err != nil {
panic(err)
}

// Create a new controller.
c := btcdctrl.New(&btcdctrl.ControllerConfig{
Config: cfg,
})

// Start btcd.
err = c.Start()
if err != nil {
panic(err)
}

// Stop btcd on exit.
defer c.Stop()

// Enable generation.
err = c.SetGenerate(true, 0)
if err != nil {
panic(err)
}

// Generate 100 blocks.
_, err = c.Generate(100)
if err != nil {
panic(err)
}

// Query info.
info, err := c.GetInfo()
if err != nil {
panic(err)
}

fmt.Println(info.Blocks)
// Output: 100
}

0 comments on commit 069afc4

Please sign in to comment.