def test_zero(args, caps): c = Accum('zero://;' + args, size='1kb', name='server', context=ctx) assert c.dcaps == 0 c.open() assert c.dcaps == caps | c.DCaps.Process if caps & c.DCaps.PollIn: assert c.fd != None
def test_union(data, r): scheme = '''yamls:// - name: sub fields: - {name: s0, type: int8} - name: msg id: 10 fields: - {name: f0, type: union, union: [{name: i8, type: int8}, {name: string, type: string}, {name: sub, type: sub}, {name: array, type: 'int8[4]'}]} ''' url = Config.load(f'''yamls:// tll.proto: yaml name: yaml dump: scheme config.0: name: msg data.f0: %s ''' % data) url['scheme'] = scheme c = Accum(url) c.open() if r is None: with pytest.raises(TLLError): c.process() assert c.state == c.State.Error return c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, 0)] m = c.unpack(c.result[0]) assert m.as_dict() == {'f0': r}
def test_many(): scheme = '''yamls:// - name: msg id: 10 fields: - {name: f0, type: int8} ''' url = Config.load('''yamls:// tll.proto: yaml name: yaml dump: scheme autoclose: no config: - {name: msg, seq: 0, data.f0: 0} - {name: msg, seq: 1, data.f0: 1} - {name: msg, seq: 2, data.f0: 2} - {name: msg, seq: 3, data.f0: 3} ''') url['scheme'] = scheme c = Accum(url) c.open() for i in range(4): c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, j) for j in range(i + 1)] c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, j) for j in range(4)] for i in range(4): assert c.unpack(c.result[i]).as_dict() == {'f0': i}
def test(init, open, wait): c = Accum('timer://;{}'.format(init), name='timer', dump='yes', context=ctx) MSGID = 2 c.open(open) poll = select.poll() poll.register(c.fd, select.POLLIN) assert c.result == [] assert poll.poll(0) == [] for w in wait: if w is None: return ts = str2ms(w) print("Check {}: {:.3f}ms".format(w, ts)) assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn assert poll.poll(0) == [] c.process() assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn assert [m.msgid for m in c.result] == [] dt = time.time() assert poll.poll(2 * ts), [(c.fd == select.POLLIN)] dt = 1000 * (time.time() - dt) assert ts / 2 < dt < 2 * ts, "Sleep time {:.3f}ms not in range {:.3f}ms < {:.3f}ms)".format( dt, ts / 2, 2 * ts) c.process() assert [m.msgid for m in c.result] == [MSGID] c.result = [] assert poll.poll(0) == [] assert c.dcaps == 0
def test_post(clock, msg, wait): ms = str2ms(wait) c = Accum('timer://', name='timer', clock=clock, dump='yes', context=ctx) c.open() poll = select.poll() poll.register(c.fd, select.POLLIN) assert c.result == [] assert c.dcaps == 0 ts = ms / 1000 if msg == 'absolute': ts += time.time() c.post({'ts': ts}, name=msg) # nanoseconds assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn assert poll.poll(0) == [] dt = time.time() assert poll.poll(2 * ms) == [(c.fd, select.POLLIN)] dt = 1000 * (time.time() - dt) assert not ( ts / 2 < dt < 2 * ts), "Sleep time {:.3f}ms not in range {:.3f}ms < {:.3f}ms)".format( dt, ts / 2, 2 * ts) c.process() assert [m.msgid for m in c.result] == [2] assert c.dcaps == 0
def test(self): import termios p = termios.tcgetattr(self.m) print(p) p[0] = p[1] = p[3] = 0 p[4] = p[5] = termios.B9600 termios.tcsetattr(self.m, 0, p) c = Accum('serial://{}'.format(self.tty), context=ctx) c.open() assert c.fd != -1 poll = select.poll() poll.register(self.m, select.POLLIN) poll.register(c.fd, select.POLLIN) assert poll.poll(0) == [] c.post(b'xxx'); assert poll.poll(0) == [(self.m, select.POLLIN)] assert os.read(self.m, 100) == b'xxx' os.write(self.m, b'data') assert poll.poll(0) == [(c.fd, select.POLLIN)] c.process() assert [x.data.tobytes() for x in c.result] == [b'data']
def reader(context, filename): return Accum(f'file://{filename}', name='reader', dump='frame', dir='r', context='context', block='1kb')
def test_enum(): scheme = '''yamls:// - name: msg id: 10 enums: Enum: {type: int32, options.type: enum, enum: {A: 10, B: 20}} fields: - {name: f0, type: Enum} - {name: f1, type: Enum} ''' url = Config.load(f'''yamls:// tll.proto: yaml name: yaml dump: scheme config.0: name: msg data: f0: A f1: 20 ''') url['scheme'] = scheme c = Accum(url) c.open() c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, 0)] m = c.unpack(c.result[0]) assert m.f0 == m.f0.A assert m.f1 == m.f1.B
def test_simple(t, v): if isinstance(v, tuple): v, s = v else: s = str(v) scheme = f'''yamls:// - name: msg id: 10 fields: - {{name: f0, type: {t} }} ''' url = Config.load(f'''yamls:// tll.proto: yaml name: yaml dump: scheme config.0: name: msg ''') url['scheme'] = scheme url['config.0.data.f0'] = s c = Accum(url) c.open() c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, 0)] m = c.unpack(c.result[0]) assert m.as_dict() == {'f0': v}
def test_message(): scheme = '''yamls:// - name: sub fields: - {name: s0, type: int8} - name: msg id: 10 fields: - {name: f0, type: sub} ''' url = Config.load(f'''yamls:// tll.proto: yaml name: yaml dump: scheme config.0: name: msg data.f0.s0: 123 ''') url['scheme'] = scheme c = Accum(url) c.open() c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, 0)] m = c.unpack(c.result[0]) assert m.as_dict() == {'f0': {'s0': 123}}
def test_post_clear(clock, msg, fail): c = Accum('timer://', name='timer', clock=clock, dump='yes', context=ctx) c.open(initial='10ms') assert c.result == [] assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn if fail == 'fail': with pytest.raises(TLLError): c.post({'ts': 0}, name=msg) else: c.post({'ts': 0}, name=msg) assert c.dcaps == 0
def test_logic(): ctx = C.Context() sl = ctx.stat_list with pytest.raises(TLLError): ctx.Channel("logic://;name=logic") ctx.register(TestLogic) with pytest.raises(TLLError): ctx.Channel( "logic://;name=logic;tll.channel.input=input;tll.channel.output=input" ) i = ctx.Channel('mem://;name=input;dump=yes') o = Accum('mem://;name=output;dump=yes', master=i, context=ctx) l = ctx.Channel( "logic://;name=logic;tll.channel.input=input;tll.channel.output=input;stat=yes" ) assert len(list(sl)) == 1 assert [x.name for x in sl] == ['logic'] fields = iter(sl).swap() assert [(f.name, f.value) for f in fields[:-1]] == [('rx', 0), ('rx', 0), ('tx', 0), ('tx', 0)] assert (fields[-1].name, fields[-1].count) == ('time', 0) l.open() i.open() o.open() o.post(b'xxx') assert [m.data.tobytes() for m in o.result] == [] i.process() assert [m.data.tobytes() for m in o.result] == [] o.process() assert [m.data.tobytes() for m in o.result] == [b'xxx'] fields = iter(sl).swap() assert [(f.name, f.value) for f in fields[:-1]] == [('rx', 1), ('rx', 3), ('tx', 0), ('tx', 0)] assert (fields[-1].name, fields[-1].count) == ('time', 1) assert fields[-1].sum > 1000
def test_binary(): url = Config.load(br'''yamls:// tll.proto: yaml name: yaml dump: frame config: - msgid: 1 seq: 10 data: "abc\x01def" ''') c = Accum(url) c.open() c.process() assert c.state == c.State.Active assert [(m.msgid, m.seq, m.data.tobytes()) for m in c.result] == [(1, 10, b'abc\x01def')] c.process() assert c.state == c.State.Closed
def test_list(t, v): scheme = f'''yamls:// - name: msg id: 10 fields: - {{name: f0, type: {t} }} ''' url = Config.load(f'''yamls:// tll.proto: yaml name: yaml dump: scheme config.0: name: msg data.f0: {v} ''') url['scheme'] = scheme c = Accum(url) c.open() c.process() assert [(m.msgid, m.seq) for m in c.result] == [(10, 0)] m = c.unpack(c.result[0]) assert m.as_dict() == {'f0': v}
def test_lz4(): s = Accum('lz4+direct://', name='server', context=ctx) c = Accum('direct://', name='client', master=s, context=ctx) s.open() c.open() s.post(b'xxx', seq=10) assert [(m.data.tobytes(), m.seq) for m in c.result] == [(lz4.block.compress(b'xxx', store_size=False), 10)] assert s.result == [] c.post(lz4.block.compress(b'yyy', store_size=False), seq=21) assert [(m.data.tobytes(), m.seq) for m in s.result] == [(b'yyy', 21)] c.post(b'xxx') assert s.state == s.State.Error
def server(self, size='1kb', **kw): return Accum(self.URL, mode='server', name='server', dump='frame', size=size, context=ctx, **kw)
def setup(self): self.s = self.server() self.c = Accum(self.URL, mode='client', name='client', dump='frame', context=ctx)
def setup(self): self.s = Accum(self.PROTO, mode='server', name='server', dump='yes', context=ctx) self.c = Accum(self.PROTO, mode='client', name='client', dump='yes', context=ctx)
class TestPub: URL = 'pub+tcp://./pub.sock' CLEANUP = ['./pub.sock'] def server(self, size='1kb', **kw): return Accum(self.URL, mode='server', name='server', dump='frame', size=size, context=ctx, **kw) def setup(self): self.s = self.server() self.c = Accum(self.URL, mode='client', name='client', dump='frame', context=ctx) def teardown(self): self.c.close() self.s.close() self.c = None self.s = None for f in self.CLEANUP: if os.path.exists(f): os.unlink(f) def test(self): s, c = self.s, self.c s.open() assert s.state == s.State.Active assert len(s.children) == 1 assert s.dcaps == s.DCaps.Zero ss = s.children[0] assert ss.dcaps == ss.DCaps.Process | ss.DCaps.PollIn c.open() assert c.state == c.State.Opening assert len(c.children) == 0 ss.process() assert len(s.children) == 2 sc = s.children[1] assert sc.dcaps == sc.DCaps.Process | sc.DCaps.PollIn assert sc.state == c.State.Opening sc.process() assert sc.state == c.State.Active c.process() assert c.state == c.State.Active assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn with pytest.raises(TLLError): s.post(b'x' * (512 - 16 + 1), seq=1) # Message larger then half of buffer s.post(b'xxx', seq=1, msgid=10) c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result] == [(1, 10, b'xxx')] c.result = [] for i in range(2, 5): s.post(b'x' * i, seq=i, msgid=10) for i in range(2, 5): c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result[-1:]] == [(i, 10, b'x' * i)] def loop_open(self, s, c): loop = Loop() loop.add(s) s.open() assert s.state == s.State.Active c.open() loop.step(0) # Accept loop.step(0) # Handshake c.process() assert c.state == c.State.Active return loop def test_more(self): s, c = self.s, self.c loop = self.loop_open(s, c) s.post(b'xxx', seq=1, msgid=10, flags=s.PostFlags.More) c.process() assert c.result == [] s.post(b'zzz', seq=2, msgid=10) c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result] == [(1, 10, b'xxx')] c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result] == [(1, 10, b'xxx'), (2, 10, b'zzz')] def test_eagain(self): self.s = None self.s = self.server(size='64kb', sndbuf='1kb') s, c = self.s, self.c loop = self.loop_open(s, c) s.post(b'xxx', seq=1, msgid=10) c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result] == [(1, 10, b'xxx')] c.result = [] for i in range(2, 10): s.post(b'x' * 256 + b'x' * i, seq=i, msgid=10) for i in range(2, 5): c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result[-1:]] == [(i, 10, b'x' * 256 + b'x' * i)] for i in range(5, 10): loop.step(0) c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result[-1:]] == [(i, 10, b'x' * 256 + b'x' * i)] def test_overflow(self): self.s = None self.s = self.server(size='1kb', sndbuf='1kb') s, c = self.s, self.c loop = self.loop_open(s, c) s.post(b'xxx', seq=1, msgid=10) c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result] == [(1, 10, b'xxx')] c.result = [] for i in range(2, 10): s.post(b'x' * 256 + b'x' * i, seq=i, msgid=10) loop.step(0) for i in range(2, 6): c.process() assert [(m.seq, m.msgid, m.data.tobytes()) for m in c.result[-1:]] == [(i, 10, b'x' * 256 + b'x' * i)] assert c.state == c.State.Active c.process() assert c.state == c.State.Error def test_many(self): s, c = self.s, self.c loop = self.loop_open(s, c) loop.add(c) for i in range(0, 1000): s.post(b'z' * 16 + b'x' * (i % 100), seq=i, msgid=10) loop.step(0) loop.step(0) assert [m.seq for m in c.result] == list(range(0, 1000))
class _test_udp_base: PROTO = 'invalid-url' FRAME = True TIMESTAMP = False CLEANUP = [] def setup(self): self.s = Accum(self.PROTO, mode='server', name='server', dump='yes', context=ctx) self.c = Accum(self.PROTO, mode='client', name='client', dump='yes', context=ctx) def teardown(self): self.c.close() self.s.close() self.c = None self.s = None for f in self.CLEANUP: if os.path.exists(f): os.unlink(f) def test(self): s, c = self.s, self.c s.open() assert s.state == s.State.Active assert len(s.children) == 0 spoll = select.poll() spoll.register(s.fd, select.POLLIN) assert s.state == s.State.Active assert s.dcaps == s.DCaps.Process | s.DCaps.PollIn c.open() cpoll = select.poll() cpoll.register(c.fd, select.POLLIN) assert c.state == c.State.Active assert len(c.children) == 0 assert c.state == c.State.Active assert c.dcaps == c.DCaps.Process | c.DCaps.PollIn c.post(b'xxx', seq=0x6ead, msgid=0x6eef) timestamp = time.time() if self.TIMESTAMP: if c.result == []: assert cpoll.poll(10) != [] c.process() assert [(m.seq, m.msgid) for m in c.result if m.type == m.Type.Control] == [(0, 10)] assert c.result[-1].time.seconds == pytest.approx(timestamp, 0.001) assert spoll.poll(10) != [] s.process() assert [m.data.tobytes() for m in s.result] == [b'xxx'] assert [(m.seq, m.msgid) for m in s.result] == [(0x6ead, 0x6eef) if self.FRAME else (0, 0)] # No frame if self.TIMESTAMP: assert s.result[-1].time.seconds == pytest.approx(timestamp, 0.001) if self.CLEANUP: return # Unix sockets don't have return address s.post(b'zzzz', seq=0x6eef, msgid=0x6ead, addr=s.result[0].addr) assert cpoll.poll(10) != [] c.process() assert [m.data.tobytes() for m in c.result if m.type == m.Type.Data] == [b'zzzz'] assert [(m.seq, m.msgid) for m in c.result if m.type == m.Type.Data] == [(0x6eef, 0x6ead) if self.FRAME else (0, 0)] # No frame
def test_prefix(): ctx = C.Context() with pytest.raises(TLLError): ctx.Channel("prefix+null://;name=channel") ctx.register(Echo) ctx.register(TestPrefix) c = Accum("prefix+echo://;name=channel", context=ctx) cfg = c.config pyc = C.channel_cast(c) assert isinstance(pyc, TestPrefix) assert c.state == c.State.Closed assert cfg.get("state", "") == "Closed" assert [x.name for x in c.children] == ['channel/prefix'] c.open() assert [x.name for x in c.children] == ['channel/prefix'] assert c.state == c.State.Opening assert cfg.get("state", "") == "Opening" c.process() assert c.state == c.State.Opening assert cfg.get("state", "") == "Opening" c.children[0].process() assert c.state == c.State.Active assert cfg.get("state", "") == "Active" assert c.result == [] c.post(b'xxx', seq=100) assert [(m.seq, m.data.tobytes()) for m in c.result] == [(100, b'xxx')] c.result = [] c.post(b'zzz', seq=200, type=C.Type.Control, addr=0xbeef) assert [(m.type, m.seq, m.addr, m.data.tobytes()) for m in c.result], [(C.Type.Control, 200, 0xbeef, b'zzz')] c.close() assert [x.name for x in c.children] == ['channel/prefix'] del c ctx.unregister(TestPrefix) with pytest.raises(TLLError): ctx.Channel("prefix+null://;name=channel")
def test_mem(fd=True, **kw): s = Accum('mem://;size=1kb', name='server', context=ctx, fd='yes' if fd else 'no', **kw) s.open() with pytest.raises(TLLError): s.post(b'x' * 1024) s.post(b'xxx', seq=10) c = Accum('mem://', name='client', master=s, context=ctx) assert c.result == [] assert s.result == [] c.open() if sys.platform.startswith('linux') and fd: assert c.fd != None else: assert c.fd == None if c.fd is not None: poll = select.poll() poll.register(c.fd, select.POLLIN) poll.register(s.fd, select.POLLIN) assert poll.poll(0), [(c.fd == select.POLLIN)] s.post(b'yyy', seq=20) c.process() assert s.result == [] assert [(m.data.tobytes(), m.seq) for m in c.result] == [(b'xxx', 10)] if c.fd is not None: assert poll.poll(0), [(c.fd == select.POLLIN)] assert c.dcaps & c.DCaps.Pending == c.DCaps.Pending c.result = [] c.process() assert s.result == [] assert [(m.data.tobytes(), m.seq) for m in c.result] == [(b'yyy', 20)] c.result = [] if c.fd is not None: assert poll.poll(0) == [] c.process() assert c.result == [] if c.fd is not None: assert poll.poll(0) == [] c.post(b'yyy', seq=21) if c.fd is not None: assert poll.poll(0) == [(s.fd, select.POLLIN)] s.process() assert [(m.data.tobytes(), m.seq) for m in s.result] == [(b'yyy', 21)]
def test_direct(): s = Accum('direct://', name='server', context=ctx) c = Accum('direct://', name='client', master=s, context=ctx) assert s.dcaps == 0 s.open() assert s.dcaps == 0 s.post(b'xxx', seq=10) assert c.result == [] assert s.result == [] assert s.dcaps == 0 c.open() assert c.dcaps == 0 s.post(b'yyy', seq=20) assert [(m.data.tobytes(), m.seq) for m in c.result] == [(b'yyy', 20)] assert s.result == [] c.post(b'yyy', seq=21) assert [(m.data.tobytes(), m.seq) for m in c.result] == [(b'yyy', 20)] assert [(m.data.tobytes(), m.seq) for m in s.result] == [(b'yyy', 21)] c.close() c.result = [] s.result = [] s.post(b'yyy', seq=20) assert c.result == [] assert s.result == []
def test(): ctx = C.Context() with pytest.raises(TLLError): ctx.Channel("echo://;name=echo") ctx.register(Echo) c = Accum("echo://;name=echo", context=ctx) cfg = c.config pyc = C.channel_cast(c) assert isinstance(pyc, Echo) pyc = C.channel_cast(c, Echo) assert isinstance(pyc, Echo) with pytest.raises(TypeError): C.channel_cast(c, TestPrefix) assert c.state == c.State.Closed assert cfg.get("state", "") == "Closed" assert [x.name for x in c.children] == [] c.open() assert [x.name for x in c.children] == ['child', 'orphan'] with pytest.raises(TypeError): C.channel_cast(c.children[0]) assert c.state == c.State.Opening assert cfg.get("state", "") == "Opening" c.process() assert c.state == c.State.Active assert cfg.get("state", "") == "Active" assert c.result == [] c.post(b'xxx', seq=100) assert [(m.seq, m.data.tobytes()) for m in c.result], [(100 == b'xxx')] c.close() assert [x.name for x in c.children] == ['orphan'] assert c.state == c.State.Closing c.process() assert c.state == c.State.Closed del c assert ctx.get('orphan') == None ctx.unregister(Echo) with pytest.raises(TLLError): ctx.Channel("echo://;name=echo")