Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qa test #5

Open
wants to merge 3 commits into
base: vin_unique_check
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions qa/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
**Application Test suite**
--------------------------
**Requirements**

- Install Python 2.7
- Download Sidechain SDK

**Additional settings**

Setup these environment variables:
```
BITCOINCLI: path to zen-cli
BITCOIND: path to zend
APP_JAR: sidechain app jar
APP_LIB: sidechain app lib folder
APP_MAIN: main sidechain class to run
SIDECHAIN_SDK: path to SDK folder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems, that we need to extract STF and Bootstaping tool to the separate git repo. Keep them generalized and let to set them as a submodules. So no need to copy that sources or keep SDK. Moreover it will let developers to fork these modules and change depends on their needs.
What do you think about this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree could be good to separate them from the SDK , since both the SDK and customer apps will use them for testing.
do you know how submodules loading works in python ? maybe we need anyway to set an env variable to the module

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, that we can use a git submodule, so the code folder will be placed in the place specified by the sidechain developer for his specific project.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, could be ok, in this way we can use relative path in python import

```

**Execution**

You can run all tests using command.

```
python run_all.py
```

Or run individual test using command like this:

```
python lambo_test1_standardWorkflow.py
```

Example for Linux environment:

```
export BITCOINCLI=/var/horizen/lamboRegistry/zend_oo/src/zen-cli
export BITCOIND=/var/horizen/lamboRegistry/zend_oo/src/zend
export SIDECHAIN_SDK=/var/horizen/lamboRegistry/Sidechains-SDK
export APP_JAR=/var/horizen/lamboRegistry/lambo-registry/target/lambo-registry-0.1.0.jar
export APP_LIB=/var/horizen/lamboRegistry/lambo-registry/target/lib/*
export APP_MAIN=io.horizen.lambo.CarRegistryApp

python run_all.py --tmpdir=./_tmp
```

103 changes: 103 additions & 0 deletions qa/basicTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python2
import sys
import os
sys.path.append(os.getenv("SIDECHAIN_SDK", "") + '/qa/')
from SidechainTestFramework.sc_test_framework import SidechainTestFramework
from SidechainTestFramework.sc_boostrap_info import SCNodeConfiguration, SCCreationInfo, MCConnectionInfo, \
SCNetworkConfiguration
from test_framework.util import assert_true, initialize_chain_clean, start_nodes, \
websocket_port_by_mc_node_index, connect_nodes_bi, disconnect_nodes_bi
from SidechainTestFramework.scutil import bootstrap_sidechain_nodes, start_sc_nodes, generate_next_blocks, connect_sc_nodes, initialize_default_sc_chain_clean
from SidechainTestFramework.sc_forging_util import *
from httpCalls.transaction.spendForgingStake import spendForgingStake

"""
Basic class for test - extend this to create your own test
This basic class handles the bootstrap of the sidechain and exposes a bounch of commonly used methods (convertInitialForging and generateOneBlock)
"""
class BasicTest(SidechainTestFramework):

def __init__(self, sc_nodes = 1):
print "---------"
print "Initializing test " + str(self.__class__)
#check variable configuration
assert_true(sc_nodes > 0, "Sidechain nodes must be > 0")
assert_true(len(os.getenv("BITCOINCLI", "")) > 0, "BITCOINCLI env var must be set")
assert_true(len(os.getenv("BITCOIND", "")) > 0, "BITCOIND env var must be set")
assert_true(len(os.getenv("SIDECHAIN_SDK", "")) > 0, "SIDECHAIN_SDK env var must be set")
assert_true(len(os.getenv("APP_JAR", "")) > 0, "APP_JAR env var must be set")
assert_true(len(os.getenv("APP_LIB", "")) > 0, "APP_LIB env var must be set")
assert_true(len(os.getenv("APP_MAIN", "")) > 0, "APP_MAIN env var must be set")
print "Configuration of this test:"
print " 1 mainchain node"
print " {} sidechains node".format(sc_nodes)
self.number_of_mc_nodes = 1
self.number_of_sidechain_nodes = sc_nodes

def setup_chain(self):
initialize_chain_clean(self.options.tmpdir, self.number_of_mc_nodes)

def setup_network(self, split = False):
print("Initializing Mainchain nodes...")
self.nodes = self.setup_nodes()
self.sync_all()
print("OK\n")

def setup_nodes(self):
return start_nodes(self.number_of_mc_nodes, self.options.tmpdir)

def sc_setup_chain(self):
mc_node_1 = self.nodes[0]

sc_node_configuration = []
for x in range(1, self.number_of_sidechain_nodes +1):
sc_node_configuration.append(
SCNodeConfiguration(
MCConnectionInfo(address="ws://{0}:{1}".format(mc_node_1.hostname, websocket_port_by_mc_node_index(0)))
)
)
network = SCNetworkConfiguration(SCCreationInfo(mc_node_1, 600, 1000), *sc_node_configuration)
self.sc_nodes_bootstrap_info = bootstrap_sidechain_nodes(self.options.tmpdir, network)



def sc_setup_network(self, split = False):
print("Initializing {} Sidechain nodes...".format(self.number_of_sidechain_nodes))
self.sc_nodes = self.sc_setup_nodes()
if (self.number_of_sidechain_nodes > 1):
for x in range(1, self.number_of_sidechain_nodes):
print('Connecting sidechain node node0 with node{}'.format(x))
connect_sc_nodes(self.sc_nodes[0], x)
self.sc_sync_all()
print("OK\n")

def sc_setup_nodes(self):
lib_separator = ":"
if sys.platform.startswith('win'):
lib_separator = ";"
app_jar = os.getenv("APP_JAR", "")
app_lib = os.getenv("APP_LIB", "")
app_main = os.getenv("APP_MAIN", "")

path = []
for x in range(1, self.number_of_sidechain_nodes + 1):
path .append(app_jar + lib_separator + app_lib + " " + app_main)

return start_sc_nodes(self.number_of_sidechain_nodes, self.options.tmpdir, None, None, path)

#spends initial forgin stake to create a stadard coinbox
def convertInitialForging(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of spending initial forging stake I would suggest to make a forward transfer.
If you will spend the stake and will not create another one, than in 2 epochs there will be no stakes registered for forging, so will not be able to produce new sc blocks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!

sc_node1 = self.sc_nodes[0]
response = sc_node1.wallet_allBoxes()
box = response["result"]["boxes"][0]
box_id = box["id"]
publicKey = box["proposition"]["publicKey"]
blockSignPublicKey = box["blockSignProposition"]["publicKey"]
vrfPubKey = box["vrfPubKey"]["publicKey"]
convertedForgingStakeValue = box["value"]
#spends forgin stake to create a stadard coinbox
spendForgingStake(sc_node1, box_id, convertedForgingStakeValue, 0, publicKey, blockSignPublicKey, vrfPubKey)
return publicKey, convertedForgingStakeValue

def generateOneBlock(self, sidechainNode):
return generate_next_blocks(sidechainNode, "", 1)[0]
1 change: 1 addition & 0 deletions qa/httpCalls/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Empty file added qa/httpCalls/block/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions qa/httpCalls/block/best.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#executes a block/best call
def http_block_best(sidechainNode):
response = sidechainNode.block_best()
return response['result']['block']



Empty file added qa/httpCalls/carApi/__init__.py
Empty file.
18 changes: 18 additions & 0 deletions qa/httpCalls/carApi/acceptCarSellOrder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import json
#create and send a custom transaction carApi/acceptCarSellOrder
def acceptCarSellOrder(sidechainNode, carSellOrderId, fee):
j = {\
"carSellOrderId": carSellOrderId,\
"fee": fee \
}
request = json.dumps(j)
response = sidechainNode.carApi_acceptCarSellOrder(request)
transactionBytes = response["result"]["transactionBytes"]
j = {\
"transactionBytes": transactionBytes,\
}
request = json.dumps(j)
response = sidechainNode.transaction_sendTransaction(request)
return response["result"]["transactionId"]


26 changes: 26 additions & 0 deletions qa/httpCalls/carApi/createCar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
#create and send a custom transaction carApi/createCar
#returns (<success>, <transactionid>)
def createCar(sidechainNode, vin, year, model, color, proposition, fee):
j = {\
"vin": vin,\
"year": year,\
"model": model,\
"color": color, \
"proposition": proposition, \
"fee": fee \
}
request = json.dumps(j)
response = sidechainNode.carApi_createCar(request)
if ("error" in response):
return (False, None)
else:
transactionBytes = response["result"]["transactionBytes"]
j = {\
"transactionBytes": transactionBytes,\
}
request = json.dumps(j)
response = sidechainNode.transaction_sendTransaction(request)
return (True, response["result"]["transactionId"])


20 changes: 20 additions & 0 deletions qa/httpCalls/carApi/createCarSellOrder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json
#create and send a custom transaction carApi/createCarSellOrder
def createCarSellOrder(sidechainNode, carBoxId, buyerProposition, sellPrice, fee):
j = {\
"carBoxId": carBoxId,\
"buyerProposition": buyerProposition,\
"sellPrice": sellPrice,\
"fee": fee \
}
request = json.dumps(j)
response = sidechainNode.carApi_createCarSellOrder(request)
transactionBytes = response["result"]["transactionBytes"]
j = {\
"transactionBytes": transactionBytes,\
}
request = json.dumps(j)
response = sidechainNode.transaction_sendTransaction(request)
return response["result"]["transactionId"]


Empty file.
17 changes: 17 additions & 0 deletions qa/httpCalls/transaction/sendCoinsToAddress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import json
#execute a transaction/sendCoinsToAddress call
def sendCoinsToAddress(sidechainNode, address, amount, fee):
j = {\
"outputs": [ \
{ \
"publicKey": address, \
"value": amount \
} \
], \
"fee": fee \
}
request = json.dumps(j)
response = sidechainNode.transaction_sendCoinsToAddress(request)
return response["result"]["transactionId"]


26 changes: 26 additions & 0 deletions qa/httpCalls/transaction/spendForgingStake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import json
#execute a transaction/spendForgingStake call
def spendForgingStake(sidechainNode, inputBoxId, valueRegular, valueForging, publicKey, blockSignPublicKey, vrfPubKey):
j = {\
"transactionInputs": [ \
{ \
"boxId": inputBoxId \
} \
],\
"regularOutputs": [\
{\
"publicKey": publicKey,\
"value": valueRegular\
}\
],\
"forgerOutputs": [\
{\
"publicKey": publicKey,\
"blockSignPublicKey": blockSignPublicKey,\
"vrfPubKey": vrfPubKey,\
"value": valueForging\
}\
],\
}
request = json.dumps(j)
sidechainNode.transaction_spendForgingStake(request)
Empty file added qa/httpCalls/wallet/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions qa/httpCalls/wallet/allBoxes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#executes a wallet/allBoxes call
def http_wallet_allBoxes(sidechainNode):
response = sidechainNode.wallet_allBoxes()
return response['result']['boxes']



7 changes: 7 additions & 0 deletions qa/httpCalls/wallet/balance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#executes a wallet/balance call
def http_wallet_balance(sidechainNode):
response = sidechainNode.wallet_balance()
return response['result']['balance']



8 changes: 8 additions & 0 deletions qa/httpCalls/wallet/createPrivateKey25519.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import json
#create and send a custom transaction block/best
def http_wallet_createPrivateKey25519(sidechainNode):
response = sidechainNode.wallet_createPrivateKey25519()
return response['result']['proposition']['publicKey']



Loading