Commit aa52f9b6 authored by Grégory Wisniewski's avatar Grégory Wisniewski

Fix many tests, mainly for storage application. They still need a full review to

ensure all is well tested and that there is no redondancy.


git-svn-id: https://svn.erp5.org/repos/neo/trunk@1304 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent 6f3d9187
......@@ -192,9 +192,8 @@ class NeoTestBase(unittest.TestCase):
self.assertTrue(isinstance(packet, protocol.Packet))
self.assertEquals(packet.getType(), packet_type)
if answered_packet is not None:
a_packet = calls[0].getParam(1)
self.assertEquals(a_packet, answered_packet)
self.assertEquals(a_packet.getId(), answered_packet.getId())
msg_id = calls[0].getParam(1)
self.assertEqual(msg_id, answered_packet.getId())
if decode:
return protocol.decode_table[packet.getType()](packet._body)
return packet
......
......@@ -48,8 +48,6 @@ class StorageClientHandlerTests(NeoTestBase):
# create an application object
config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config)
self.app.num_partitions = 1
self.app.num_replicas = 1
self.app.transaction_dict = {}
self.app.store_lock_dict = {}
self.app.load_lock_dict = {}
......@@ -92,7 +90,9 @@ class StorageClientHandlerTests(NeoTestBase):
# check if client's transaction are cleaned
uuid = self.getNewUUID()
from neo.node import ClientNode
manager = Mock()
client = ClientNode(('127.0.0.1', 10010))
client.setManager(manager)
client.setUUID(uuid)
self.app.nm.add(client)
self.app.store_lock_dict[0] = object()
......@@ -183,7 +183,7 @@ class StorageClientHandlerTests(NeoTestBase):
# well case => answer
conn = Mock({})
packet = Packet(msg_type=ASK_TIDS)
self.app.num_partitions = 1
self.app.pt = Mock({'getPartitions': 1})
self.app.dm = Mock({'getTIDList': (INVALID_TID, )})
self.operation.handleAskTIDs(conn, packet, 1, 2, 1)
calls = self.app.dm.mockGetNamedCalls('getTIDList')
......@@ -195,10 +195,9 @@ class StorageClientHandlerTests(NeoTestBase):
# invalid partition => answer usable partitions
conn = Mock({})
packet = Packet(msg_type=ASK_TIDS)
self.app.num_partitions = 1
cell = Mock({'getUUID':self.app.uuid})
self.app.dm = Mock({'getTIDList': (INVALID_TID, )})
self.app.pt = Mock({'getCellList': (cell, )})
self.app.pt = Mock({'getCellList': (cell, ), 'getPartitions': 1})
self.operation.handleAskTIDs(conn, packet, 1, 2, INVALID_PARTITION)
self.assertEquals(len(self.app.pt.mockGetNamedCalls('getCellList')), 1)
calls = self.app.dm.mockGetNamedCalls('getTIDList')
......
......@@ -52,11 +52,9 @@ class StorageInitializationHandlerTests(NeoTestBase):
self.client_port = 11011
self.num_partitions = 1009
self.num_replicas = 2
self.app.num_partitions = 1009
self.app.num_replicas = 2
self.app.operational = False
self.app.load_lock_dict = {}
self.app.pt = PartitionTable(self.app.num_partitions, self.app.num_replicas)
self.app.pt = PartitionTable(self.num_partitions, self.num_replicas)
def tearDown(self):
NeoTestBase.tearDown(self)
......@@ -107,31 +105,33 @@ class StorageInitializationHandlerTests(NeoTestBase):
node_1 = self.getNewUUID()
node_2 = self.getNewUUID()
node_3 = self.getNewUUID()
# SN already known one of the node
# SN already know all nodes
self.app.nm.add(StorageNode(uuid=node_1))
self.app.nm.add(StorageNode(uuid=node_2))
self.app.nm.add(StorageNode(uuid=node_3))
self.app.ptid = 1
self.app.num_partitions = 3
self.app.num_replicas =2
self.assertEqual(self.app.dm.getPartitionTable(), ())
self.assertEqual(self.app.dm.getPartitionTable(), [])
row_list = [(0, ((node_1, UP_TO_DATE_STATE), (node_2, UP_TO_DATE_STATE))),
(1, ((node_3, UP_TO_DATE_STATE), (node_1, UP_TO_DATE_STATE))),
(2, ((node_2, UP_TO_DATE_STATE), (node_3, UP_TO_DATE_STATE)))]
self.assertFalse(self.app.pt.filled())
# send part of the table, won't be filled
self.verification.handleSendPartitionTable(conn, packet, "1", row_list[:1])
self.verification.handleSendPartitionTable(conn, packet, 1, row_list[:1])
self.assertFalse(self.app.pt.filled())
self.assertEqual(self.app.ptid, "1")
self.assertEqual(self.app.dm.getPartitionTable(), ())
# send remaining of the table
self.verification.handleSendPartitionTable(conn, packet, "1", row_list[1:])
self.assertEqual(self.app.pt.getID(), 1)
self.assertEqual(self.app.dm.getPartitionTable(), [])
# send remaining of the table (ack with AnswerPartitionTable)
self.verification.handleSendPartitionTable(conn, packet, 1, row_list[1:])
self.verification.handleAnswerPartitionTable(conn, packet, 1, [])
self.assertTrue(self.app.pt.filled())
self.assertEqual(self.app.ptid, "1")
self.assertNotEqual(self.app.dm.getPartitionTable(), ())
# send a complete new table
self.verification.handleSendPartitionTable(conn, packet, "2", row_list)
self.assertEqual(self.app.pt.getID(), 1)
self.assertNotEqual(self.app.dm.getPartitionTable(), [])
# send a complete new table and ack
self.verification.handleSendPartitionTable(conn, packet, 2, row_list)
self.verification.handleAnswerPartitionTable(conn, packet, 2, [])
self.assertTrue(self.app.pt.filled())
self.assertEqual(self.app.ptid, "2")
self.assertNotEqual(self.app.dm.getPartitionTable(), ())
self.assertEqual(self.app.pt.getID(), 2)
self.assertNotEqual(self.app.dm.getPartitionTable(), [])
if __name__ == "__main__":
......
......@@ -47,8 +47,6 @@ class StorageMasterHandlerTests(NeoTestBase):
# create an application object
config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config)
self.app.num_partitions = 1
self.app.num_replicas = 1
self.app.transaction_dict = {}
self.app.store_lock_dict = {}
self.app.load_lock_dict = {}
......@@ -105,10 +103,10 @@ class StorageMasterHandlerTests(NeoTestBase):
})
app.replicator = Mock({})
packet = Packet(msg_type=NOTIFY_PARTITION_CHANGES)
self.app.ptid = 1
self.app.pt = Mock({'getID': 1})
count = len(self.app.nm.getNodeList())
self.operation.handleNotifyPartitionChanges(conn, packet, 0, ())
self.assertEquals(self.app.ptid, 1)
self.assertEquals(self.app.pt.getID(), 1)
self.assertEquals(len(self.app.nm.getNodeList()), count)
calls = self.app.replicator.mockGetNamedCalls('removePartition')
self.assertEquals(len(calls), 0)
......@@ -117,11 +115,11 @@ class StorageMasterHandlerTests(NeoTestBase):
def test_14_handleNotifyPartitionChanges2(self):
# cases :
uuid = self.getNewUUID()
uuid1, uuid2, uuid3 = [self.getNewUUID() for i in range(3)]
cells = (
(0, uuid, UP_TO_DATE_STATE),
(1, self.app.uuid, DISCARDED_STATE),
(2, self.app.uuid, OUT_OF_DATE_STATE),
(0, uuid1, UP_TO_DATE_STATE),
(1, uuid2, DISCARDED_STATE),
(2, uuid3, OUT_OF_DATE_STATE),
)
# context
conn = Mock({
......@@ -130,32 +128,19 @@ class StorageMasterHandlerTests(NeoTestBase):
})
packet = Packet(msg_type=NOTIFY_PARTITION_CHANGES)
app = self.app
ptid1, ptid2 = self.getTwoIDs()
# register nodes
app.nm.add(StorageNode(uuid=uuid1))
app.nm.add(StorageNode(uuid=uuid2))
app.nm.add(StorageNode(uuid=uuid3))
ptid1, ptid2 = (1, 2)
self.assertNotEquals(ptid1, ptid2)
app.ptid = ptid1
app.pt = PartitionTable(3, 1)
app.pt = Mock({ })
app.dm = Mock({ })
app.replicator = Mock({})
count = len(app.nm.getNodeList())
self.operation.handleNotifyPartitionChanges(conn, packet, ptid2, cells)
# ptid set
self.assertEquals(app.ptid, ptid2)
# two nodes added
self.assertEquals(len(app.nm.getNodeList()), count + 2)
# uuid != app.uuid -> TEMPORARILY_DOWN_STATE
self.assertEquals(app.nm.getNodeByUUID(uuid).getState(), TEMPORARILY_DOWN_STATE)
# pt calls
calls = self.app.pt.mockGetNamedCalls('setCell')
self.assertEquals(len(calls), 3)
calls[0].checkArgs(0, app.nm.getNodeByUUID(uuid), UP_TO_DATE_STATE)
calls[1].checkArgs(1, app.nm.getNodeByUUID(app.uuid), DISCARDED_STATE)
calls[2].checkArgs(2, app.nm.getNodeByUUID(app.uuid), OUT_OF_DATE_STATE)
# replicator calls
calls = self.app.replicator.mockGetNamedCalls('removePartition')
self.assertEquals(len(calls), 1)
calls[0].checkArgs(1)
calls = self.app.replicator.mockGetNamedCalls('addPartition')
self.assertEquals(app.pt.getID(), ptid2)
# dm call
calls = self.app.dm.mockGetNamedCalls('changePartitionTable')
self.assertEquals(len(calls), 1)
......@@ -172,6 +157,7 @@ class StorageMasterHandlerTests(NeoTestBase):
conn = Mock({ 'isServer': False, })
self.app.dm = Mock({ })
packet = Packet(msg_type=LOCK_INFORMATION)
packet.setId(1)
transaction = Mock({ 'getObjectList': ((0, ), ), })
self.app.transaction_dict[INVALID_TID] = transaction
self.operation.handleLockInformation(conn, packet, INVALID_TID)
......@@ -190,6 +176,7 @@ class StorageMasterHandlerTests(NeoTestBase):
conn = Mock({ 'isServer': False, })
self.app.dm = Mock({ })
packet = Packet(msg_type=LOCK_INFORMATION)
packet.setId(1)
transaction = Mock({ 'getObjectList': ((0, ), ), })
self.app.transaction_dict[INVALID_TID] = transaction
self.app.load_lock_dict[0] = transaction
......
......@@ -25,6 +25,7 @@ from neo.node import MasterNode, ClientNode, StorageNode
from neo.storage.mysqldb import p64, u64, MySQLDatabaseManager
from collections import deque
from neo.pt import PartitionTable
from neo.util import dump
class StorageAppTests(NeoTestBase):
......@@ -92,17 +93,20 @@ class StorageAppTests(NeoTestBase):
else:
self.assertFalse(self.app.pt.hasOffset(x))
# fill partition table
self.app.dm.setPTID(1)
self.app.dm.query('delete from pt;')
self.app.dm.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(0, client_uuid, UP_TO_DATE_STATE))
(0, dump(client_uuid), UP_TO_DATE_STATE))
self.app.dm.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(1, client_uuid, UP_TO_DATE_STATE))
(1, dump(client_uuid), UP_TO_DATE_STATE))
self.app.dm.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(1, storage_uuid, UP_TO_DATE_STATE))
(1, dump(storage_uuid), UP_TO_DATE_STATE))
self.app.dm.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(2, storage_uuid, UP_TO_DATE_STATE))
(2, dump(storage_uuid), UP_TO_DATE_STATE))
self.app.dm.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(2, master_uuid, UP_TO_DATE_STATE))
(2, dump(master_uuid), UP_TO_DATE_STATE))
self.assertEqual(len(self.app.dm.getPartitionTable()), 5)
self.app.pt.clear()
self.app.loadPartitionTable()
self.assertTrue(self.app.pt.filled())
for x in xrange(num_partitions):
......@@ -143,15 +147,6 @@ class StorageAppTests(NeoTestBase):
params = call.kwparams
self.assertEqual(params, {'key': 'value'})
def test_04_getPartition(self):
self.app.num_partitions = 3
p = self.app.getPartition(p64(1))
self.assertEqual(p, 1)
p = self.app.getPartition(p64(2))
self.assertEqual(p, 2)
p = self.app.getPartition(p64(3))
self.assertEqual(p, 0)
if __name__ == '__main__':
unittest.main()
......@@ -45,8 +45,6 @@ class StorageStorageHandlerTests(NeoTestBase):
# create an application object
config = self.getStorageConfiguration(master_number=1)
self.app = Application(**config)
self.app.num_partitions = 1
self.app.num_replicas = 1
self.app.transaction_dict = {}
self.app.store_lock_dict = {}
self.app.load_lock_dict = {}
......@@ -141,8 +139,8 @@ class StorageStorageHandlerTests(NeoTestBase):
# well case => answer
conn = Mock({})
packet = Packet(msg_type=ASK_TIDS)
self.app.num_partitions = 1
self.app.dm = Mock({'getTIDList': (INVALID_TID, )})
self.app.pt = Mock({'getPartitions': 1})
self.operation.handleAskTIDs(conn, packet, 1, 2, 1)
calls = self.app.dm.mockGetNamedCalls('getTIDList')
self.assertEquals(len(calls), 1)
......@@ -153,10 +151,9 @@ class StorageStorageHandlerTests(NeoTestBase):
# invalid partition => answer usable partitions
conn = Mock({})
packet = Packet(msg_type=ASK_TIDS)
self.app.num_partitions = 1
cell = Mock({'getUUID':self.app.uuid})
self.app.dm = Mock({'getTIDList': (INVALID_TID, )})
self.app.pt = Mock({'getCellList': (cell, )})
self.app.pt = Mock({'getCellList': (cell, ), 'getPartitions': 1})
self.operation.handleAskTIDs(conn, packet, 1, 2, INVALID_PARTITION)
self.assertEquals(len(self.app.pt.mockGetNamedCalls('getCellList')), 1)
calls = self.app.dm.mockGetNamedCalls('getTIDList')
......@@ -201,7 +198,7 @@ class StorageStorageHandlerTests(NeoTestBase):
# well case > answer OIDs
conn = Mock({})
packet = Packet(msg_type=ASK_OIDS)
self.app.num_partitions = 1
self.app.pt = Mock({'getPartitions': 1})
self.app.dm = Mock({'getOIDList': (INVALID_OID, )})
self.operation.handleAskOIDs(conn, packet, 1, 2, 1)
calls = self.app.dm.mockGetNamedCalls('getOIDList')
......@@ -213,10 +210,9 @@ class StorageStorageHandlerTests(NeoTestBase):
# invalid partition => answer usable partitions
conn = Mock({})
packet = Packet(msg_type=ASK_OIDS)
self.app.num_partitions = 1
cell = Mock({'getUUID':self.app.uuid})
self.app.dm = Mock({'getOIDList': (INVALID_OID, )})
self.app.pt = Mock({'getCellList': (cell, )})
self.app.pt = Mock({'getCellList': (cell, ), 'getPartitions': 1})
self.operation.handleAskOIDs(conn, packet, 1, 2, INVALID_PARTITION)
self.assertEquals(len(self.app.pt.mockGetNamedCalls('getCellList')), 1)
calls = self.app.dm.mockGetNamedCalls('getOIDList')
......
......@@ -20,6 +20,7 @@ import unittest
from neo import logging
import MySQLdb
from mock import Mock
from neo.util import dump
from neo.protocol import *
from neo.tests import NeoTestBase
from neo.exception import DatabaseFailure
......@@ -223,26 +224,16 @@ class StorageMySQSLdbTests(NeoTestBase):
self.db.setup()
rid, uuid, state = '\x00' * 8, '\x00' * 16, 0
self.db.query("insert into pt (rid, uuid, state) values ('%s', '%s', %d)" %
(u64(rid), uuid, state))
(dump(rid), dump(uuid), state))
pt = self.db.getPartitionTable()
self.assertEquals(pt, ((0L, uuid, state), ))
self.assertEquals(pt, [(0L, uuid, state)])
def test_17_getLastOID(self):
# should search in obj table only
self.db.setup()
self.db.query("""insert into obj (oid, serial, compression,
checksum, value) values (3, 'A', 0, 0, '')""")
self.db.query("""insert into obj (oid, serial, compression,
checksum, value) values (1, 'A', 0, 0, '')""")
self.db.query("""insert into obj (oid, serial, compression,
checksum, value) values (2, 'A', 0, 0, '')""")
an_oid = '\x01' * 8
self.db.setLastOID(an_oid)
result = self.db.getLastOID()
self.assertEquals(result, '\x00' * 7 + '\x03')
# should look in temporary table too
self.db.query("""insert into tobj (oid, serial, compression,
checksum, value) values (5, 'A', 0, 0, '')""")
result = self.db.getLastOID(all=True)
self.assertEquals(result, '\x00' * 7 + '\x05')
self.assertEquals(result, an_oid)
def test_18_getLastTID(self):
# max TID is in obj table
......@@ -346,20 +337,20 @@ class StorageMySQSLdbTests(NeoTestBase):
self.db.changePartitionTable(ptid, cells)
result = self.db.query('select rid, uuid, state from pt')
self.assertEquals(len(result), 1)
self.assertEquals(result[0], (1, uuid2, 0))
self.assertEquals(result[0], (1, dump(uuid2), 0))
self.assertEquals(self.db.getPTID(), ptid)
# delete previous entries for a DISCARDED_STATE node
self.db.query("delete from pt")
args = (0, uuid1, DISCARDED_STATE)
args = (0, dump(uuid1), DISCARDED_STATE)
self.db.query('insert into pt (rid, uuid, state) values (%d, "%s", %d)' % args)
result = self.db.query('select rid, uuid, state from pt')
self.assertEquals(len(result), 1)
self.assertEquals(result[0], (0, uuid1, 3))
self.assertEquals(result[0], (0, dump(uuid1), 3))
self.assertEquals(self.db.getPTID(), ptid)
self.db.changePartitionTable(ptid, cells)
result = self.db.query('select rid, uuid, state from pt')
self.assertEquals(len(result), 1)
self.assertEquals(result[0], (1, uuid2, 0))
self.assertEquals(result[0], (1, dump(uuid2), 0))
self.assertEquals(self.db.getPTID(), ptid)
# raise exception (config not set), check rollback
self.db.query("drop table config") # will generate the exception
......@@ -386,7 +377,7 @@ class StorageMySQSLdbTests(NeoTestBase):
self.db.setPartitionTable(ptid, cells)
result = self.db.query('select rid, uuid, state from pt')
self.assertEquals(len(result), 1)
self.assertEquals(result[0], (1, uuid2, 0))
self.assertEquals(result[0], (1, dump(uuid2), 0))
self.assertEquals(self.db.getPTID(), ptid)
# delete previous entries for a DISCARDED_STATE node
self.db.query("delete from pt")
......@@ -399,7 +390,7 @@ class StorageMySQSLdbTests(NeoTestBase):
self.db.setPartitionTable(ptid, cells)
result = self.db.query('select rid, uuid, state from pt')
self.assertEquals(len(result), 1)
self.assertEquals(result[0], (1, uuid2, 0))
self.assertEquals(result[0], (1, dump(uuid2), 0))
self.assertEquals(self.db.getPTID(), ptid)
# raise exception (config not set), check rollback
self.db.query("drop table config") # will generate the exception
......
......@@ -52,11 +52,9 @@ class StorageVerificationHandlerTests(NeoTestBase):
self.client_port = 11011
self.num_partitions = 1009
self.num_replicas = 2
self.app.num_partitions = 1009
self.app.num_replicas = 2
self.app.operational = False
self.app.load_lock_dict = {}
self.app.pt = PartitionTable(self.app.num_partitions, self.app.num_replicas)
self.app.pt = PartitionTable(self.num_partitions, self.num_replicas)
def tearDown(self):
......@@ -104,11 +102,14 @@ class StorageVerificationHandlerTests(NeoTestBase):
conn = Mock({"getUUID" : uuid,
"getAddress" : ("127.0.0.1", self.client_port),
"isServer" : False})
last_ptid = '\x01' * 8
last_oid = '\x02' * 8
self.app.pt = Mock({'getID': last_ptid})
self.verification.handleAskLastIDs(conn, packet)
oid, tid, ptid = self.checkAnswerLastIDs(conn, decode=True)
self.assertEqual(oid, INVALID_OID)
self.assertEqual(tid, INVALID_TID)
self.assertEqual(ptid, self.app.ptid)
self.assertEqual(ptid, last_ptid)
# return value stored in db
# insert some oid
......@@ -135,12 +136,13 @@ class StorageVerificationHandlerTests(NeoTestBase):
self.app.dm.query("""insert into tobj (oid, serial, compression,
checksum, value) values (0, 4, 0, 0, '')""")
self.app.dm.commit()
self.app.dm.setLastOID(last_oid)
self.verification.handleAskLastIDs(conn, packet)
self.checkAnswerLastIDs(conn)
oid, tid, ptid = self.checkAnswerLastIDs(conn, decode=True)
self.assertEqual(u64(oid), 5)
self.assertEqual(oid, last_oid)
self.assertEqual(u64(tid), 4)
self.assertEqual(ptid, self.app.ptid)
self.assertEqual(ptid, self.app.pt.getID())
def test_08_handleAskPartitionTable(self):
uuid = self.getNewUUID()
......@@ -190,14 +192,14 @@ class StorageVerificationHandlerTests(NeoTestBase):
"getAddress" : ("127.0.0.1", self.master_port),
})
packet = Packet(msg_type=NOTIFY_PARTITION_CHANGES)
cell = (0, self.getNewUUID(), UP_TO_DATE_STATE)
count = len(self.app.nm.getNodeList())
new_uuid = self.getNewUUID()
cell = (0, new_uuid, UP_TO_DATE_STATE)
self.app.nm.add(StorageNode(uuid=new_uuid))
self.app.pt = PartitionTable(1, 1)
self.app.dm = Mock({ })
ptid, self.ptid = self.getTwoIDs()
# pt updated
self.verification.handleNotifyPartitionChanges(conn, packet, ptid, (cell, ))
self.assertEquals(len(self.app.nm.getNodeList()), count + 1)
# check db update
calls = self.app.dm.mockGetNamedCalls('changePartitionTable')
self.assertEquals(len(calls), 1)
......@@ -298,7 +300,7 @@ class StorageVerificationHandlerTests(NeoTestBase):
conn = Mock({ "getAddress" : ("127.0.0.1", self.master_port),
'isServer': True })
packet = Packet(msg_type=ASK_TRANSACTION_INFORMATION)
self.verification.handleAskTransactionInformation(conn, packet, p64(3))
self.verification.handleAskTransactionInformation(conn, packet, p64(2))
code, message = self.checkErrorPacket(conn, decode=True)
self.assertEqual(code, TID_NOT_FOUND_CODE)
......
......@@ -168,11 +168,9 @@ class EventTests(NeoTestBase):
self.assertEquals(len(conn.mockGetNamedCalls("getHandler")), 0)
self.assertEquals(len(conn.mockGetNamedCalls("close")), 0)
self.assertEquals(len(conn.mockGetNamedCalls("unlock")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("ask")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("ping")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("expectMessage")), 1)
self.assertEquals(len(handler.mockGetNamedCalls("timeoutExpired")), 0)
# check ping packet sent
self.checkAskPacket(conn, PING)
# call with time < critical_time < t
t = critical_time + 5
......@@ -183,7 +181,7 @@ class EventTests(NeoTestBase):
self.assertEquals(len(conn.mockGetNamedCalls("getHandler")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("close")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("unlock")), 2)
self.assertEquals(len(conn.mockGetNamedCalls("ask")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("ping")), 1)
self.assertEquals(len(conn.mockGetNamedCalls("expectMessage")), 1)
self.assertEquals(len(handler.mockGetNamedCalls("timeoutExpired")), 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment