Skip to content

Commit 874800c

Browse files
committed
btcd,integration,integration/rpctest: integrate debugstream with btcd
btcd: integrated debugstream, now we can send debug events and improve testing capabilities. The hidden flag --debugstream=<host:port> starts the debug Stream when btcd is compiled with the debug tag. integration: added debugstream integration test. integration/rpctest: added DebugStreamHandler to harness options, allowing integration tests to easily process debug events. The btcd executable build to be used by the Harness is now being built with the debug tag, but the debug stream will be started only if the DebugStreamHandler is also passed to the Harness.
1 parent b5c88d5 commit 874800c

6 files changed

Lines changed: 105 additions & 3 deletions

File tree

btcd.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"github.com/btcsuite/btcd/blockchain/indexers"
2020
"github.com/btcsuite/btcd/database"
21+
"github.com/btcsuite/btcd/debugstream"
2122
"github.com/btcsuite/btcd/limits"
2223
"github.com/btcsuite/btcd/ossec"
2324
)
@@ -56,6 +57,24 @@ func btcdMain(serverChan chan<- *server) error {
5657
}
5758
}()
5859

60+
// DebugStream is enabled only if btcd is compiled with the debug tag.
61+
// Otherwise a nop implementation is used.
62+
debugstream.S = debugstream.New()
63+
if dsListen := cfg.DebugStream; dsListen != "" {
64+
err := debugstream.S.Listen(dsListen)
65+
if err != nil {
66+
return fmt.Errorf("error starting debug stream: %v",
67+
err)
68+
}
69+
debugstream.S.Broadcast(debugstream.Event{
70+
Code: debugstream.DEStart,
71+
})
72+
defer debugstream.S.Shutdown()
73+
defer debugstream.S.Broadcast(debugstream.Event{
74+
Code: debugstream.DEShutdown,
75+
})
76+
}
77+
5978
// Get a channel that will be closed when a shutdown signal has been
6079
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
6180
// another subsystem such as the RPC server.

config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ type config struct {
120120
DataDir string `short:"b" long:"datadir" description:"Directory to store data"`
121121
DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"`
122122
DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify <subsystem>=<level>,<subsystem2>=<level>,... to set the log level for individual subsystems -- Use show to list available subsystems"`
123+
DebugStream string `long:"debugstream" hidden:"true" description:"TCP listen address of the debug stream. To use this feature btcd must also be compiled with debug tag."`
123124
DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."`
124125
DropCfIndex bool `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."`
125126
DropTxIndex bool `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."`

integration/debugstream_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//go:build rpctest
2+
3+
package integration
4+
5+
import (
6+
"context"
7+
"testing"
8+
"time"
9+
10+
"github.com/btcsuite/btcd/debugstream"
11+
"github.com/btcsuite/btcd/integration/rpctest"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestDebugStream(t *testing.T) {
16+
const (
17+
sBegin = iota
18+
sNodeStarted
19+
sNodeShutdown
20+
)
21+
var state uint64
22+
ctx, cancel := context.WithTimeout(t.Context(), time.Second*10)
23+
defer cancel()
24+
debHandler := func(e debugstream.Event) {
25+
switch e.Code {
26+
case debugstream.DEStart:
27+
state = sNodeStarted
28+
29+
case debugstream.DEShutdown:
30+
state = sNodeShutdown
31+
cancel()
32+
}
33+
}
34+
35+
h, err := rpctest.New(rpctest.HarnessOpts{
36+
DebugStreamHandler: debHandler,
37+
})
38+
require.NoError(t, err)
39+
h.SetUp(false, 0)
40+
41+
err = h.TearDown()
42+
require.NoError(t, err)
43+
44+
<-ctx.Done()
45+
require.Equal(t, true, sNodeShutdown == state)
46+
}

integration/rpctest/btcd.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ func btcdExecutablePath() (string, error) {
5353
if runtime.GOOS == "windows" {
5454
outputPath += ".exe"
5555
}
56-
cmd := exec.Command(
57-
"go", "build", "-o", outputPath, "github.com/btcsuite/btcd",
58-
)
56+
cmd := exec.Command("go", "build", "-tags=debug", "-o", outputPath,
57+
"github.com/btcsuite/btcd")
5958
err = cmd.Run()
6059
if err != nil {
6160
return "", fmt.Errorf("Failed to build btcd: %v", err)

integration/rpctest/rpc_harness.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/btcsuite/btcd/btcutil/v2"
2323
"github.com/btcsuite/btcd/chaincfg/v2"
2424
"github.com/btcsuite/btcd/chainhash/v2"
25+
"github.com/btcsuite/btcd/debugstream"
2526
"github.com/btcsuite/btcd/rpcclient"
2627
"github.com/btcsuite/btcd/wire/v2"
2728
)
@@ -126,6 +127,8 @@ type Harness struct {
126127
testNodeDir string
127128
nodeNum int
128129

130+
debugClient *debugstream.Client
131+
129132
sync.Mutex
130133
}
131134

@@ -142,6 +145,11 @@ type HarnessOpts struct {
142145
// CustomExePath can be set to the path of a custom btcd executable,
143146
// otherwise we build and use a default executable.
144147
CustomExePath string
148+
149+
// DebugStreamHandler makes the harness to start btcd with the debug
150+
// stream enabled, and use the DebugStreamHandler as the handler for
151+
// the debug events.
152+
DebugStreamHandler func(debugstream.Event)
145153
}
146154

147155
// New creates and initializes new instance of the rpc test harness.
@@ -201,6 +209,15 @@ func New(opts ...HarnessOpts) (*Harness, error) {
201209
miningAddr := fmt.Sprintf("--miningaddr=%s", wallet.coinbaseAddr)
202210
o.ExtraArgs = append(o.ExtraArgs, miningAddr)
203211

212+
var debugClient *debugstream.Client
213+
if o.DebugStreamHandler != nil {
214+
p := NextAvailablePort()
215+
streamAddr := fmt.Sprintf("127.0.0.1:%d", p)
216+
debugClient = debugstream.NewClient(streamAddr,
217+
o.DebugStreamHandler)
218+
o.ExtraArgs = append(o.ExtraArgs, "--debugstream="+streamAddr)
219+
}
220+
204221
config, err := newConfig(testNodeDir, certFile, keyFile, o.ExtraArgs,
205222
o.CustomExePath)
206223
if err != nil {
@@ -260,6 +277,7 @@ func New(opts ...HarnessOpts) (*Harness, error) {
260277
ActiveNet: o.ActiveNet,
261278
nodeNum: nodeNum,
262279
wallet: wallet,
280+
debugClient: debugClient,
263281
}
264282

265283
// Track this newly created test instance within the package level
@@ -285,6 +303,12 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error {
285303
if err := h.connectRPCClient(); err != nil {
286304
return fmt.Errorf("error connecting RPC client: %w", err)
287305
}
306+
if h.debugClient != nil {
307+
if err := h.debugClient.Start(); err != nil {
308+
return fmt.Errorf("error connecting debug client: %w",
309+
err)
310+
}
311+
}
288312

289313
h.wallet.Start()
290314

@@ -347,6 +371,13 @@ func (h *Harness) tearDown(skipCleanup bool) error {
347371
h.BatchClient.WaitForShutdown()
348372
}
349373

374+
if h.debugClient != nil {
375+
// Is better to stop the client after stopping btcd, because
376+
// this way we can use the debugHandler to test the btcd
377+
// shutdown behavior.
378+
defer h.debugClient.Stop()
379+
}
380+
350381
// In the case of exit errors we still perform the cleanup, but also
351382
// return the exit error to the caller.
352383
exitErr := &exec.ExitError{}

log.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/btcsuite/btcd/blockchain/indexers"
1616
"github.com/btcsuite/btcd/connmgr"
1717
"github.com/btcsuite/btcd/database"
18+
"github.com/btcsuite/btcd/debugstream"
1819
"github.com/btcsuite/btcd/mempool"
1920
"github.com/btcsuite/btcd/mining"
2021
"github.com/btcsuite/btcd/mining/cpuminer"
@@ -61,6 +62,8 @@ var (
6162
bcdbLog = backendLog.Logger("BCDB")
6263
btcdLog = backendLog.Logger("BTCD")
6364
chanLog = backendLog.Logger("CHAN")
65+
debsLog = backendLog.Logger("DEBS")
66+
debcLog = backendLog.Logger("DEBC")
6467
discLog = backendLog.Logger("DISC")
6568
indxLog = backendLog.Logger("INDX")
6669
minrLog = backendLog.Logger("MINR")
@@ -79,6 +82,7 @@ func init() {
7982
connmgr.UseLogger(cmgrLog)
8083
database.UseLogger(bcdbLog)
8184
blockchain.UseLogger(chanLog)
85+
debugstream.UseLoggers(debsLog, debcLog)
8286
indexers.UseLogger(indxLog)
8387
mining.UseLogger(minrLog)
8488
cpuminer.UseLogger(minrLog)
@@ -97,6 +101,8 @@ var subsystemLoggers = map[string]btclog.Logger{
97101
"BCDB": bcdbLog,
98102
"BTCD": btcdLog,
99103
"CHAN": chanLog,
104+
"DEBS": debsLog,
105+
"DEBC": debcLog,
100106
"DISC": discLog,
101107
"INDX": indxLog,
102108
"MINR": minrLog,

0 commit comments

Comments
 (0)