256
262
def faked_nothing(ssmr, event, params, *args):
257
263
"""Wrap SSMR.nothing to test."""
258
264
self.called = True
265
self.patch(SyncStateMachineRunner, 'nothing', faked_nothing)
260
SyncStateMachineRunner.nothing = faked_nothing
261
267
kwargs = dict(share_id='share_id', node_id='node_id')
262
268
sync.handle_AQ_DOWNLOAD_DOES_NOT_EXIST(**kwargs)
263
269
self.assertTrue(self.called, 'nothing was called')
266
class SyncStateMachineRunnerTestCase(BaseTwistedTestCase):
271
def test_handle_FILE_CREATE_while_LOCAL(self):
272
"""A FS_FILE_CREATE is received with the node in LOCAL."""
273
sync = Sync(main=self.main)
276
def faked_nothing(ssmr, event, params, *args):
277
"""Wrap SSMR.nothing to test."""
279
self.patch(SyncStateMachineRunner, 'nothing', faked_nothing)
281
# create a file and put it in local
283
somepath = os.path.join(self.root, 'somepath')
284
mdid = fsm.create(somepath, '')
285
fsm.set_by_mdid(mdid, local_hash='somehash')
287
# send the event, and check that it called its .nothing()
288
sync.handle_FS_FILE_CREATE(somepath)
289
self.assertTrue(self.called)
291
def test_SV_HASH_NEW_with_file_uploadinterrupted(self):
292
"""A SV_HASH_NEW is received after upload interrupted."""
293
sync = Sync(main=self.main)
296
def fake_meth(_, event, params, hash):
297
"""Wrap SSMR.reput_file_from_local to test."""
298
self.assertEqual(event, 'SV_HASH_NEW')
299
self.assertEqual(hash, '')
301
self.patch(SyncStateMachineRunner, 'reput_file_from_local', fake_meth)
303
# create a file and put it in local, without server_hash, as
304
# if the upload was cut in the middle after the make file
306
somepath = os.path.join(self.root, 'somepath')
307
mdid = fsm.create(somepath, '', node_id='node_id')
308
fsm.set_by_mdid(mdid, local_hash='somehash', crc32='crc32',
309
stat='stat', size='size')
311
# send the event and check
312
mdobj = fsm.get_by_mdid(mdid)
313
sync.handle_SV_HASH_NEW(mdobj.share_id, mdobj.node_id, '') # no content
314
self.assertTrue(self.called)
317
class SyncStateMachineRunnerTestCase(BaseSync):
267
318
"""Tests for the SyncStateMachineRunner."""
271
BaseTwistedTestCase.setUp(self)
272
self.ssmr = SyncStateMachineRunner(fsm=None, main=None,
273
key=DummyClass(), logger=None)
325
self.fsm = self.main.fs
326
somepath = os.path.join(self.root, 'somepath')
327
self.mdid = self.fsm.create(somepath, '', node_id='node_id')
329
key = FSKey(self.main.fs, share_id='', node_id='node_id')
330
self.ssmr = SyncStateMachineRunner(fsm=self.main.fs, main=self.main,
331
key=key, logger=None)
332
self.root = self.mktemp('root')
275
334
def tearDown(self):
278
BaseTwistedTestCase.tearDown(self)
337
BaseSync.tearDown(self)
280
def test_delete_file(self):
281
"""delete_file can be called with or without the server hash."""
339
def test_delete_file_without_hash(self):
340
"""Delete_file can be called without the server hash."""
282
341
self.ssmr.delete_file(event='AQ_DOWNLOAD_ERROR', params=None)
343
def test_delete_file_with_hash(self):
344
"""Delete_file can be called with the server hash."""
284
345
self.ssmr.delete_file(event='AQ_DOWNLOAD_ERROR', params=None,
348
def test_validateactualdata_log(self):
349
"""This method should log detailed info."""
350
# create testing data
351
somepath = os.path.join(self.root, 'somepath')
352
open(somepath, "w").close()
353
oldstat = os.stat(somepath)
354
f = open(somepath, "w")
359
handler = testcase.MementoHandler()
360
handler.setLevel(logging.DEBUG)
361
self.ssmr.log.addHandler(handler)
363
# call the method with args to not match
364
self.ssmr.validate_actual_data(somepath, oldstat)
367
self.assertEqual(len(handler.records), 1)
368
log_msg = handler.records[0].message
369
self.assertTrue("st_ino" in log_msg)
370
self.assertTrue("st_size" in log_msg)
371
self.assertTrue("st_mtime" in log_msg)
372
self.ssmr.log.removeHandler(handler)
374
def test_put_file_stores_info(self):
375
"""The put_file method should store the info in FSM."""
376
self.ssmr.put_file('HQ_HASH_NEW', None, 'hash', 'crc', 'size', 'stt')
378
# check the info is stored
379
mdobj = self.fsm.get_by_mdid(self.mdid)
380
self.assertEqual(mdobj.local_hash, 'hash')
381
self.assertEqual(mdobj.crc32, 'crc')
382
self.assertEqual(mdobj.size, 'size')
383
self.assertEqual(mdobj.stat, 'stt')
385
def test_reput_file_stores_info(self):
386
"""The reput_file method should store the info in FSM."""
387
self.ssmr.reput_file('HQ_HASH_NEW', None, 'hash', 'crc', 'size', 'stt')
389
# check the info is stored
390
mdobj = self.fsm.get_by_mdid(self.mdid)
391
self.assertEqual(mdobj.local_hash, 'hash')
392
self.assertEqual(mdobj.crc32, 'crc')
393
self.assertEqual(mdobj.size, 'size')
394
self.assertEqual(mdobj.stat, 'stt')
397
class FakedState(object):
400
def __init__(self, action_func):
401
self.action_func = action_func
404
def get_transition(self, event_name, parameters):
405
"""A fake get_transition."""
406
class A(object): pass
408
result.action_func = self.action_func
409
result.target = self.values
413
class StateMachineRunnerTestCase(BaseTwistedTestCase):
414
"""Test suite for StateMachineRunner."""
418
BaseTwistedTestCase.setUp(self)
420
logger = logging.getLogger('ubuntuone.SyncDaemon.sync')
421
self.smr = fsm_module.StateMachineRunner(None, logger)
422
self.handler = testcase.MementoHandler()
423
self.handler.setLevel(logging.INFO)
424
logger.addHandler(self.handler)
426
def test_on_event_logs_info(self):
427
"""Test proper logging in on_event."""
428
event_name = 'TEST_EVENT'
429
parameters = object()
430
action_func = 'SOME_ACTION_FUNC'
431
setattr(self.smr, action_func, lambda *_: None)
432
self.patch(self.smr, 'get_state', lambda: FakedState(action_func))
433
self.smr.on_event(event_name=event_name, parameters=parameters)
435
# assert over logging
436
self.assertTrue(len(self.handler.records), 1)
438
record = self.handler.records[0]
439
self.assertEqual(record.levelno, logging.INFO)
442
error = '%s must be in record.message (%s)'
443
self.assertTrue(event_name in msg, error % (event_name, msg))
444
self.assertTrue(str(parameters) in msg, error % (parameters, msg))
445
self.assertTrue(action_func in msg, error % (action_func, msg))