Skip to content

Commit

Permalink
dcrwtest: Initial Version.
Browse files Browse the repository at this point in the history
The dcrwtest module allows running a dcrwallet instance.  It supports
creating and opening wallets, syncing the wallet with with a dcrd node
(in either RPC or SPV mode) and operating the wallet through its gRPC
and JSON-RPC interfaces.
  • Loading branch information
matheusd committed Dec 21, 2023
1 parent 3d06801 commit 30516a6
Show file tree
Hide file tree
Showing 16 changed files with 1,952 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ The following sub-modules are currently provided:

- [`dcrdtest`](./dcrdtest): Provides testing facilities to use
[`dcrd`](https://github.com/decred/dcrd) binaries in a simnet network.
- [`dcrwtest`](./dcrwtest): Provides automation facilities to use
[`dcrwallet`](https://github.com/decred/dcrwallet) binaries in testing or
other autmated scenarios.

## License

Expand Down
1 change: 1 addition & 0 deletions dcrtest.work
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
go 1.19

use ./dcrdtest
use ./dcrwtest
55 changes: 55 additions & 0 deletions dcrwtest/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
dcrwtest
=======

[![Build Status](https://github.com/decred/dcrtest/workflows/Build%20and%20Test/badge.svg)](https://github.com/decred/dcrtest/actions)
[![ISC License](https://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
[![Doc](https://img.shields.io/badge/doc-reference-blue.svg)](https://pkg.go.dev/github.com/decred/dcrtest/dcrwtest)

Package dcrwtest provides a dcrwallet-specific automation and testing
harness. This allows creating, running and operating a decred wallet through its
JSON-RPC and gRPC interfaces.

This package was designed specifically to act as a testing harness for
`dcrwallet`. However, the constructs presented are general enough to be adapted
to any project wishing to programmatically drive a `dcrwallet` instance of its
systems/integration tests.

## Installation and Updating

```shell
$ go get github.com/decred/dcrtest/dcrwtest@latest
```

## Choice of dcrwallet Binary

This library requires a `dcrwallet` binary to be available for running and
driving its operations. The specific binary that is used can be selected in two
ways:

### Manually

Using the package-level `SetPathToDcrwallet()` function, users of `dcrwtest` can
specify a path to a pre-existing binary. This binary must exist and have
executable permissions for the current user.

### Automatically

When a path to an existing `dcrwallet` binary is not defined via
`SetPathToDcrwallet()`, then this package will attempt to build one in a
temporary directory. This requires the Go toolchain to be available for the
current user.

The version of the `dcrwallet` binary that will be built will be chosen
following the rules for the standard Go toolchain module version determination:

1. The version or replacement specified in the currently active [Go
Workspace](https://go.dev/ref/mod#workspaces).
2. The version or replacement specified in the main module (i.e. in the
`go.mod` of the project that imports this package).
3. The version specified in the [go.mod](./go.mod) of this package.

## License

Package dcrwtest is licensed under the [copyfree](http://copyfree.org) ISC
License.

128 changes: 128 additions & 0 deletions dcrwtest/builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright (c) 2023 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package dcrwtest

import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"sync"
)

var (
// pathToDcrwMtx protects the following fields.
pathToDcrwMtx sync.RWMutex

// pathToDcrw points to the test dcrwallet binary. It is supplied
// through NewWithDCRW or created on the first call to New and used
// throughout the life of this package.
pathToDcrw string

// isBuiltBinary tracks whether the dcrwallet binary pointed to by
// pathToDcrw was built by an invocation of globalPathToDcw().
isBuiltBinary bool

// dcrwMainPkg is the main dcrwallet package version.
//
// NOTE: this MUST have the same value as the one required in
// require.go.
dcrwMainPkg = "decred.org/dcrwallet/v3"
)

// SetPathToDcrwallet sets the package level dcrwallet executable. All calls to
// New will use the dcrwallet located there throughout their life. If not set
// upon the first call to New, a dcrwallet will be created in a temporary
// directory and pathToDCRW set automatically.
//
// NOTE: This function is safe for concurrent access, but care must be taken
// when setting different paths and using New, as whatever is at pathToDCRW at
// the time will be used to start that instance.
func SetPathToDcrwallet(path string) {
pathToDcrwMtx.Lock()
pathToDcrw = path
isBuiltBinary = false
pathToDcrwMtx.Unlock()
}

// SetDcrwalletMainPkg sets the version of the main dcrwallet package executable.
// Calls to New that require building a fresh dcrwallet instance will cause
// the specified package to be built.
//
// NOTE: This function is safe for concurrent access, but care must be taken
// when setting different packages and using New, as the value of the package
// set when New() is executed will be used.
func SetDcrwalletMainPkg(pkg string) {
pathToDcrwMtx.Lock()
dcrwMainPkg = pkg
pathToDcrw = ""
isBuiltBinary = false
pathToDcrwMtx.Unlock()
}

// buildDcrw builds a dcrwallet binary in a temp file and returns the path to
// the binary. This requires the Go toolchain to be installed and available in
// the machine. The version of the dcrwallet package built depends on the
// currently required version of the decred.org/dcrwallet module, which may be
// defined by either the go.mod file in this package, a main go.mod file (when
// this package is included as a library in a project) or the current
// workspace.
func buildDcrw(dcrwMainPkg string) (string, error) {
// NOTE: when updating this package, the dummy import in require.go
// MUST also be updated.
outDir, err := os.MkdirTemp("", "dcrwtestdcrwallet")
if err != nil {
return "", err
}

dcrwalletBin := "dcrwallet"
if runtime.GOOS == "windows" {
dcrwalletBin += ".exe"
}

dcrwPath := filepath.Join(outDir, dcrwalletBin)
log.Debugf("Building dcrwallet pkg %s in %s", dcrwMainPkg, dcrwPath)
cmd := exec.Command("go", "build", "-o", dcrwPath, dcrwMainPkg)
output, err := cmd.CombinedOutput()
if err != nil {
log.Error(string(output))
return "", fmt.Errorf("failed to build dcrwallet: %w", err)
}

return dcrwPath, nil
}

// globalPathToDcrw returns the global path to the binary dcrwallet instance.
// If needed, this will attempt to build a test instance of dcrwallet.
func globalPathToDcrw() (string, error) {
pathToDcrwMtx.Lock()
defer pathToDcrwMtx.Unlock()
if pathToDcrw != "" {
return pathToDcrw, nil
}

newPath, err := buildDcrw(dcrwMainPkg)
if err != nil {
return "", err
}
pathToDcrw = newPath
isBuiltBinary = true
return newPath, nil
}

// CleanBuiltDcrwallet cleans the currently used dcrwallet binary dir if it was
// built by this package.
func CleanBuiltDcrwallet() error {
var err error
pathToDcrwMtx.Lock()
if isBuiltBinary && pathToDcrw != "" {
isBuiltBinary = false
err = os.RemoveAll(filepath.Dir(pathToDcrw))
pathToDcrw = ""
}
pathToDcrwMtx.Unlock()
return err

}
34 changes: 34 additions & 0 deletions dcrwtest/builder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2023 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package dcrwtest

import (
"os"
"os/exec"
"path/filepath"
"testing"
)

// TestBuilder tests that we can build a new dcrwallet binary.
func TestBuilder(t *testing.T) {
path, err := buildDcrw(dcrwMainPkg)
if err != nil {
t.Fatalf("Unable to build dcrwallet: %v", err)
}

t.Logf("Built dcrwallet at %s", path)

cmd := exec.Command(path, "--version")
output, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("Unable to fetch dcrwallet output: %v", err)
}

t.Logf("dcrwallet version: %s", string(output))

err = os.RemoveAll(filepath.Dir(path))
if err != nil {
t.Fatal(err)
}
}
64 changes: 64 additions & 0 deletions dcrwtest/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module github.com/decred/dcrtest/dcrwtest

go 1.19

// The following require defines the version of dcrwallet that is built for
// tests of this package and the minimum version used when this package is
// required by a client module (unless overridden in the main module or
// workspace).
require decred.org/dcrwallet/v3 v3.0.0

require (
github.com/decred/dcrd/chaincfg/v3 v3.2.0
github.com/decred/dcrd/dcrjson/v4 v4.0.1
github.com/decred/dcrd/rpcclient/v8 v8.0.0
github.com/decred/dcrd/wire v1.6.0
github.com/decred/slog v1.2.0
github.com/jrick/wsrpc/v2 v2.3.5
golang.org/x/net v0.9.0
golang.org/x/sync v0.5.0
google.golang.org/grpc v1.54.0
matheusd.com/testctx v0.1.0
)

require (
decred.org/cspp/v2 v2.1.0 // indirect
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a // indirect
github.com/dchest/siphash v1.2.3 // indirect
github.com/decred/base58 v1.0.5 // indirect
github.com/decred/dcrd/addrmgr/v2 v2.0.2 // indirect
github.com/decred/dcrd/blockchain/stake/v5 v5.0.0 // indirect
github.com/decred/dcrd/blockchain/standalone/v2 v2.2.0 // indirect
github.com/decred/dcrd/certgen v1.1.2 // indirect
github.com/decred/dcrd/chaincfg/chainhash v1.0.4 // indirect
github.com/decred/dcrd/connmgr/v3 v3.1.1 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
github.com/decred/dcrd/crypto/ripemd160 v1.0.2 // indirect
github.com/decred/dcrd/database/v3 v3.0.1 // indirect
github.com/decred/dcrd/dcrec v1.0.1 // indirect
github.com/decred/dcrd/dcrec/edwards/v2 v2.0.3 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/decred/dcrd/dcrutil/v4 v4.0.1 // indirect
github.com/decred/dcrd/gcs/v4 v4.0.0 // indirect
github.com/decred/dcrd/hdkeychain/v3 v3.1.1 // indirect
github.com/decred/dcrd/rpc/jsonrpc/types/v4 v4.1.0 // indirect
github.com/decred/dcrd/txscript/v4 v4.1.0 // indirect
github.com/decred/go-socks v1.1.0 // indirect
github.com/decred/vspd/client/v2 v2.0.0 // indirect
github.com/decred/vspd/types/v2 v2.1.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/jrick/bitset v1.0.0 // indirect
github.com/jrick/logrotate v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/protobuf v1.30.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
)
Loading

0 comments on commit 30516a6

Please sign in to comment.