def test_remove_udf(udf_name, sd1, sd2, sd3, prefix): """Test 8: Remove an UDF, assert correct deletion on both clients.""" yield create_udf(udf_name, sd1, prefix) yield sd2.sdt.wait_for_nirvana(.5) assert os.path.exists(os.path.join(sd2.homedir, udf_name)) actual1 = walk_and_list_dir(os.path.join(sd1.homedir, udf_name)) actual2 = walk_and_list_dir(os.path.join(sd2.homedir, udf_name)) debug(prefix, "contents for SD1", actual1) assert actual1 == actual2 debug(prefix, "Removing the UDF:", udf_name) shutil.rmtree(os.path.join(sd1.homedir, udf_name)) yield sd1.sdt.wait_for_nirvana(.5) yield sd2.sdt.wait_for_nirvana(.5) events = [event['event_name'] for event in sd2.events] assert 'VM_VOLUME_DELETED' in events, 'VM_UDF_DELETED in sd2.events' debug(prefix, "VM_VOLUME_DELETED found on SD2") msg = 'UDF\'s contents must be deleted from file system on SD2.' udf_content = os.listdir(os.path.join(sd2.homedir, udf_name)) debug(prefix, 'contents for SD2', udf_content) assert udf_content == [], msg
def test_disconnect_modify_connect(udf_name, sd1, sd2, sd3, prefix): """Test 13: Create UDF, disconnect the SD, do stuff, and then reconnect.""" folder = yield create_udf(udf_name, sd1, prefix) folder_path = folder['path'] other_dir = os.path.join(folder_path, 'other_dir') os.mkdir(other_dir) third_dir = os.path.join(folder_path, 'third_dir') os.mkdir(third_dir) yield sd1.sdt.wait_for_nirvana(.5) debug(prefix, 'Disconnecting SD1.') yield sd1.sdt.disconnect() # disconnect SD1 debug(prefix, 'Doing stuff in the file system of SD1.') # do stuff in the file system xyz_dir = os.path.join(folder_path, 'x', 'y', 'z') os.makedirs(xyz_dir) create_file_and_add_content(os.path.join(xyz_dir, 'new.txt')) # move a file within the UDF os.rename(os.path.join(folder_path, 'a_dir', 'a_file.txt'), os.path.join(xyz_dir, 'renamed_file.txt')) # move a folder outside the UDF to the root dir os.rename(os.path.join(folder_path, 'other_dir'), os.path.join(sd1.rootdir, udf_name + 'renamed_other_dir')) # move a folder outside the UDF to the home dir renamed_third_dir = os.path.join(sd1.homedir, 'renamed_third_dir') os.rename(os.path.join(folder_path, 'third_dir'), renamed_third_dir) expected = set(walk_and_list_dir(sd1.homedir)) debug(prefix, "Expected to have", expected) debug(prefix, 'Re connecting SD1.') yield sd1.sdt.connect() # re-connect SD1 yield sd1.sdt.wait_for_nirvana(.5) debug(prefix, 'Waiting for nirvana for SD2.') yield sd2.sdt.wait_for_nirvana(.5) # wait for SD2 to get all the changes actual = set(walk_and_list_dir(sd2.homedir)) debug(prefix, "Currently found", actual) debug(prefix, 'expected sym diff actual', expected.symmetric_difference(actual)) assert expected.difference(actual) == set([u'renamed_third_dir']), \ 'SD1 home must have the same as SD2 except for renamed_third_dir.' assert actual.difference(expected) == set([]), \ 'SD2 home must have nothing extra than the SD1\'s.'
def test_unsuscribe_delete_subscribe(udf_name, sd1, sd2, sd3, prefix): """Test 14: unsubscribe and subsc., removing everything in the middle.""" # create udf folder = yield create_udf(udf_name, sd1, prefix) folder_id = folder["volume_id"] udf_path = folder["path"] debug(prefix, 'create_folder completed!', folder) assert folder['subscribed'], 'sd1 must be subscribed' yield sd1.sdt.wait_for_nirvana(.5) # un-subscribe and check yield sd1.sdt.unsubscribe_folder(folder_id) folders = yield sd1.sdt.get_folders() assert len(folders) == 1, "SD1 has udfs != 1 (%d)" % len(folders) assert not folders[0]['subscribed'], 'sd1 must NOT be subscribed' debug(prefix, 'unsubscribed!') # remove everything shutil.rmtree(udf_path) debug(prefix, 'everything removed from disk') yield sd1.sdt.wait_for_nirvana(.5) # subscribe and wait yield sd1.sdt.subscribe_folder(folder_id) folders = yield sd1.sdt.get_folders() assert len(folders) == 1, "SD1 has udfs != 1 (%d)" % len(folders) assert folders[0]['subscribed'], 'sd1 must be subscribed' yield sd1.sdt.wait_for_nirvana(.5) debug(prefix, 'subscribed!') # check stuff in disk for sd1 in_disk = walk_and_list_dir(udf_path) expected = ['a_dir', os.path.join('a_dir', 'a_file.txt')] assert in_disk == expected, \ "Wrong stuff in disk: %s (expected: %s)" % (in_disk, expected)
def test_merge_directories_no_overlap(udf_name, sd1, sd2, sd3, prefix): """Test 4: Assert directories are correctly merged if no overlapping.""" folderdir1 = os.path.join(sd1.homedir, udf_name) folderdir2 = os.path.join(sd2.homedir, udf_name) expected = [] os.mkdir(folderdir1) # add folders and files to folderdir1 on_sd1 = [] for d in ('a', 'b', 'c'): dirpath = os.path.join(folderdir1, d) os.makedirs(dirpath) expected.append(d) for f in ('foo1.txt', 'bar1.txt', 'syncdaemon1.log'): # flip a coin if random.random() < 0.5: filepath = os.path.join(dirpath, f) open(filepath, 'w').close() on_sd1.append(os.path.join(d, f)) debug(prefix, "created in sd1", on_sd1) expected.extend(on_sd1) os.mkdir(folderdir2) on_sd2 = [] # add folders and files to folderdir2 for d in ('z', 'y', 'x'): dirpath = os.path.join(folderdir2, d) os.makedirs(dirpath) expected.append(d) for f in ('foo2.txt', 'bar2.txt', 'syncdaemon2.log'): # flip a coin if random.random() < 0.5: filepath = os.path.join(dirpath, f) open(filepath, 'w').close() on_sd2.append(os.path.join(d, f)) debug(prefix, "created in sd2", on_sd2) expected.extend(on_sd2) expected.sort() debug(prefix, "Expected", expected) # create the folder on sd1 and wait sd2 to finish working yield sd1.sdt.create_folder(path=folderdir1) yield sd1.sdt.wait_for_nirvana(.5) folders = yield sd1.sdt.get_folders() debug(prefix, 'get_folders completed!', folders) assert len(folders) == 1 # UDF was reported as expected yield sd2.sdt.wait_for_nirvana(.5) actual = walk_and_list_dir(folderdir2) debug(prefix, 'Found in SD2', actual) assert expected == actual, 'directory merge successful'
def test_create_folder(udf_name, sd1, sd2, sd3, prefix): """Test 1: Assert correct folder creation.""" wait_for_udf_created = sd2.wait_for_event('VM_UDF_CREATED') yield create_udf(udf_name, sd1, prefix) yield wait_for_udf_created yield sd2.sdt.wait_for_nirvana(.5) folderdir1 = os.path.join(sd1.homedir, udf_name) folderdir2 = os.path.join(sd2.homedir, udf_name) expected = walk_and_list_dir(folderdir1) actual = walk_and_list_dir(folderdir2) debug(prefix, 'expected', expected) debug(prefix, 'actual', actual) assert expected == actual, 'UDF must be replicated correctly' with open(os.path.join(folderdir1, expected[-1])) as fd: content1 = fd.read() with open(os.path.join(folderdir1, actual[-1])) as fd: content2 = fd.read() assert content1 == content2, 'file content macth'
def test_unsusc_lotofchanges_subsc(udf_name, sd1, sd2, sd3, prefix): """Test 19: Merge should be done correctly.""" # some dirs and files udf_dir = os.path.join(sd1.homedir, udf_name) dir_a = os.path.join(udf_dir, "a") file_1 = os.path.join(dir_a, "file1") file_2 = os.path.join(dir_a, "file2") file_3 = os.path.join(dir_a, "file3") dir_b = os.path.join(udf_dir, "b") dir_c = os.path.join(udf_dir, "c") dir_d = os.path.join(udf_dir, "d") # we create an UDF and put: # - dir_a, with: # - file_1 # - file_2 # - dir_b # - dir_c folder, = yield sd1.sdt.create_folder(path=udf_dir) folder_id = folder["volume_id"] for d in (dir_a, dir_b, dir_c): os.mkdir(d) for f in (file_1, file_2): open(f, "w").close() debug(prefix, 'initial UDF completed!') yield sd1.sdt.wait_for_nirvana(.5) # unsubscribe yield sd1.sdt.unsubscribe_folder(folder_id) debug(prefix, 'unsubscribed!') # some changes: os.rmdir(dir_c) os.mkdir(dir_d) os.remove(file_2) open(file_3, "w").close() debug(prefix, 'changes made!') yield sd1.sdt.wait_for_nirvana(1) # subscribe again yield sd1.sdt.subscribe_folder(folder_id) debug(prefix, 'subscribed!') yield sd1.sdt.wait_for_nirvana(.5) yield sd2.sdt.wait_for_nirvana(.5) debug(prefix, 'changes propagated') # what the merge should do: # - dir_c is back from the server # - dir_d uploaded # - file_2 is back from the server # - file_3 uploaded to the server # - the rest should remain unchanged # to check, we verify everything in both clients expected = ['a', 'a/file1', 'a/file2', 'a/file3', 'b', 'c', 'd'] for which, sd in enumerate((sd1, sd2)): debug(prefix, 'check SD', sd) udf_dir = os.path.join(sd.homedir, udf_name) in_disk = walk_and_list_dir(udf_dir) assert in_disk == expected, "sd %s has bad stuff in "\ "disk: %s" % (which, in_disk)
def test_merge_directories_with_overlap(udf_name, sd1, sd2, sd3, prefix): """Test 5: Assert directories are correctly merge with overlapping.""" # Structure to start # # client 1: # .../a # .../a/conflict.txt (content random) # .../a/noconflict.txt (same content that 2) # .../a/bar.txt # .../b # # client 2: # .../a # .../a/conflict.txt (content random) # .../a/noconflict.txt (same content that 1) # .../a/beer.txt # .../c # # Result after UDF creation and merge: # # .../a/bar.txt and .../b are synced to client 2 # .../a/beer.txt and .../c are synced to client 1 # .../a/conflict.txt stays the same in one client, and in the other it # goes to conflict (depending on which got first to the server) # .../a/noconflict.txt stays ok in both clients # folderdir1 = os.path.join(sd1.homedir, udf_name) folderdir2 = os.path.join(sd2.homedir, udf_name) os.mkdir(folderdir1) # add folders and files to folderdir1 dirpath = os.path.join(folderdir1, 'a') os.makedirs(dirpath) filepath = os.path.join(dirpath, 'conflict.txt') create_file_and_add_content(filepath, content='content from SD1') filepath = os.path.join(dirpath, 'noconflict.txt') with open(filepath, "w") as fh: fh.write("same content") filepath = os.path.join(dirpath, 'bar.txt') create_file_and_add_content(filepath) dirpath = os.path.join(folderdir1, 'b') os.makedirs(dirpath) os.mkdir(folderdir2) # add folders and files to folderdir2 dirpath = os.path.join(folderdir2, 'a') os.makedirs(dirpath) filepath = os.path.join(dirpath, 'conflict.txt') create_file_and_add_content(filepath, content='content from SD2') filepath = os.path.join(dirpath, 'noconflict.txt') with open(filepath, "w") as fh: fh.write("same content") filepath = os.path.join(dirpath, 'beer.txt') create_file_and_add_content(filepath) dirpath = os.path.join(folderdir1, 'c') os.makedirs(dirpath) # wait for all changes to settle down yield sd2.sdt.wait_for_nirvana(.5) yield sd1.sdt.wait_for_nirvana(.5) # prepare the info to compare expected_no_conflict = ['a', 'b', 'c', os.path.join('a', 'bar.txt'), os.path.join('a', 'beer.txt'), os.path.join('a', 'noconflict.txt'), os.path.join('a', 'conflict.txt')] expected_no_conflict.sort() debug(prefix, 'expected without conflict', expected_no_conflict) expected_with_conflict = copy(expected_no_conflict) expected_with_conflict.append(os.path.join('a', 'conflict.txt.u1conflict')) expected_with_conflict.sort() debug(prefix, 'expected with conflict', expected_with_conflict) # create the UDF and wait everything to stop yield sd1.sdt.create_folder(path=folderdir1) yield sd2.sdt.wait_for_nirvana(.5) yield sd1.sdt.wait_for_nirvana(.5) actual1 = walk_and_list_dir(folderdir1) debug(prefix, 'actual content from SD1', actual1) actual2 = walk_and_list_dir(folderdir2) debug(prefix, 'actual content from SD2', actual2) # we don't know which client will enter in conflict, so we # tested both ways. if actual1 != expected_no_conflict: assert actual1 == expected_with_conflict, \ 'directory merge must be correct for SD1' assert actual2 == expected_no_conflict, \ 'directory merge must be correct for SD2' else: assert actual1 == expected_no_conflict, \ 'directory merge must be correct for SD1' assert actual2 == expected_with_conflict, \ 'directory merge must be correct for SD2'