Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Fix failing test_project.py - merge to main #87

Closed
wants to merge 10 commits into from
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ venv/
ENV/
env.bak/
venv.bak/
.vscode/

# Spyder project settings
.spyderproject
Expand All @@ -128,4 +129,4 @@ dmypy.json
# Pyre type checker
.pyre/

example/test/build
example/test/build
6 changes: 1 addition & 5 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -395,11 +395,7 @@ logging-modules=logging
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
confidence=

# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
Expand Down
2 changes: 2 additions & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
temp/
test_app/
52 changes: 52 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Pytest Validation for DUNE

# WARNING

These tests are destructive. Do NOT run them when there is important data in your container!

## Getting Started

Make sure you have a recent version of `pytest` installed. Development was initially done with version `7.1`.

Pytest can be installed with [pip](https://pypi.org/project/pytest/)
or - very likely - is part of your Linux distribution. Additionally,
the source is available [here](https://github.com/pytest-dev/pytest).

Following the [instructions](../README.md#getting-started) for
building and installing DUNE.

## Running the Tests

From the root directory, execute all the tests as follows:
```
$ pytest ./tests/
```

If you need to run a single test, it can be done similar to the example below:
```
$ pytest ./tests/test_version.py
```

More information regarding running and developing tests with pytest
can be found [here](https://docs.pytest.org/en/stable/).

## What to do when you find a defect?

Check DUNE's github site to see if the issue already exists. Make sure
that your issue isn't already fixed in the main DUNE branch by
rerunning the tests there if you haven't already. If the problem is
repeatable in the main branch and no issue already exists, add a new
issue including what platform (e.g. Ubuntu 20.04 x86, OSX arm64, etc),
complier, python version, pytest version, and steps we might need to
repeat the defect.

## Adding new tests

Make sure any new tests follow the same basic format as exist
here. You can use [test_version.py](test_version.py) as a sample.

Note that you will NEED to run pylint against the tests. This can be
done from the root directory like this:
```
$ pylint ./tests/<my_new_test>.py
```
15 changes: 15 additions & 0 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


import os

# Find path for tests:
TEST_PATH = os.path.dirname(os.path.abspath(__file__))

# Set path for executable:
DUNE_EXE = os.path.split(TEST_PATH)[0] + "/dune"
print("Executable path: ", DUNE_EXE)

# Default addresses
DEFAULT_HTTP_ADDR="127.0.0.1:8888"
DEFAULT_P2P_ADDR="0.0.0.0:9876"
DEFAULT_SHIP_ADDR="127.0.0.1:8080"
24 changes: 24 additions & 0 deletions tests/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
wasm-runtime = eos-vm
abi-serializer-max-time-ms = 15
chain-state-db-size-mb = 65536
# chain-threads = 2
contracts-console = true
http-server-address = 127.0.0.1:9991
p2p-listen-endpoint = 0.0.0.0:9992
state-history-endpoint = 127.0.0.1:9993
verbose-http-errors = true
# http-threads = 2
agent-name = "DUNE Test Node"
net-threads = 2
max-transaction-time = 100
producer-name = eosio
enable-stale-production = true
# producer-threads = 2
# trace-history = false
# chain-state-history = false
resource-monitor-not-shutdown-on-threshold-exceeded=true

plugin = eosio::chain_api_plugin
plugin = eosio::http_plugin
plugin = eosio::producer_plugin
plugin = eosio::producer_api_plugin
141 changes: 141 additions & 0 deletions tests/container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import os
import platform
import subprocess


class container:
_container_name = ""
_image_name = ""

def __init__(self, container_name='dune_container', image_name='dune:latest'):
self._container_name = container_name
self._image_name = image_name
self._debug = True

@staticmethod
def abs_host_path(directory):
abs_path = os.path.abspath(directory)
if platform.system() == 'Windows':
# remove the drive letter prefix and replace the separators
abs_path = abs_path[3:].replace('\\', '/')
else:
abs_path = abs_path[1:]

return '/host/' + abs_path

def get_container(self):
return self._container_name

def get_image(self):
return self._image_name

def execute_docker_cmd(self, cmd):
with subprocess.Popen(['docker'] + cmd,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:
stdout, stderr = proc.communicate()
if self._debug:
print('docker '+' '.join(cmd))
print(stdout.decode('UTF-8'))
print(stderr.decode('UTF-8'))
return [stdout.decode('UTF-8'), stderr.decode('UTF-8'), proc.poll()]

def file_exists(self, file_name):
return self.execute_cmd(['test', '-f', file_name])[2] == 0

def dir_exists(self, directory):
return self.execute_cmd(['test', '-d', directory])[2] == 0

def tar_dir(self, file_name, directory):
return self.execute_cmd(['tar', 'cvzf', file_name + '.tgz', directory])

def untar(self, directory):
return self.execute_cmd(['tar', 'xvzf', directory])

def cp_to_host(self, container_file, host_file):
return self.execute_docker_cmd(
['cp', self._container_name + ":" + container_file, host_file])

def cp_from_host(self, host_file, container_file):
return self.execute_docker_cmd(
['cp', host_file, self._container_name + ":" + container_file])

def rm_file(self, file_name):
self.execute_cmd(['rm', '-rf', file_name])

def find_pid(self, process_name):
stdout, _, _ = self.execute_cmd(['ps', 'ax'])
for line in stdout.splitlines(True):
if "PID TTY" in line:
continue
if process_name in line:
return line.split()[0]
return -1

def get_container_name(self):
return self._container_name

def commit(self):
self.execute_docker_cmd(['commit', 'dune', 'dune'])

def start(self):
print("Starting docker container [" + self._container_name + "]")
self.execute_docker_cmd(['container', 'start', self._container_name])

def stop(self):
print("Stopping docker container [" + self._container_name + "]")
self.execute_docker_cmd(['container', 'stop', self._container_name])

def destroy(self):
print("Destroying docker container [" + self._container_name + "]")
self.execute_docker_cmd(['container', 'stop', self._container_name])
self.execute_docker_cmd(['container', 'rm', self._container_name])

def execute_cmd_at(self, directory, cmd):
with subprocess.Popen(['docker', 'container', 'exec', '-w', directory,
self._container_name] + cmd) as proc:
proc.communicate()

def execute_cmd(self, cmd):
return self.execute_docker_cmd(
['container', 'exec', self._container_name] + cmd)

def execute_interactive_cmd(self, cmd):
with subprocess.Popen(['docker', 'container',
'exec', '-i', self._container_name] + cmd) as proc:
proc.communicate()

def execute_cmd2(self, cmd):
with subprocess.Popen(['docker', 'container',
'exec', self._container_name] + cmd) as proc:
proc.communicate()

def execute_bg_cmd(self, cmd):
return self.execute_cmd(cmd + ['&'])

# possible values for the status: created, restarting, running, removing, paused, exited, dead
def check_status(self, status):
stdout, _, _ = self.execute_docker_cmd(['ps', '--filter',
'status=' + status])
for line in stdout.splitlines(True):
if "CONTAINER ID" in line:
continue
if self._container_name in line:
return True
return False

# check if the container is still exists and was not deleted
def exists(self):
stdout, _, _ = self.execute_docker_cmd(['ps', '--filter',
'name=' + self._container_name])
for line in stdout.splitlines(True):
if "CONTAINER ID" in line:
continue
if self._container_name in line:
return True
return False

# create a new container
def create(self):
print("Creating docker container [" + self._container_name + "]")
self.execute_docker_cmd(["run", "--name=" + self._container_name,
self._image_name, "exit"])
31 changes: 31 additions & 0 deletions tests/show_untested_options.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh

# This file MUST remain co-located with the files to work.


# Find paths to the tests and the dune executable.
SCRIPT=`readlink -f "$0"`
TEST_DIR=`dirname "$SCRIPT"`
DUNE_DIR=`dirname "$TEST_DIR"`
DUNE="$DUNE_DIR/dune"

# Get a list of the options.
options=`$DUNE --help | grep -o "^ --[a-z\-]*"`

# Get a list of the test files.
files=`find "$TEST_DIR" | grep "[.]py\$"`

# Return value. Initially set to zero/success.
rv=0

# Search for each option.
for opt in $options; do
if ! grep --quiet \"$opt\" $files ; then
# Report missing options and set the return value to non-zeor/failure.
echo "Missing option: $opt"
rv=1
fi
done

# Report success/fail.
exit $rv
21 changes: 21 additions & 0 deletions tests/test_all_options_tested.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python3

"""Test DUNE Version_

This script tests that the compiled binary produce expected output
in response to `--version` option.
"""



import subprocess

from common import TEST_PATH


def test_all_options_tested():
"""Test that all the options from the output of `--help` are in the various test files."""

script=TEST_PATH+"/show_untested_options.sh"

subprocess.run(script, check=True)
54 changes: 54 additions & 0 deletions tests/test_boostrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3

"""Test DUNE bootstrap

These options are tested:
--create-key
--import-dev-key
--bootstrap-system-full
"""

import subprocess

from common import DUNE_EXE

# Globals
NODE_NAME = "my_node"
ACCT_NAME = "myaccount"



def test_booststrap():

# Remove any existing containers.
subprocess.run([DUNE_EXE,"--destroy-container"], check=True)

# Start the new node.
subprocess.run([DUNE_EXE,"--start",NODE_NAME], check=True)

# Create an account.
subprocess.run([DUNE_EXE,"--create-account",ACCT_NAME], check=True)

# Create a key. Get it to a var as well.
public_key = None
private_key = None
stdout_result = subprocess.run([DUNE_EXE,"--create-key"], check=True, stdout=subprocess.PIPE)
result_list = stdout_result.stdout.decode().split("\n")
for entry in result_list:
# ignore empty entries.
if len(entry) == 0:
continue
items = entry.split(': ')
if len(items) == 2:
if items[0] == "Private key":
private_key = items[1]
elif items[0] == "Public key":
public_key = items[1]
assert private_key is not None

# Import the key.
subprocess.run([DUNE_EXE,"--import-dev-key",private_key], check=True)

# Bootstrap the system.
subprocess.run([DUNE_EXE, "--bootstrap-system-full"], check=True)
assert False # Asserting because --bootstrap-system-full doesn't currently behave correctly.
Loading