def test_setting_amplitude(loc): payload = Payload("loc", '{"coil_0_amplitude": 20}', 1) put_in_queue(payload, loc.inbox) time.sleep(0.1) payload = Payload("loc", '{"coil_0_amplitude": 0}', 1) put_in_queue(payload, loc.inbox) time.sleep(0.1) payload = Payload("loc", '{"single_pulse": "coil_0"}', 1) put_in_queue(payload, loc.inbox)
def test_forwarding(ctrl, capsys): locp = Payload("loc", "test", 12345) mrkp = Payload("mrk", "test", 12345) ctrl.queue.put(locp) ctrl.queue.put(mrkp) time.sleep(0.1) pipe = capsys.readouterr() assert ctrl.loc.get_nowait() == locp assert ctrl.mrk.get_nowait() == mrkp
def test_valid(): def pl(msg: str) -> Payload: return Payload(fmt="loc", msg=msg) assert not is_valid(Payload(fmt="mrk", msg='{"get":"test_xase"}')) assert not is_valid(pl('{"get":"test_xase"}')) assert is_valid(pl('{"get":"pointer_position"}')) assert is_valid( pl('{"coil_0_response": {"mepmaxtime": 25, "mepamplitude": 50, "mepmin": -25, "mepmax": 25} }' )) assert (is_valid( pl('{"coil_0_response": {"mepmaxtime": -1, "mepamplitude": 50, "mepmin": -25, "mepmax": 25} }' )) == False) assert (is_valid( pl('{"coil_0_response": {"mepmaxtime": 25, "mepamplitude": 50, "garbage": -25, "mepmax": 25} }' )) == False) assert (is_valid( pl('{"coil_0_response": {"mepmaxtime": 25, "mepamplitude": 50, "mepmin": -25, "mepmax": 999999999} }' )) == False) assert is_valid(pl('{"single_pulse":"COIL_0"}')) assert is_valid(pl('{"coil_0_amplitude": 20}')) assert is_valid(pl('{"coil_0_amplitude": -1}')) == False assert is_valid(pl('{"coil_0_target_index": 20}')) assert is_valid(pl('{"coil_0_target_index": -1}')) == False assert is_valid(pl('{"current_instrument": "POINTER"}')) assert is_valid(pl('{"garbage": "garbage"}')) == False
def test_latency_below_1ms(mrk, capsys): pl = Payload("mrk", "test_latency", pylsl.local_clock()) mrk.queue.put(pl) time.sleep(0.01) pipe = capsys.readouterr() latency = pipe.out.split("delayed by ")[1].split("ms")[0] assert float(latency) < 0.001
def test_latency_below_1ms(ctrl): locp = Payload("loc", "test", 12345) ctrl.queue.put(locp) t0 = time.time() while get_from_queue(ctrl.queue) is None: pass latency = time.time() - t0 assert latency < 0.001
def test_last_message_works(): pl = Payload(fmt="loc", msg='{"single_pulse":"COIL_0"}') lm = LastMessage() lm.update(pl) assert lm.expects(None) == 1 assert lm.expects(None) == 2 response = {lm.expect: 1} assert lm.expects(response) == 0 assert lm.expect == None
def decode_payload(buffer: bytes) -> Union[Payload, None]: try: fmt, msg, tstamp = json.loads(buffer.decode("ascii")) payload = Payload(fmt, msg, tstamp) if payload.fmt in ("cmd", "mrk", "loc"): return payload else: raise InvalidPayload(f"({fmt}, {msg}, {tstamp}) is no valid Payload") except json.decoder.JSONDecodeError: return None
def test_invalid(loc, mock): pl = Payload("loc", '{"garbage": "garbage"}', 12345) put_in_queue(pl, loc.inbox) recv = [] t0 = time.time() while t0 - time.time() < 5: pl = get_from_queue(loc.outbox) if pl is not None: recv.append(pl) if "garbage" in pl.msg: break assert "error" in pl.msg
def listen_and_queue(client: localiteClient, ignore: List[Dict[str, str]], queue: Queue) -> Union[Dict[str, Any], None]: """listen to the localice stream and forward to queue """ msg = client.listen() if msg is None or json.loads(msg) in ignore: return None else: print("LOC:MSG", msg) pl = Payload("mrk", msg, local_clock()) put_in_queue(pl, queue) return json.loads(msg)
def test_set_response(loc, mock): "coil_0_response" payload = Payload("loc", '{"get": "coil_0_amplitude"}', 12345) put_in_queue(payload, loc.inbox) recv = [] t0 = time.time() while t0 - time.time() < 5: pl = get_from_queue(loc.outbox) if pl is not None: recv.append(pl) if "coil_0_amplitude" in pl.msg: break assert "coil_0_amplitude" in pl.msg
def mrk(capsys): mrk = Queue() mrk = MRK(mrk) mrk.start() mrk.await_running() pipe = capsys.readouterr() assert "localite_marker" in pipe.out yield mrk killpayload = Payload("cmd", "poison-pill", 12345) mrk.queue.put(killpayload) time.sleep(0.5) pipe = capsys.readouterr() assert "Shutting MRK down" in pipe.out
def test_trigger(loc, mock): pl = Payload("loc", '{"single_pulse":"COIL_0"}', 12345) put_in_queue(pl, loc.inbox) recv = [] t0 = time.time() while t0 - time.time() < 5: pl = get_from_queue(loc.outbox) if pl is not None: recv.append(pl) if "coil_0_didt" in pl.msg: break assert "coil_0_didt" in pl.msg
def loc(mock): inbox = Queue() outbox = Queue() loc = LOC(address=(host, port), inbox=inbox, outbox=outbox) loc.start() loc.await_running() yield loc # shut down in less than 7s pl = Payload("cmd", "poison-pill", 12345) put_in_queue(pl, loc.inbox) t0 = time.time() d = 0 while loc.is_running.is_set() and d < 7: d = time.time() - t0 assert not loc.is_running.is_set()
def loc(): inbox = Queue() outbox = Queue() loc = LOC(address=(os.environ["LOCALITE_HOST"], 6666), inbox=inbox, outbox=outbox) loc.start() loc.await_running() yield loc pl = Payload("cmd", "poison-pill", 12345) put_in_queue(pl, loc.inbox) t0 = time.time() d = 0 while loc.is_running.is_set() and d < 7: d = time.time() - t0 assert not loc.is_running.is_set()
def run(self): # initialize clients and message expectations client = localiteClient(host=self.host, port=self.port) lastmessage = LastMessage() response = None self.is_running.set() print(f"LOC {self.host}:{self.port} started") while self.is_running.is_set(): try: payload = get_from_queue(self.inbox) if payload is None: if "status" in lastmessage.msg: response = listen_and_queue(client, ignore=[], queue=self.outbox) else: response = listen_and_queue(client, ignore=self.ignore, queue=self.outbox) # sometimes, the get: "target_index" is ignored. # in these cases, resend if "target_index" in lastmessage.msg: flevel = lastmessage.expects(response) if flevel >= 2: print("LOC:RESEND", lastmessage.msg) client.send(lastmessage.msg) lastmessage.counter = 0 else: print("LOC:RECV", payload) if payload.fmt == "cmd": if payload.msg == "poison-pill": self.is_running.clear() break else: # pragma no cover print("LOC:INVALID", payload) elif payload.fmt == "loc": client.send(payload.msg) lastmessage.update(payload) except Exception as e: # pragma no cover if self.is_running.set(): print("LOC:EXC", e) pl = Payload("mrk", "LOC:EXC " + str(e), local_clock()) put_in_queue(pl, self.outbox) self.is_running.clear() print("Shutting LOC down")
def test_sending_out(mrk): from os import environ if ("GITHUB_ACTION" in environ.keys() ): # the LSL sending seems to deadlock on their server return class Listener(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.running = False def run(self): sinfo = pylsl.resolve_byprop("name", "localite_marker")[0] stream = pylsl.StreamInlet(sinfo) msg = [] time.sleep(1) msg, t1 = stream.pull_chunk() self.running = True while self.running: try: msg, t1 = stream.pull_chunk() print(msg) if msg == []: time.sleep(0.001) else: self.running = False except pylsl.pylsl.LostError: break self.msg = msg self.t1 = t1 del stream l = Listener() l.start() while not l.running: pass t0 = pylsl.local_clock() pl = Payload("mrk", '{"test":"sending_out"}', t0) mrk.queue.put(pl) while l.running: pass assert abs(l.t1[0] - t0) < 0.001 assert l.msg[0][0] == pl.msg l.running = False
def kill(port: int = 6667, host: str = "127.0.0.1") -> bool: """kill the markerserver is already at that port args ---- host: str the ip of the markerserver (defaults to localhost) port: int the port number of the markerserver (defaults to 6667) returns ------- status: bool True if message was sent, False if server was not available """ return push_payload(Payload("cmd", "poison-pill", local_clock()))
def available(port: int = 6667, host: str = "127.0.0.1") -> bool: """test whether EXT is available at port args ---- host: str the ip of the EXT (defaults to localhost) port: int the port number of the EXT (defaults to 6667) returns ------- status: bool True if available, False if not """ return push_payload(Payload("cmd", "ping", local_clock()))
def push( fmt: str, msg: str, tstamp: int = None, host="127.0.0.1", port: int = 6667, verbose=True, ): "a functional interface to pushing a message" tstamp = tstamp or local_clock() payload = Payload(fmt, msg, tstamp) try: Client(host=host, port=port, verbose=verbose).push(payload) return True except (ConnectionRefusedError, ConnectionResetError) as e: if verbose and msg != "ping": # pragma no cover print(e) print(f"Localite EXT at {host}:{port} is not available") return False
def ctrl(capsys): queue = Queue() loc = Queue() mrk = Queue() ctrl = CTRL(queue, loc, mrk) ctrl.start() ctrl.await_running() pipe = capsys.readouterr() assert "CTRL started" in pipe.out assert ctrl.is_running.is_set() yield ctrl killpayload = Payload("cmd", "poison-pill", 12345) ctrl.queue.put(killpayload) time.sleep(0.1) assert ctrl.is_running.is_set() == False pipe = capsys.readouterr() assert "Shutting CTRL down" in pipe.out locp = ctrl.loc.get_nowait() mrkp = ctrl.mrk.get_nowait() assert mrkp == killpayload assert locp == killpayload
def test_get(loc, mock): msg = json.dumps({ "coil_0_response": { "mepmaxtime": 18, "mepamplitude": 50, "mepmin": -25, "mepmax": 25, } }) payload = Payload("loc", msg, 12345) put_in_queue(payload, loc.inbox) recv = [] t0 = time.time() while t0 - time.time() < 5: pl = get_from_queue(loc.outbox) if pl is not None: recv.append(pl) if "coil_0_response" in pl.msg: break assert pl.fmt == "mrk" assert "coil_0_response" in pl.msg
def test_cmd(ctrl, capsys): ctrl.queue.put(Payload("cmd", "test", 12345)) time.sleep(0.1) pipe = capsys.readouterr() assert "CTRL:CMD" in pipe.out
def pl(msg: str) -> Payload: return Payload(fmt="loc", msg=msg)
def test_last_message_raises(): pl = Payload(fmt="mrk", msg='{"single_pulse":"COIL_0"}') lm = LastMessage() with raises(ValueError): lm.update(pl)
def test_ping(ctrl, capsys): ctrl.queue.put(Payload("cmd", "ping", 12345)) time.sleep(0.1) pipe = capsys.readouterr() assert "ping" in pipe.out
def test_unknown(ctrl, capsys): ctrl.queue.put(Payload("unk", "test", 12345)) time.sleep(0.1) pipe = capsys.readouterr() assert "CTRL:FMT" in pipe.out