Using Delv To Debug TDD Tesing In Golang — BTC ledger crawler program

Context

Sample & delv debug usage

➜  utxo-cqrs git:(develop) cd app/service/block_parser/pkg/repository
➜ repository git:(develop) dlv test ./
Type 'help' for list of commands.
(dlv) help
The following commands are available:
Running the program:
call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)
continue (alias: c) --------- Run until breakpoint or program termination.
next (alias: n) ------------- Step over to next source line.
rebuild --------------------- Rebuild the target executable and restarts it. It does not work if the executable was not built by delve.
restart (alias: r) ---------- Restart process.
step (alias: s) ------------- Single step through program.
step-instruction (alias: si) Single step a single cpu instruction.
stepout (alias: so) --------- Step out of the current function.
Manipulating breakpoints:
break (alias: b) ------- Sets a breakpoint.
breakpoints (alias: bp) Print out info for active breakpoints.
clear ------------------ Deletes breakpoint.
clearall --------------- Deletes multiple breakpoints.
condition (alias: cond) Set breakpoint condition.
on --------------------- Executes a command when a breakpoint is hit.
trace (alias: t) ------- Set tracepoint.
Viewing program variables and memory:
args ----------------- Print function arguments.
display -------------- Print value of an expression every time the program stops.
examinemem (alias: x) Examine memory:
locals --------------- Print local variables.
print (alias: p) ----- Evaluate an expression.
regs ----------------- Print contents of CPU registers.
set ------------------ Changes the value of a variable.
vars ----------------- Print package variables.
whatis --------------- Prints type of an expression.
Listing and switching between threads and goroutines:
goroutine (alias: gr) -- Shows or changes current goroutine
goroutines (alias: grs) List program goroutines.
thread (alias: tr) ----- Switch to the specified thread.
threads ---------------- Print out info for every traced thread.
Viewing the call stack and selecting frames:
deferred --------- Executes command in the context of a deferred call.
down ------------- Move the current frame down.
frame ------------ Set the current frame, or execute command on a different frame.
stack (alias: bt) Print stack trace.
up --------------- Move the current frame up.
Other commands:
config --------------------- Changes configuration parameters.
disassemble (alias: disass) Disassembler.
edit (alias: ed) ----------- Open where you are in $DELVE_EDITOR or $EDITOR
exit (alias: quit | q) ----- Exit the debugger.
funcs ---------------------- Print list of functions.
help (alias: h) ------------ Prints the help message.
libraries ------------------ List loaded dynamic libraries
list (alias: ls | l) ------- Show source code.
source --------------------- Executes a file containing a list of delve commands
sources -------------------- Print list of source files.
types ---------------------- Print list of types
Type help followed by a command for full documentation.
➜  repository git:(develop) dlv test ./
Type 'help' for list of commands.
(dlv) b TestBlockGenerated
Breakpoint 1 set at 0x19672db for github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:17
(dlv) c
2021/03/12 16:56:30 WARNING: proto: file "block.proto" is already registered
A future release will panic on registration conflicts. See:
https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict
2021/03/12 16:56:32 Established connection to RPC server localhost:8431
2021/03/12 16:56:32 Starting RPC client localhost:8431
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:17 (hits goroutine(118):1 total:1) (PC: 0x19672db)
12:
13: type BlockProjectorTestSuite struct {
14: RepoSuite
15: }
16:
=> 17: func (s *BlockProjectorTestSuite) TestBlockGenerated() {
18: cases := []struct {
19: BlockCmd *rpcproto.GetBlockVerboseTxResult
20: constraintEvent bool
21: err error
22: }{
(dlv) b 59
Breakpoint 2 set at 0x196799c for github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:59
(dlv) c
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:59 (hits goroutine(118):1 total:1) (PC: 0x196799c)
54: false,
55: BlockExistErr{Msg: "block exist: 0000000000000000000aafc247e4f795e1de32f20356bac70ce39e7eb9d53ae1"},
56: },
57: }
58:
=> 59: for _, tc := range cases {
60: err := s.repository.BlockGenerated(context.Background(), tc.BlockCmd, tc.constraintEvent)
61: if tc.err == nil {
62: s.Assert().NoError(err)
63: } else {
64: s.Assert().EqualError(tc.err, err.Error())
(dlv) n
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:60 (PC: 0x1967a40)
55: BlockExistErr{Msg: "block exist: 0000000000000000000aafc247e4f795e1de32f20356bac70ce39e7eb9d53ae1"},
56: },
57: }
58:
59: for _, tc := range cases {
=> 60: err := s.repository.BlockGenerated(context.Background(), tc.BlockCmd, tc.constraintEvent)
61: if tc.err == nil {
62: s.Assert().NoError(err)
63: } else {
64: s.Assert().EqualError(tc.err, err.Error())
65: }
(dlv) s
> context.Background() /usr/local/Cellar/go/1.16/libexec/src/context/context.go:208 (PC: 0x11641c0)
203:
204: // Background returns a non-nil, empty Context. It is never canceled, has no
205: // values, and has no deadline. It is typically used by the main function,
206: // initialization, and tests, and as the top-level Context for incoming
207: // requests.
=> 208: func Background() Context {
209: return background
210: }
211:
212: // TODO returns a non-nil, empty Context. Code should use context.TODO when
213: // it's unclear which Context to use or it is not yet available (because the
(dlv) stepout
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*BlockProjectorTestSuite).TestBlockGenerated() ./block_projector_suite_test.go:60 (PC: 0x1967a45)
Values returned:
~r0: context.Context(*context.emptyCtx) *0
55: BlockExistErr{Msg: "block exist: 0000000000000000000aafc247e4f795e1de32f20356bac70ce39e7eb9d53ae1"},
56: },
57: }
58:
59: for _, tc := range cases {
=> 60: err := s.repository.BlockGenerated(context.Background(), tc.BlockCmd, tc.constraintEvent)
61: if tc.err == nil {
62: s.Assert().NoError(err)
63: } else {
64: s.Assert().EqualError(tc.err, err.Error())
65: }
(dlv) s
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*repo).BlockGenerated() ./block_projector.go:26 (PC: 0x19628bb)
21:
22: func (err BlockExistErr) Error() string {
23: return err.Msg
24: }
25:
=> 26: func (repo *repo) BlockGenerated(ctx context.Context, event *rpcproto.GetBlockVerboseTxResult, constraintEvent bool) error {
27: conn := repo.db.Conn()
28: defer conn.Close()
29:
30: // query with block hash and heigh
31: // block-parser=# explain (analyze,verbose,timing,costs,buffers)select count(*) from events where event_json @> '{"hash":"0000000033a27c42a6d51c428de207c78007492be46d5488e636121e84161a18", "height":"5247"}';
(dlv) b 67
Breakpoint 3 set at 0x19632f5 for github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*repo).BlockGenerated() ./block_projector.go:67
(dlv) c
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*repo).BlockGenerated() ./block_projector.go:67 (hits goroutine(118):1 total:1) (PC: 0x19632f5)
62: eventMeta, err := pgjson.Marshal(&txsWithHex)
63: if err != nil {
64: return errors.New("fail to marshal block tx: " + err.Error())
65: }
66:
=> 67: event.Tx = nil
68: eventJSON, err := pgjson.Marshal(&event)
69: if err != nil {
70: return errors.New("fail to marshal block payload: " + err.Error())
71: }
72:
(dlv) p txsWithHex
[]github.com/wenweih/bitcoin-rpc-golang/proto.Transaction len: 2, cap: 2, [
{
state: (*"google.golang.org/protobuf/internal/impl.MessageState")(0xc0001cc140),
sizeCache: 0,
unknownFields: []uint8 len: 0, cap: 0, nil,
Txid: "",
Hash: "",
Version: 0,
Size: 0,
Vsize: 0,
Weight: 0,
Locktime: 0,
Vin: []*github.com/wenweih/bitcoin-rpc-golang/proto.Vin len: 0, cap: 0, nil,
Vout: []*github.com/wenweih/bitcoin-rpc-golang/proto.Vout len: 0, cap: 0, nil,
Hex: "0100000000010100000000000000000000000000000000000000000000000000...+690 more",},
{
state: (*"google.golang.org/protobuf/internal/impl.MessageState")(0xc0001cc1e0),
sizeCache: 0,
unknownFields: []uint8 len: 0, cap: 0, nil,
Txid: "",
Hash: "",
Version: 0,
Size: 0,
Vsize: 0,
Weight: 0,
Locktime: 0,
Vin: []*github.com/wenweih/bitcoin-rpc-golang/proto.Vin len: 0, cap: 0, nil,
Vout: []*github.com/wenweih/bitcoin-rpc-golang/proto.Vout len: 0, cap: 0, nil,
Hex: "01000000025867051e9262a2191c6627cca7c65a44a1b9080156af96b1f6eaa3...+680 more",},
]
(dlv) c
> github.com/wenweih/utxo-cqrs/app/service/block_parser/pkg/repository.(*repo).BlockGenerated() ./block_projector.go:67 (hits goroutine(118):2 total:2) (PC: 0x19632f5)
62: eventMeta, err := pgjson.Marshal(&txsWithHex)
63: if err != nil {
64: return errors.New("fail to marshal block tx: " + err.Error())
65: }
66:
=> 67: event.Tx = nil
68: eventJSON, err := pgjson.Marshal(&event)
69: if err != nil {
70: return errors.New("fail to marshal block payload: " + err.Error())
71: }

--

--

--

https://huangwenwei.com

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Converting Interactable Legacy Input to the New Unity Input System

Load Testing | Best Practices For Black Friday

Migrating from Dropbox to Nextcloud

Airplane — With the best

Four Strategies to Reduce Risk When Modifying Code

Cassandra with Spring Framework

The Best Practices of Alibaba Cloud’s DCDN in the Game Industry

It’s the World’s First Application Management Model, and It’s Open-Source!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
hww

hww

https://huangwenwei.com

More from Medium

Cross-compilation in Go

Golang default settings

We are more than 75,000 people (stars 🌟) — awesome-go

GitHub repository avelino/awesome-go

GoFrame 101: Enable TLS/SSL with rk-boot