def test_ProcessIncomingEntryAssignWithFlags( storage_populate_one, dispatcher, entry_notifier, is_server, conn ): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0, 1, value, 0x2), conn) # EXPECT_CALL(*conn, proto_rev()).WillRepeatedly(Return(0x0300u)) if is_server: # server broadcasts new value/flags to all *other* connections dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryAssign("foo", 0, 1, value, 0x2), None, conn)] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_UPDATE | NT_NOTIFY_FLAGS)] ) else: # client forces flags back when an assign message is received for an # existing entry with different flags dispatcher._queueOutgoing.assert_has_calls( [call(Message.flagsUpdate(0, 0), None, None)] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_UPDATE)] )
def test_ProcessIncomingEntryAssignWithFlags(storage_populate_one, dispatcher, entry_notifier, is_server, conn): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0, 1, value, 0x2), conn) #EXPECT_CALL(*conn, proto_rev()).WillRepeatedly(Return(0x0300u)) if is_server: # server broadcasts new value/flags to all *other* connections dispatcher._queueOutgoing.assert_has_calls([ call(Message.entryAssign("foo", 0, 1, value, 0x2), None, conn), ]) entry_notifier.notifyEntry.assert_has_calls([ call(0, "foo", value, NT_NOTIFY_UPDATE | NT_NOTIFY_FLAGS), ]) else: # client forces flags back when an assign message is received for an # existing entry with different flags dispatcher._queueOutgoing.assert_has_calls([ call(Message.flagsUpdate(0, 0), None, None), ]) entry_notifier.notifyEntry.assert_has_calls([ call(0, "foo", value, NT_NOTIFY_UPDATE), ])
def _fn(msg, minver=0x0200, exclude=None): out = [] fp = BytesIO() rstream = ReadStream(fp) if codec.proto_rev < minver: # The codec won't have the correct struct set if # the version isn't supported Message.write(msg, out, codec) assert not out return Message.write(msg, out, codec) fp.write(b"".join(out)) fp.seek(0) mm = Message.read(rstream, codec, lambda x: msg.value.type) with pytest.raises(StreamEOF): rstream.read(1) # In v2, some fields aren't copied over, so we exclude them # by overwriting those indices and recreating the read message if exclude: args = list(mm) for e in exclude: args[e] = msg[e] mm = MessageType(*args) assert msg == mm
def test_LoadPersistentUpdateValueFlags(storage_populated, dispatcher, entry_notifier, is_server): storage = storage_populated fp = StringIO("[NetworkTables Storage 3.0]\ndouble \"foo2\"=1.0\n") assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo2") assert Value.makeDouble(1.0) == entry.value assert NT_PERSISTENT == entry.flags # client shouldn't send an update as id not assigned yet if is_server: # id assigned as this is the server; seq_num incremented dispatcher._queueOutgoing.assert_has_calls([ call(Message.entryUpdate(1, 2, entry.value), None, None), call(Message.flagsUpdate(1, NT_PERSISTENT), None, None), ]) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls([ call(1, "foo2", entry.value, NT_NOTIFY_FLAGS | NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL) ]) if not is_server: assert 2 == storage.m_entries.get( "foo2").seq_num # still should be incremented
def _fn(msg, minver=0x0200, exclude=None): out = [] fp = BytesIO() rstream = ReadStream(fp) if codec.proto_rev < minver: # The codec won't have the correct struct set if # the version isn't supported Message.write(msg, out, codec) assert not out return Message.write(msg, out, codec) fp.write(b''.join(out)) fp.seek(0) mm = Message.read(rstream, codec, lambda x: msg.value.type) with pytest.raises(StreamEOF): rstream.read(1) # In v2, some fields aren't copied over, so we exclude them # by overwriting those indices and recreating the read message if exclude: args = list(mm) for e in exclude: args[e] = msg[e] mm = MessageType(*args) assert msg == mm
def test_DeleteEntryExist(storage_populated, dispatcher, entry_notifier, is_server): storage = storage_populated storage.deleteEntry("foo2") entry = storage.m_entries.get("foo2") assert entry is not None assert entry.value is None assert entry.id == 0xffff assert entry.local_write == False # client shouldn't send an update as id not assigned yet if is_server: # id assigned as this is the server dispatcher._queueOutgoing.assert_has_calls([ call(Message.entryDelete(1), None, None), ]) else: # shouldn't send an update id not assigned yet assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls([ call(1, "foo2", Value.makeDouble(0.0), NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL), ]) if is_server: assert len(storage.m_idmap) >= 2 assert not storage.m_idmap[1]
def test_SetEntryValueDifferentValue(storage_populated, is_server, dispatcher, entry_notifier): storage = storage_populated # update with same type and different value results in value update message value = Value.makeDouble(1.0) assert storage.setEntryValue("foo2", value) entry = storage.m_entries.get("foo2") assert value == entry.value # client shouldn't send an update as id not assigned yet if is_server: # id assigned if server; seq_num incremented dispatcher._queueOutgoing.assert_has_calls([ call(Message.entryUpdate(1, 2, value), None, None), ]) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls([ call(1, "foo2", value, NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL), ]) if not is_server: assert 2 == storage.m_entries.get( "foo2").seq_num # still should be incremented
def test_SetEntryTypeValueAssignNew( storage_empty, dispatcher, entry_notifier, is_server ): storage = storage_empty # brand new entry value = Value.makeBoolean(True) storage.setEntryTypeValue("foo", value) assert value == storage.m_entries.get("foo").value dispatcher._queueOutgoing.assert_has_calls( [ call( Message.entryAssign("foo", 0 if is_server else 0xFFFF, 1, value, 0), None, None, ) ] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL)] ) if is_server: assert 1 == len(storage.m_idmap) assert value == storage.m_idmap[0].value else: assert len(storage.m_idmap) == 0
def test_SetEntryValueDifferentValue( storage_populated, is_server, dispatcher, entry_notifier ): storage = storage_populated # update with same type and different value results in value update message value = Value.makeDouble(1.0) assert storage.setEntryValue("foo2", value) entry = storage.m_entries.get("foo2") assert value == entry.value # client shouldn't send an update as id not assigned yet if is_server: # id assigned if server; seq_num incremented dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryUpdate(1, 2, value), None, None)] ) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", value, NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL)] ) if not is_server: assert 2 == storage.m_entries.get("foo2").seq_num # still should be incremented
def test_LoadPersistentAssign(storage_empty, dispatcher, entry_notifier, is_server): storage = storage_empty fp = StringIO('[NetworkTables Storage 3.0]\nboolean "foo"=true\n') assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo") assert Value.makeBoolean(True) == entry.value assert NT_PERSISTENT == entry.flags dispatcher._queueOutgoing.assert_has_calls( [ call( Message.entryAssign( "foo", 0 if is_server else 0xFFFF, 1, entry.value, NT_PERSISTENT ), None, None, ) ] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", entry.value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL)] )
def test_DeleteEntryExist(storage_populated, dispatcher, entry_notifier, is_server): storage = storage_populated storage.deleteEntry("foo2") entry = storage.m_entries.get("foo2") assert entry is not None assert entry.value is None assert entry.id == 0xFFFF assert entry.local_write == False # client shouldn't send an update as id not assigned yet if is_server: # id assigned as this is the server dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryDelete(1), None, None)] ) else: # shouldn't send an update id not assigned yet assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", Value.makeDouble(0.0), NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL)] ) if is_server: assert len(storage.m_idmap) >= 2 assert not storage.m_idmap[1]
def test_LoadPersistentAssign(storage_empty, dispatcher, entry_notifier, is_server): storage = storage_empty fp = StringIO('[NetworkTables Storage 3.0]\nboolean "foo"=true\n') assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo") assert Value.makeBoolean(True) == entry.value assert NT_PERSISTENT == entry.flags assert entry.isPersistent dispatcher._queueOutgoing.assert_has_calls( [ call( Message.entryAssign( "foo", 0 if is_server else 0xFFFF, 1, entry.value, NT_PERSISTENT ), None, None, ) ] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", entry.value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL)] )
def test_LoadPersistentUpdateValue( storage_populated, dispatcher, entry_notifier, is_server ): storage = storage_populated entry = storage.m_entries.get("foo2") entry.flags = NT_PERSISTENT entry.isPersistent = True fp = StringIO('[NetworkTables Storage 3.0]\ndouble "foo2"=1.0\n') assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo2") assert Value.makeDouble(1.0) == entry.value assert NT_PERSISTENT == entry.flags assert entry.isPersistent # client shouldn't send an update as id not assigned yet if is_server: # id assigned as this is the server; seq_num incremented dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryUpdate(1, 2, entry.value), None, None)] ) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", entry.value, NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL)] ) if not is_server: assert 2 == storage.m_entries.get("foo2").seq_num # still should be incremented
def test_ProcessIncomingEntryAssign1(storage_populate_one, dispatcher, entry_notifier, is_server, conn): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0, 1, value, 0), conn) # EXPECT_CALL(*conn, proto_rev()).WillRepeatedly(Return(0x0300u)) if is_server: # server broadcasts new value to all *other* connections dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryAssign("foo", 0, 1, value, 0), None, conn)]) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_UPDATE)])
def test_ProcessIncomingEntryAssign0( storage_empty, dispatcher, entry_notifier, is_server, conn ): storage = storage_empty value = Value.makeDouble(1.0) entry_id = 0xFFFF if is_server else 0 storage.processIncoming(Message.entryAssign("foo", entry_id, 0, value, 0), conn) if is_server: # id assign message reply generated on the server sent to everyone dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryAssign("foo", 0, 0, value, 0), None, None)] ) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls([call(0, "foo", value, NT_NOTIFY_NEW)])
def test_ProcessIncomingEntryAssignIgnore(storage_populate_one, dispatcher, entry_notifier, is_server, conn): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0xffff, 1, value, 0), conn) assert dispatcher._queueOutgoing.call_count == 0 assert entry_notifier.notifyEntry.call_count == 0
def test_ProcessIncomingEntryAssignIgnore( storage_populate_one, dispatcher, entry_notifier, is_server, conn ): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0xFFFF, 1, value, 0), conn) assert dispatcher._queueOutgoing.call_count == 0 assert entry_notifier.notifyEntry.call_count == 0
def test_ProcessIncomingEntryAssign1( storage_populate_one, dispatcher, entry_notifier, is_server, conn ): storage = storage_populate_one value = Value.makeDouble(1.0) storage.processIncoming(Message.entryAssign("foo", 0, 1, value, 0), conn) # EXPECT_CALL(*conn, proto_rev()).WillRepeatedly(Return(0x0300u)) if is_server: # server broadcasts new value to all *other* connections dispatcher._queueOutgoing.assert_has_calls( [call(Message.entryAssign("foo", 0, 1, value, 0), None, conn)] ) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_UPDATE)] )
def test_deleteAllEntries(storage_populated, dispatcher, entry_notifier): storage = storage_populated storage.deleteAllEntries() assert len(storage.m_entries) == 4 assert len(storage.getEntries("", 0)) == 0 assert storage.m_entries["foo2"].value is None dispatcher._queueOutgoing.assert_has_calls( [call(Message.clearEntries(), None, None)]) entry_notifier.notifyEntry.assert_has_calls( [call(ANY, ANY, ANY, NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL)] * 4)
def test_DeleteAllEntriesPersistent(storage_populated, dispatcher, entry_notifier): storage = storage_populated storage.m_entries.get("foo2").flags = NT_PERSISTENT storage.deleteAllEntries() assert len(storage.getEntries("", 0)) == 1 assert "foo2" in storage.m_entries dispatcher._queueOutgoing.assert_has_calls( [call(Message.clearEntries(), None, None)]) entry_notifier.notifyEntry.assert_has_calls( [call(ANY, ANY, ANY, NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL)] * 3)
def test_deleteAllEntries(storage_populated, dispatcher, entry_notifier): storage = storage_populated storage.deleteAllEntries() assert len(storage.m_entries) == 4 assert len(storage.getEntries("", 0)) == 0 assert storage.m_entries["foo2"].value is None dispatcher._queueOutgoing.assert_has_calls( [call(Message.clearEntries(), None, None)] ) entry_notifier.notifyEntry.assert_has_calls( [call(ANY, ANY, ANY, NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL)] * 4 )
def test_SetEntryValueAssignNew(storage_empty, dispatcher, entry_notifier, is_server): storage = storage_empty # brand entry value = Value.makeBoolean(True) assert storage.setEntryValue("foo", value) assert value == storage.m_entries.get("foo").value dispatcher._queueOutgoing.assert_has_calls([ call( Message.entryAssign("foo", 0 if is_server else 0xffff, 1, value, 0), None, None), ]) entry_notifier.notifyEntry.assert_has_calls([ call(0, "foo", value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL), ])
def test_DeleteAllEntriesPersistent(storage_populated, dispatcher, entry_notifier): storage = storage_populated entry = storage.m_entries.get("foo2") entry.flags = NT_PERSISTENT entry.isPersistent = True storage.deleteAllEntries() assert len(storage.getEntries("", 0)) == 1 assert "foo2" in storage.m_entries dispatcher._queueOutgoing.assert_has_calls( [call(Message.clearEntries(), None, None)] ) entry_notifier.notifyEntry.assert_has_calls( [call(ANY, ANY, ANY, NT_NOTIFY_DELETE | NT_NOTIFY_LOCAL)] * 3 )
def test_SetEntryTypeValueAssignTypeChange(storage_populate_one, dispatcher, entry_notifier, is_server): storage = storage_populate_one # update with different type results in assignment message value = Value.makeDouble(0.0) storage.setEntryTypeValue("foo", value) assert value == storage.m_entries.get("foo").value dispatcher._queueOutgoing.assert_has_calls([ call( Message.entryAssign("foo", 0 if is_server else 0xffff, 2, value, 0), None, None), ]) entry_notifier.notifyEntry.assert_has_calls([ call(0, "foo", value, NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL), ])
def test_LoadPersistentUpdateFlags(storage_populated, dispatcher, entry_notifier, is_server): storage = storage_populated fp = StringIO('[NetworkTables Storage 3.0]\ndouble "foo2"=0.0\n') assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo2") assert Value.makeDouble(0.0) == entry.value assert NT_PERSISTENT == entry.flags if is_server: dispatcher._queueOutgoing.assert_has_calls( [call(Message.flagsUpdate(1, NT_PERSISTENT), None, None)]) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", entry.value, NT_NOTIFY_FLAGS | NT_NOTIFY_LOCAL)])
def test_SetEntryFlagsDifferentValue(storage_populated, dispatcher, entry_notifier, is_server): storage = storage_populated # update with different value results in flags update message storage.setEntryFlags("foo2", 1) entry = storage.m_entries.get("foo2") assert 1 == entry.flags if is_server: # id assigned as this is the server dispatcher._queueOutgoing.assert_has_calls( [call(Message.flagsUpdate(1, 1), None, None)]) else: # shouldn't send an update id not assigned yet assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", entry.value, NT_NOTIFY_FLAGS | NT_NOTIFY_LOCAL)])
def test_SetDefaultEntryAssignNew(storage_empty, dispatcher, entry_notifier, is_server): storage = storage_empty # brand new entry value = Value.makeBoolean(True) ret_val = storage.setDefaultEntryValue("foo", value) assert ret_val assert value == storage.m_entries.get("foo").value dispatcher._queueOutgoing.assert_has_calls( [ call( Message.entryAssign("foo", 0 if is_server else 0xFFFF, 1, value, 0), None, None, ) ] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_NEW | NT_NOTIFY_LOCAL)] )
def test_SetEntryFlagsDifferentValue( storage_populated, dispatcher, entry_notifier, is_server ): storage = storage_populated # update with different value results in flags update message storage.setEntryFlags("foo2", 1) entry = storage.m_entries.get("foo2") assert 1 == entry.flags if is_server: # id assigned as this is the server dispatcher._queueOutgoing.assert_has_calls( [call(Message.flagsUpdate(1, 1), None, None)] ) else: # shouldn't send an update id not assigned yet assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", entry.value, NT_NOTIFY_FLAGS | NT_NOTIFY_LOCAL)] )
def test_SetEntryTypeValueAssignTypeChange( storage_populate_one, dispatcher, entry_notifier, is_server ): storage = storage_populate_one # update with different type results in assignment message value = Value.makeDouble(0.0) storage.setEntryTypeValue("foo", value) assert value == storage.m_entries.get("foo").value dispatcher._queueOutgoing.assert_has_calls( [ call( Message.entryAssign("foo", 0 if is_server else 0xFFFF, 2, value, 0), None, None, ) ] ) entry_notifier.notifyEntry.assert_has_calls( [call(0, "foo", value, NT_NOTIFY_UPDATE | NT_NOTIFY_LOCAL)] )
def test_LoadPersistentUpdateFlags( storage_populated, dispatcher, entry_notifier, is_server ): storage = storage_populated fp = StringIO('[NetworkTables Storage 3.0]\ndouble "foo2"=0.0\n') assert storage.loadPersistent(fp=fp) is None entry = storage.m_entries.get("foo2") assert Value.makeDouble(0.0) == entry.value assert NT_PERSISTENT == entry.flags assert entry.isPersistent if is_server: dispatcher._queueOutgoing.assert_has_calls( [call(Message.flagsUpdate(1, NT_PERSISTENT), None, None)] ) else: assert dispatcher._queueOutgoing.call_count == 0 entry_notifier.notifyEntry.assert_has_calls( [call(1, "foo2", entry.value, NT_NOTIFY_FLAGS | NT_NOTIFY_LOCAL)] )
def test_wire_clientHelloDone(msg_round_trip): msg_round_trip(Message.clientHelloDone())
def test_wire_rpcResponse(msg_round_trip): msg_round_trip(Message.rpcResponse(0x1234, 0x4321, "parameter"), minver=0x0300)
def test_wire_executeRpc(msg_round_trip): msg_round_trip(Message.executeRpc(0x1234, 0x4321, "parameter"), minver=0x0300)
def test_wire_clearEntries(msg_round_trip): msg_round_trip(Message.clearEntries(), minver=0x0300)
def test_wire_entryDelete(msg_round_trip): msg_round_trip(Message.entryDelete(0x1234), minver=0x0300)
def test_wire_flagsUpdate(msg_round_trip): msg_round_trip(Message.flagsUpdate(0x1234, 0x42), minver=0x0300)
def test_wire_entryUpdate2(msg_round_trip, proto_rev): exclude = [] if proto_rev >= 0x0300 else [4] value = Value.makeString("Oh noes") msg_round_trip(Message.entryUpdate(0x1234, 0x4321, value), exclude=exclude)
def test_wire_entryUpdate1(msg_round_trip, proto_rev): exclude = [] if proto_rev >= 0x0300 else [4] value = Value.makeBoolean(True) msg_round_trip(Message.entryUpdate(0x1234, 0x4321, value), exclude=exclude)
def test_wire_keepAlive(msg_round_trip): msg_round_trip(Message.keepAlive())
def test_wire_serverHelloDone(msg_round_trip): msg_round_trip(Message.serverHelloDone())
def test_wire_clientHelloV3(msg_round_trip): msg_round_trip(Message.clientHello(0x0300, "Hi"))
def test_wire_clientHello(msg_round_trip): msg_round_trip(Message.clientHello(0x0200, "Hi"), exclude=[1])
def test_wire_protoUnsup(msg_round_trip): msg_round_trip(Message.protoUnsup(0x0300))
def test_wire_serverHello(msg_round_trip): msg_round_trip(Message.serverHello(0x01, "Hi"), minver=0x0300)