Skip to content

Commit

Permalink
Fix and improve tests (#60)
Browse files Browse the repository at this point in the history
* [tests] move BCNode to separate module

* [tests] move LitNode to separate module

* [tests] Update copyright notice and python hashbang

* [tests] Ensure we're running the minimum bitcoind version

* [ci] download bitcoind from bitcoin.org

* [tests] try to clean up bitcoind and lit processes on failure

* [tests] remove global TMP_DIR

* [tests] Improve failure logging

* [tests] fixups

* [ci] cache bitcoind and litecoind binaries
  • Loading branch information
jnewbery authored and adiabat committed May 9, 2017
1 parent 6f9307a commit 7e79b4d
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 165 deletions.
19 changes: 13 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@ language: go
go:
- 1.8
sudo: required
cache:
directories:
- bitcoin-0.14.1
- litecoin-0.13.2
install:
- sudo apt-get update
- sudo apt-get install python3 python3-pip python3-requests
- sudo apt-get install bitcoind
- wget https://download.litecoin.org/litecoin-0.13.2/linux/litecoin-0.13.2-x86_64-linux-gnu.tar.gz
- tar xvf litecoin-0.13.2-x86_64-linux-gnu.tar.gz
- sudo apt-get install python3 python3-pip
# Download bitcoind and add it to the path
- ls bitcoin-0.14.1/bin/bitcoind || (wget https://bitcoin.org/bin/bitcoin-core-0.14.1/bitcoin-0.14.1-x86_64-linux-gnu.tar.gz && tar xvf bitcoin-0.14.1-x86_64-linux-gnu.tar.gz)
- PATH=$PATH:$PWD/bitcoin-0.14.1/bin
# Download bitcoind and add it to the path
- ls litecoin-0.13.2/bin/litecoind || (wget https://download.litecoin.org/litecoin-0.13.2/linux/litecoin-0.13.2-x86_64-linux-gnu.tar.gz && tar xvf litecoin-0.13.2-x86_64-linux-gnu.tar.gz)
- PATH=$PATH:$PWD/litecoin-0.13.2/bin
- sudo pip3 install --upgrade pip
- sudo pip3 install websocket-client
- pip3 install --upgrade pip
- pip3 install requests
- pip3 install websocket-client
script:
- go get -v ./...
- go test ./...
Expand Down
5 changes: 4 additions & 1 deletion cmd/litpy/litrpc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#!/usr/bin/python3
#!/usr/bin/env python3
# Copyright (c) 2017 The lit developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Python interface to lit"""

import json
Expand Down
77 changes: 77 additions & 0 deletions test/bcnode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The lit developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Classes representing bitcoind and litecoind nodes
BCNode and LCNode represent a bitcoind and litecoind node respectively.
They can be used to start/stop a bitcoin/litecoin node and communicate
with it over RPC."""
import json
import os
import random
import subprocess
import sys
import time

import requests # `pip install requests`

class BCNode():
"""A class representing a bitcoind node"""
bin_name = "bitcoind"
short_name = "bc"
min_version = 140000

def __init__(self, i, tmd_dir):
self.data_dir = tmd_dir + "/%snode%s" % (self.__class__.short_name, i)
os.makedirs(self.data_dir)

self.args = ["-regtest", "-datadir=%s" % self.data_dir, "-rpcuser=regtestuser", "-rpcpassword=regtestpass", "-rpcport=18332"]
self.msg_id = random.randint(0, 9999)
self.rpc_url = "http://regtestuser:[email protected]:18332"

def start_node(self):
try:
self.process = subprocess.Popen([self.__class__.bin_name] + self.args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except FileNotFoundError:
print("%s not found on path. Please install %s" % (self.__class__.bin_name, self.__class__.bin_name))
sys.exit(1)

# Wait for process to start
while True:
if self.process.poll() is not None:
raise Exception('%s exited with status %i during initialization' % (self.__class__.bin_name, self.process.returncode))
try:
resp = self.getinfo()
if resp.json()['error'] and resp.json()['error']['code'] == -28:
# RPC is still in warmup. Sleep some more.
continue
# Check that we're running at least the minimum version
assert resp.json()['result']['version'] > self.__class__.min_version
break # break out of loop on success
except requests.exceptions.ConnectionError as e:
time.sleep(0.25)

def send_message(self, method, params):
self.msg_id += 1
rpcCmd = {
"method": method,
"params": params,
"jsonrpc": "2.0",
"id": str(self.msg_id)
}
payload = json.dumps(rpcCmd)

return requests.post(self.rpc_url, headers={"Content-type": "application/json"}, data=payload)

def __getattr__(self, name):
"""Dispatches any unrecognised messages to the websocket connection"""
def dispatcher(**kwargs):
return self.send_message(name, kwargs)
return dispatcher

class LCNode(BCNode):
"""A class representing a litecoind node"""
bin_name = "litecoind"
short_name = "lc"
min_version = 130200
36 changes: 36 additions & 0 deletions test/litnode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The lit developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Class representing a lit node
LitNode represents a lit node. It can be used to start/stop a lit node
and communicate with it over RPC."""
import os
import subprocess

from litpy import litrpc

LIT_BIN = "%s/../lit" % os.path.abspath(os.path.dirname(__file__))

class LitNode():
"""A class representing a Lit node"""
def __init__(self, i, tmp_dir):
self.data_dir = tmp_dir + "/litnode%s" % i
os.makedirs(self.data_dir)

# Write a hexkey to the privkey file
with open(self.data_dir + "/privkey.hex", 'w+') as f:
f.write("1" * 63 + str(i) + "\n")

self.args = ["-dir", self.data_dir]

def start_node(self):
self.process = subprocess.Popen([LIT_BIN] + self.args, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

def add_rpc_connection(self, ip, port):
self.rpc = litrpc.LitConnection(ip, port)
self.rpc.connect()

def __getattr__(self, name):
return self.rpc.__getattr__(name)
Loading

0 comments on commit 7e79b4d

Please sign in to comment.