SG verified artifact 3043b7b7625d0a37
Browse files- test_leave_identities.py +73 -0
test_leave_identities.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Leaving removes every observed identity without removing accepted totals."""
|
| 2 |
+
import threading, types, unittest
|
| 3 |
+
import dbmoe as db
|
| 4 |
+
|
| 5 |
+
class LeaveIdentities(unittest.TestCase):
|
| 6 |
+
def setUp(self):
|
| 7 |
+
self.c = c = db.Coordinator.__new__(db.Coordinator)
|
| 8 |
+
c.lock = threading.RLock()
|
| 9 |
+
c.meta = {'workers': {}, 'worker_alias_salt': 'test-only', 'updates': 99, 'tokens': 1234}
|
| 10 |
+
c.leases = {}
|
| 11 |
+
c.enrol = None
|
| 12 |
+
c.save = lambda: None
|
| 13 |
+
c.log = lambda **kw: None
|
| 14 |
+
c.net = n = db.NetInfer.__new__(db.NetInfer)
|
| 15 |
+
n.cv = threading.Condition(threading.RLock())
|
| 16 |
+
n.peers = {}
|
| 17 |
+
n.idle = {}
|
| 18 |
+
|
| 19 |
+
def peer(self, owner, name):
|
| 20 |
+
worker = owner + '/' + name
|
| 21 |
+
key = worker + '/session'
|
| 22 |
+
self.c.net.peers[key] = {'owner': owner, 'worker': worker}
|
| 23 |
+
event = threading.Event()
|
| 24 |
+
self.c.net.idle[key] = types.SimpleNamespace(event=event)
|
| 25 |
+
return event
|
| 26 |
+
|
| 27 |
+
def test_inference_only_is_tombstoned_and_woken(self):
|
| 28 |
+
event = self.peer('alice', 'serve')
|
| 29 |
+
result = self.c.leave('alice', {})
|
| 30 |
+
self.assertEqual(result['removed'], 1)
|
| 31 |
+
self.assertEqual(self.c.meta['left_workers'], [self.c.alias('alice/serve')])
|
| 32 |
+
self.assertTrue(event.is_set())
|
| 33 |
+
self.assertFalse(self.c.net.peers)
|
| 34 |
+
self.assertEqual(self.c.meta['updates'], 99)
|
| 35 |
+
self.assertEqual(self.c.meta['tokens'], 1234)
|
| 36 |
+
|
| 37 |
+
def test_lease_only_identity(self):
|
| 38 |
+
self.c.leases['x'] = {'owner': 'alice', 'worker': 'alice/new'}
|
| 39 |
+
self.c.leave('alice', {})
|
| 40 |
+
self.assertFalse(self.c.leases)
|
| 41 |
+
self.assertEqual(self.c.meta['left_workers'], [self.c.alias('alice/new')])
|
| 42 |
+
|
| 43 |
+
def test_mixed_roles_deduplicate_and_repeated_leave_is_idempotent(self):
|
| 44 |
+
self.peer('alice', 'mixed')
|
| 45 |
+
self.c.meta['workers']['alice/mixed'] = {'updates': 1}
|
| 46 |
+
self.c.leases['x'] = {'owner': 'alice', 'worker': 'alice/mixed'}
|
| 47 |
+
self.assertEqual(self.c.leave('alice', {})['removed'], 1)
|
| 48 |
+
self.assertEqual(self.c.leave('alice', {})['removed'], 0)
|
| 49 |
+
self.assertEqual(self.c.meta['left_workers'], [self.c.alias('alice/mixed')])
|
| 50 |
+
|
| 51 |
+
def test_named_leave_preserves_other_name_and_owner(self):
|
| 52 |
+
for owner, name in [('alice', 'one'), ('alice', 'two'), ('alice2', 'one')]:
|
| 53 |
+
self.peer(owner, name)
|
| 54 |
+
key = owner + '/' + name
|
| 55 |
+
self.c.meta['workers'][key] = {'updates': 1}
|
| 56 |
+
self.c.leases[key] = {'owner': owner, 'worker': key}
|
| 57 |
+
self.assertEqual(self.c.leave('alice', {}, 'one')['removed'], 1)
|
| 58 |
+
self.assertEqual(set(self.c.meta['workers']), {'alice/two', 'alice2/one'})
|
| 59 |
+
self.assertEqual(set(self.c.leases), {'alice/two', 'alice2/one'})
|
| 60 |
+
self.assertEqual({p['worker'] for p in self.c.net.peers.values()}, {'alice/two', 'alice2/one'})
|
| 61 |
+
self.assertEqual(self.c.meta['left_workers'], [self.c.alias('alice/one')])
|
| 62 |
+
|
| 63 |
+
def test_all_roles_and_tombstone_bound(self):
|
| 64 |
+
self.c.meta['left_workers'] = ['old-' + str(i) for i in range(5000)]
|
| 65 |
+
self.c.meta['workers']['alice/train'] = {}
|
| 66 |
+
self.peer('alice', 'serve')
|
| 67 |
+
self.c.leases['x'] = {'owner': 'alice', 'worker': 'alice/new'}
|
| 68 |
+
self.assertEqual(self.c.leave('alice', {})['removed'], 3)
|
| 69 |
+
self.assertEqual(len(self.c.meta['left_workers']), 5000)
|
| 70 |
+
self.assertEqual(set(self.c.meta['left_workers'][-3:]), {self.c.alias('alice/' + n) for n in ['train','serve','new']})
|
| 71 |
+
|
| 72 |
+
if __name__ == '__main__':
|
| 73 |
+
unittest.main()
|