#!/usr/bin/env python3 # Once you have a ./sync command you can use this file to test it. # The fact this test program is in Python has nothing to do with the language # you use for your solution, because the command is called as though from the # command line. # Comment out the bits at the bottom of the program you don't want to run. # The order from 1 to 9 is mostly from easiest to hardest. import os import shutil import time def surround_test(message, test): print("*" * 40) print(message) test() print("*" * 40 + "\n") def print_directory(directory, spaces): """Pretty print a directory, with indenting indicating subdirectories.""" for file in os.listdir(directory): if file[0] != ".": # don't show files starting with '.' print(" " * spaces + "-" + file, end="") path = directory + "/" + file if os.path.isfile(path): modified_time = time.strftime("%Y-%m-%d %H:%M:%S %z", time.localtime(os.path.getmtime(path))) print(" " + str(os.path.getsize(path)) + " " + modified_time) else: print() if os.path.isdir(path): print_directory(path, spaces + 4) def print_file(name): with open(name) as file: print(file.read()) def remove_all_files(): # time.sleep(1) shutil.rmtree("dirA", ignore_errors=True) shutil.rmtree("dirB", ignore_errors=True) def remove_files(files): for file in files: os.remove(file) def test_sync(): os.system("./sync dirA dirB") def make_file(name, contents): with open(name, "w") as file: file.write("The contents of file, base/{}:\n".format(name) + contents) def append_file(name, extra): with open(name, "a") as file: file.write(extra) def setup_no_overlap(): remove_all_files() # make the directories os.mkdir("dirA") os.mkdir("dirB") # make the initial files make_file("dirA/a.txt", "Not very exciting really.") make_file("dirA/b.txt", "Also, not very exciting.") time.sleep(1) make_file("dirB/c.txt", "Still not very exciting.") make_file("dirB/d.txt", "A new file.") def setup_with_overlap(): setup_no_overlap() time.sleep(2) # to make sure the modified times are different make_file("dirB/a.txt", "This should replace the one in dirA. ") def setup_with_overlap_and_subdirectories(): remove_all_files() # make all of the directories for name in ["dirA", "dirA/dirA_1", "dirA/dirA_1/dirA_1_1", "dirA/dirA_2", "dirB", "dirB/dirB_1"]: os.mkdir(name) # make the initial files make_file("dirA/file1_1.txt", "Not very exciting really.") make_file("dirA/file1_2.txt", "Also, not very exciting.") make_file("dirA/dirA_1/dirA_1_1/file1_1_1_1.txt", "But the pathname is exciting.") make_file("dirA/dirA_2/file1_2_1.txt", "") make_file("dirB/file2_1.txt", "Still not very exciting.") make_file("dirB/dirB_1/file2_1_1.txt", "Also, not very exciting.") time.sleep(2) # to make sure the modified times are different make_file("dirB/file1_1.txt", "This should replace the one in dirA.") # The tests follow here def p1(): remove_all_files() test_sync() def p2(): remove_all_files() os.mkdir("dirA") test_sync() if not os.path.isfile("dirA/.sync"): print("dirA/.sync does not exist") if not os.path.isfile("dirB/.sync"): print("dirB/.sync does not exist") directories = [f for f in os.listdir(".") if os.path.isdir(f)] print("\n".join(directories)) def p3(): remove_all_files() os.mkdir("dirA") make_file("dirA/file1_1.txt", "Not very exciting really.") test_sync() print_file("dirA/.sync") def p4(): remove_all_files() os.mkdir("dirA") make_file("dirA/file1_1.txt", "Not very exciting really.") test_sync() print_file("dirA/.sync") append_file("dirA/file1_1.txt", "\nNew data written.") test_sync() print_file("dirA/.sync") def p5(): setup_no_overlap() test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) def p6(): setup_with_overlap() test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) def p7(): p6() print("\n --- then after the change ---\n") # now make changes to dirA extra = "\nchanged in both." append_file("dirA/a.txt", extra) append_file("dirA/b.txt", extra) append_file("dirA/c.txt", extra) test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) def p8(): p5() print("\n --- only c.txt ---\n") remove_files(["dirA/b.txt", "dirB/a.txt", "dirA/d.txt"]) test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) print("\n --- new b.txt ---\n") make_file("dirB/b.txt", "This doesn't hang around for long.") test_sync() time.sleep(1) os.remove("dirA/b.txt") test_sync() make_file("dirA/b.txt", "This one survives.") test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) print("\n --- dirA sync file ---") print_file("dirA/.sync") print("\n --- dirB sync file ---") print_file("dirB/.sync") def p9(): setup_with_overlap_and_subdirectories() test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) print("\n --- delete all files ---\n") remove_files(["dirA/file1_1.txt", "dirA/file1_2.txt", "dirA/dirA_1/dirA_1_1/file1_1_1_1.txt", "dirA/dirA_2/file1_2_1.txt", "dirB/file2_1.txt", "dirB/dirB_1/file2_1_1.txt"]) test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) print("\n --- recreate two ---\n") make_file("dirA/dirA_1/dirA_1_1/file1_1_1_1.txt", "I'm back.") make_file("dirA/file1_1.txt", "I'm back.") test_sync() print_directory('dirA', 0) print() print_directory('dirB', 0) # Run different parts of this test program by un/commenting the bits you do/don't want. surround_test("1. This should print an error (or usage) message:", p1) surround_test("2. This should show both dirA and dirB as directories (ignore others):", p2) surround_test("3. This should show sync file contents:", p3) surround_test("""4. This should show two different sync files. The first appears as the last entry in the second:""", p4) surround_test("""5. This should show two matching directories. Times and sizes should match in both directories:""", p5) surround_test("""6. This should show two matching directories with the file 'a.txt' 76 bytes long and the modification time later than b.txt:""", p6) surround_test("""7. This should show two pairs of matching directories with the second pair showing different sizes and modification times. a.txt may have the same time but different size. d.txt should be unchanged:""", p7) surround_test("""8. This should show the two directories. Then they should only contain c.txt. Then they should have a new version of b.txt:""", p8) surround_test("""9. This starts by showing the initial synchronized directories. file1_1.txt must be 81 bytes long:""", p9)