def calculate(self, expression): """ :param expression: string with expression to send to Calc App :return: ProtocolReply """ start_time = time.time() if self._mock: try: result = evaluate(expression) except ZeroDivisionError: result = None except Exception as e: result = "Platform {}: exception occurred on calculate: {}".format( self.name, e) exprint() tprint("calculate (with fail) elapsed {}".format(time.time() - start_time)) return proto_failure(result, -2) tprint("calculate elapsed {}".format(time.time() - start_time)) return proto_success(result) # NOTE: mock code just ended here. To avoid nesting there is no else, just flat code # TODO: optimize code - now it's way to hard (just send/receive and so much code!!!) c = self.request(new_message(self._io_interface, "send", expression), None, [], {}, timeout=2.0) # TODO: decrease timeout c_state = self._pop_request_state(c) if not self._request_state_is_success(c_state): tprint( "calculate (with fail result) elapsed {}".format(time.time() - start_time)) return proto_failure("IO failed to send data") c = self.request(new_message(self._io_interface, "receive"), None, [], {}, timeout=2.0) # TODO: decrease timeout c_state = self._pop_request_state(c) if not self._request_state_is_success(c_state): tprint( "calculate (with fail result) elapsed {}".format(time.time() - start_time)) return proto_failure("IO failed to receive response") # TODO: convert from string to number tprint("calculate elapsed {}".format(time.time() - start_time)) result = PM.parse(c_state["__message__"]).reply_data["value"] if isinstance( result, (list, tuple) ): # NOTE: softwarerunner returns list but stream_io returns single item result = result[0] if result.strip() == 'None': result = None else: try: result = int(result) except ValueError: result = float(result) return proto_success(result)
def _platformix_call_test(self): env = self._env value = [0, 101, 202] expected = [value[2], value[1], value[0]] r = env.transaction("@platform_b", new_message("platformix", "call", "call_test", *value), er.all_success, more_info=True) if r["result"] is False: eprint("Failed call_test transaction") return False r = r["replies"]["platform_b"] r_data = r.reply_data["value"] compare_failed = False if not isinstance(r_data, list): compare_failed = True elif len(r_data) != len(expected): compare_failed = True else: for i in range(0, len(expected)): if r_data[i] != expected[i]: compare_failed = True break if compare_failed: eprint("Reply of call_test: {} is not that expected: {}!".format(r.reply_data["value"], expected)) return False return True
def _run(self, context, runs=None): # TODO: threaded arg if runs is None: runs = self._runs if runs <= 0: runs = 0 self._complete = 0 self._remaining = runs if self._remaining > 0: self._reply(context, PM.notify("started sequence")) while self._remaining > 0: assert self._expr is not None, "Sequencer {} wasn't started!".format(self.name) start_time = time.time() expr_result = next(self._expr) # TODO: replace assertions with proto_fails? assert isinstance(expr_result, (list, tuple)), "Expression should return list or tuple" assert len(expr_result) > 0, "Expression should return list or tuple with length at least" \ "3 if there is no channel specification and " \ "4 if there is channel specification" if isinstance(expr_result[0], str) and expr_result[0][0] in ('@', '#'): channel = expr_result.pop(0) else: channel = None assert len(expr_result) >= 3, "Expression should return list or tupple with length at least" \ "3 if there is no channel specification and " \ "4 if there is channel specification" request_message = new_message(*expr_result) c = self.request(request_message, None, [], {}, channel=channel, store_state=False) # NOTE: used default request handler (which just waits for success or failure reply) tprint("sequencer {} request elapsed {}".format(self.name, time.time()-start_time)) # TODO: option to treat request completed when specific message is passed by over special interface self._complete += 1 self._remaining -= 1 return proto_success({"breaked": runs != self._complete, "runs_completed": self._complete}, None)
def _start(self, reply_contexts): """ 1. Update's host from parent platform if necessary 2. Connects to a Caller :return: True if started successfully, otherwise - False """ if self._port is None and self._service is None: eprint( "Platform {} failed to start - port or service should be specified" .format(self.name)) return proto_failure( "Platform {} failed to start - port or service should be specified" ) if self._port is not None and self._service is not None: eprint( "Platform {} failed to start - specify only port or service, but not both" .format(self.name)) return proto_failure( "Platform {} failed to start - port or service should be specified" ) if self._host is None and self.parent is not None: c = self.request( new_message("platformix", "get", "host"), self._generic_request_handler, [], { "on_success": lambda d: setattr(self, "_host", d["host"]), "on_failure": lambda d: eprint("Failed to get host due to {}:{}".format( d["errcode"], d["state"])) }) if self._host is None: eprint("Platform {} failed to start - can't get host".format( self.name)) return proto_failure("Failed to start - can't get host") try: self._connection = rpyc.connect(self._host, self._port) # TODO: use service instead of port if it's specified if self._args is not None: self._connection.root.set_args(copy.copy(self._args)) result = self._connection.root.run() except Exception as e: self._connection = None eprint("Platform {} failed to start due to exception {}".format( self.name, e)) exprint() return proto_failure("Failed to start due to exception {}", -2) if result is False: self._connection = None eprint("Platform {} failed to start: rpyc server returned False". format(self.name)) return proto_failure("RPYC server returned False") if result and not self._mock: if self._start_sequence is not None and len( self._start_sequence) > 0: self.rpyc_send(self._start_sequence) return super(SoftwareRunner, self)._start(reply_contexts)
def _platformix_getset_test(self): env = self._env value = time.time() if env.transaction("@platform_b", new_message("platformix", "set", "tag", value), er.all_success) is False: eprint("Failed to set property") return False r = env.transaction("@platform_b", new_message("platformix", "get", "tag"), er.all_success, more_info=True) if r["result"] is False: eprint("Failed to get property") return False r = r["replies"]["platform_b"] if r.reply_data["tag"] != value: eprint("Value of property: {} is not that expected: {}!".format(r.reply_data["tag"], value)) return False if env.transaction("@platform_b", new_message("platformix", "set", "__shouldnt_exists__", value), er.all_fail) is False: eprint("Failed check of setting wrong property (expected to fail, but succeed)") return False return True # TODO: enable code below # NOTE: code below is unreachable yet since exception during transaction now breaks whole process try: if env.transaction("@platform_b", new_message("platformix", "set", "__shouldnt_exists__"), er.all_fail) is False: eprint("Failed check set without necessary arguments (expected exception, but succeed)") return False eprint("Failed check set without necessary arguments (expected exception, but failed)") return False except TypeError as e: pass try: if env.transaction("@platform_b", new_message("platformix", "get"), er.all_fail) is False: eprint("Failed check get without necessary arguments (expected exception, but succeed)") return False eprint("Failed check get without necessary arguments (expected exception, but failed)") return False except TypeError as e: pass return True
def _test_arith(self, op, expected): """ Issues operation to a arith component and checks result against expected value """ r = self._env.transaction( "@calc_if", # TODO: specify channel via arg new_message("arith", *op), more_info=True) assert r["result"] is True, "Failed to complete transaction {}".format( ' '.join(str(o) for o in op)) if r["replies"]["calc_if"].reply_data[ "value"] != expected: # TODO: specify responder's name via arg return False return True
def _test_arith_crt(self, runs=None): # TODO: tell scoreboards about new test beginning (to be available get isolated test results) if runs is not None: args = [runs] else: args = [] r = self._env.transaction("#sequencer", new_message("sequencer", "run", *args), more_info=True) assert r[ "result"] is True, "Failed on sequence running for arith".format() # TODO: get scoreboards results and judge failed it or not return True
def _start(self, reply_contexts): """ Makes sure that incoming/outgoing streams are synchronised :return: True if all necessary actions complete successfully, otherwise - False """ # Flush any junk that could occur on app start (a common case example) # NOTE: Or you could wait in a loop for a specific message depending on app used if not self._mock: c = self.request(new_message(self._io_interface, "receive", -1), None, [], {}, timeout=2.0) # TODO: cleaning required for softwarerunner only # TODO: reduce receive timeout instead of increasing request timeout c_state = self._pop_request_state(c) if not self._request_state_is_success(c_state): return proto_failure("Failed to flush i/o on start") return super(Calc, self)._start(reply_contexts)
def check_scoreboards(self, include=None, exclude=None): try: r = self.transaction( "#scoreboard", new_message("platformix", "get", "scoreboard"), more_info=True) # TODO: add Scoreboard interface except Exception as e: eprint("Exception occurred on get scoreboard: {}".format(e)) eprint() return False if r["result"] is False: eprint("Failed to get scoreboard") return False if len(r["replies"]) == 0: eprint("No scoreboards found") return False print( "\n============================================================\n" "Scoreboards:") summary = {} errors = False for sname in r["replies"]: sdata = r["replies"][sname].reply_data["scoreboard"] print(" {}:\n{}".format(sname, pprint.pformat(sdata, indent=4))) for f in sdata: if f not in summary: summary[f] = sdata[f] else: try: summary[f] += sdata[f] except Exception as e: eprint( "Exception occurred on scoreboard summary update: {}" .format(e)) exprint() errors = True if len(r["replies"]) > 1: print("Summary:\n{}".format(pprint.pformat(summary))) print("") if errors or summary["errors"] > 0 or summary[ "unhandled"] > 0 or summary["requests"] != summary["success"]: return False return True
def _start(self, reply_contexts): """ 1. Update's host from parent platform if necessary 2. Connects to a Caller :return: True if started successfully, otherwise - False """ if self._port is None: eprint("Platform {} failed to start - port should be specified".format(self.name)) return proto_failure("Platform {} failed to start - port or service should be specified") if self._host is None and self.parent is not None: c = self.request(new_message("platformix", "get", "host"), self._generic_request_handler, [], {"on_success": lambda d: setattr(self, "_host", d["host"]), "on_failure": lambda d: eprint("Failed to get host due to {}:{}".format( d["errcode"], d["state"])) }) if self._host is None: eprint("Platform {} failed to start - can't get host".format(self.name)) return proto_failure("Failed to start - can't get host") try: timeout = time.time() + self._connect_timeout while True: try: if self._mock is None: self._sock = sock = socket.socket() sock.connect((self._host, self._port)) sock.settimeout(self._timeout) break except ConnectionRefusedError as e: if time.time() > timeout: raise e except Exception as e: self._sock = None eprint("Platform {} failed to start due to exception {}".format(self.name, e)) exprint() return proto_failure("Failed to start due to exception {}", -2) return super(TcpIO, self)._start(reply_contexts)
def _platformix_smoke_test(self, tests_list=None): env = self._env # Accepts following values in tests_list: # "success, fake, report" # "no fail check" # TODO: check if there is required amount of responses # Start # NOTE: startup is made by testenv itself now # assert env.transaction("#platforms", new_message("platformix", "start")) is True, "Failed to start platforms" # Test errors control if tests_list is not None: tests_list = list(tests_list) if tests_list is None or "[sanity check]" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[sanity check]")] if env.transaction( "@platform_b", fake_op_message("platformix", proto_failure("Failed by intent (fake_next_op, " "Single unit error in [all success] condition)"), on_channel="#platforms", on_message=new_message("platformix", "report", "is_running") ), er.all_success + er.none_fail) is False: eprint("Failed to set fake_next_op on [sanity check]") return False # NOTE: both all and none in condition above are for testing purpose # No fail since it's another channel if env.transaction("@platform_b", new_message("platformix", "report", "is_running"), er.none_fail) is False: # NOTE: none in condition above is testing purpose eprint("Failed to pass [report is_running] or avoid faking on [sanity check]") return False # No fail since it's another command if env.transaction("#platforms", new_message("platformix", "report", "running")) is False: eprint("Failed to pass [report running] or avoid faking on [sanity check]") return False # Fail as we told platform_b to do so if env.transaction("#platforms", new_message("platformix", "report", "is_running")) is True: eprint("Failed to pass faking or [all success] fail check on [sanity check]") return False if tests_list is None or "[single fail] success check" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[single fail] success check")] if env.transaction( "@platform_b", fake_op_message("platformix", proto_failure("Failed by intent (fake_next_op, Single unit error " "in [single fail] condition)"), on_channel="#platforms", execute=True )) is False: eprint("Failed to set fake_next_op on [single fail] success check") return False # No fail as we expecting that platform_b about to fail (NOTE: - no message filtering here) if env.transaction("#platforms", new_message("platformix", "report", "running"), er.fail("platform_b") + er.others_success) is False: eprint("Failed to pass [single fail] success check") return False if tests_list is None or "[any success] fail check" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[any success] fail check")] if env.transaction( "#platforms", fake_op_message("platformix", proto_failure("Failed by intent (fake_next_op, All fail " "on [any success] condition)"), on_channel="#platforms" )) is False: eprint("Failed to set fake_next_op on [any success] fail check") return False # Should fail if env.transaction("#platforms", new_message("platformix", "report", "running"), er.any_success) is True: eprint("Failed to pass [any success] fail check") return False if tests_list is None or "[not(any success)] fail check" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[not(any success)] fail check")] # Should pass as condition is negated if env.transaction("#platforms", new_message("platformix", "report", "running"), [("any", "success", True)]) is True: eprint("Failed to pass [not(any success)] fail check") return False if tests_list is None or "[any fail] success check" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[any fail] success check")] if env.transaction( "@platform_b", fake_op_message("platformix", proto_failure("Failed by intent (fake_next_op, Should pass " "as condition is negated)"), on_channel="#platforms" )) is False: eprint("Failed to set fake_next_op on [any fail] success check") return False # Should pass as one item failed, as expected if env.transaction("#platforms", new_message("platformix", "report", "running"), er.any_fail) is False: eprint("Failed to pass [any fail] success check") return False # Check request without response (should fail) if tests_list is None or "[no response] fail check" in tests_list: if tests_list is not None: del tests_list[tests_list.index("[no response] fail check")] if env.transaction("__void__", new_message(None, "platformix", "report", "running"), er.all_fail) is True: eprint("Failed to pass [no response] fail check") return False # Stop # NOTE: stop is made by testenv itself now # assert env.transaction("#platforms", new_message("platformix", "stop")) is True, "Failed to stop platforms" if tests_list is not None and len(tests_list) > 0: eprint("There is unknown tests left in a list: {}".format(tests_list)) return False return True