blob: e2678141f3af5a66c2ff3c17fb1c4c6a6c0128c6 [file] [log] [blame]
"""
This module implements command-line interface for running TPPT scripts directly from Python interpreter
without TnT UI.
To run TPPT as standalone, use test parameters stored in dry_run_parameters.json.
This file has content identical to history.json. Assuming that the json file has entry
"test_parameters", start dry run by executing:
> python standalone.py "test_parameters"
Currently Python 3.5 32-bit / 64-bit is supported.
Copyright (c) 2019, OptoFidelity OY
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the OptoFidelity OY.
Neither the name of the OptoFidelity OY nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import logging
import time
import sys
import threading
import ruamel.yaml as yaml
from LoopSequence import Context, STATE_WAITING
from drserver.server import DryRunThreadingServer
from drserver.tree import create_dry_run_tree
logger = logging.getLogger(__name__)
class UiProxyStandalone:
"""
Proxy class for UI object that is used in standalone scheme.
In this scheme script is executed directly by standalone Python interpreter without UI.
Most interface functions are for UI interaction and are just dummy implementations in this class.
"""
def __init__(self):
self.context = None
def create_dut_svg(self, x, y):
pass
def add_dut_point(self, x, y):
pass
#print("Touched {}, {}".format(x, y ))
def clear_dut_points(self):
pass
def dialog_to_continue(self, message):
print(message)
input("Press enter to continue...")
self.context.toggle_pause()
def script_failed(self, message):
print("Script failed: " + message)
def script_finished(self):
pass
def change_to_figure_page(self):
pass
def hide_loading_element(self):
pass
def append_images_to_figure_page(self, images):
pass
def set_indicators(self, text):
pass
def log(self, message):
logger.info(message)
def set_script_nodes(self, node_dict):
pass
def set_script_parameters(self, parameters):
pass
def set_script_callables(self, callables):
pass
def set_configuration_group_headers(self, names, selected):
pass
def sys_log(self, message):
logging.info(message)
def set_history_headers(self, headers):
pass
def script_ready(self, success):
pass
def start_dry_run_server(port=8000):
"""
Start dry run server that provides REST API that is compatible with the TnT Client
used by TPPT.
:param port: Server port.
"""
print("Starting dry run server.")
with open("drconfig.yaml") as file:
config = yaml.safe_load(file)
create_dry_run_tree(config, poll_input=True, dut_comm=True)
server = DryRunThreadingServer(("", port))
def run_server():
# This function blocks so it is ran in separate thread.
server.serve_forever(1000)
server_thread = threading.Thread(target=run_server)
server_thread.start()
return server, server_thread
def query_input(prompt, options=None, default=None):
while True:
if default is not None:
prompt = prompt + " [{}]".format(default)
result = input(prompt + ": ")
if default is not None and len(result) == 0:
return default
if options is None:
return result
if result not in options:
print("Invalid option '{}'!".format(result))
continue
return result
def run_standalone(name):
"""
Run TPPT script as standalone.
:param name: Name of history file entry to use to obtain script parameters.
"""
server, server_thread = start_dry_run_server()
ui = UiProxyStandalone()
# Add log handler to pass script logs to UI process.
root = logging.getLogger()
# Change level to affect which messages are shown in UI console.
root.setLevel(logging.INFO)
print("Loading scripts.")
# Create script context.
context = Context(ui)
ui.context = context
input("Connect DUT application and press enter.")
while True:
sequence_type = query_input("Run single sequence (s) or group (g)", ["s", "g"], "s")
if sequence_type == "g":
context.active_group = input("Group name: ")
print("Executing tests.")
context.execute_tests(run_configuration_group=True)
elif sequence_type == "s":
file_path = query_input("Parameter file", None, "dry_run_parameters.json")
# Load parameters from JSON file. The file has the same kind of content as history.yaml.
print("Loading script parameters '{}'.".format(name))
context.load(name, file_path=file_path)
print("Executing tests.")
context.execute_tests(run_configuration_group=False)
# Wait for execution to complete.
while context.state != STATE_WAITING:
time.sleep(1)
# Stop execution.
context.stop()
print("Finished")
result = query_input("Run another sequence (yes / no)", ["yes", "no"], "yes")
if result == "no":
break
server.server_close()
server_thread.join()
print("Server stopped")
if __name__ == "__main__":
if len(sys.argv) < 2:
raise Exception("Missing required argument: history file entry name.")
# Get history entry name from command line parameter list.
name = sys.argv[1]
run_standalone(name)