Example #1
0
def test_bob_creates_alice_deletes_bob_restores(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob creates a file
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(
        join(alice_dir, "boom"),
        "bob wrote this"
    )

    # alice deletes it (so bob should as well
    unlink(join(alice_dir, "boom"))
    util.await_file_vanishes(join(bob_dir, "boom"))

    # bob restore it, with new contents
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this again, because reasons")

    # XXX double-check this behavior is correct!

    # alice sees bob's update, but marks it as a conflict (because
    # .. she previously deleted it? does that really make sense)

    util.await_file_contents(
        join(alice_dir, "boom.conflict"),
        "bob wrote this again, because reasons",
    )
Example #2
0
def test_bob_creates_alice_deletes_bob_restores(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob creates a file
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(join(alice_dir, "boom"), "bob wrote this")

    # alice deletes it (so bob should as well
    unlink(join(alice_dir, "boom"))
    util.await_file_vanishes(join(bob_dir, "boom"))

    # bob restore it, with new contents
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this again, because reasons")

    # XXX double-check this behavior is correct!

    # alice sees bob's update, but marks it as a conflict (because
    # .. she previously deleted it? does that really make sense)

    util.await_file_contents(
        join(alice_dir, "boom"),
        "bob wrote this again, because reasons",
    )
def test_bob_creates_alice_deletes_bob_restores(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob creates a file
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(
        join(alice_dir, "boom"),
        "bob wrote this"
    )

    # alice deletes it (so bob should as well .. but keep a backup)
    unlink(join(alice_dir, "boom"))
    util.await_file_vanishes(join(bob_dir, "boom"))
    assert exists(join(bob_dir, "boom.backup"))

    # bob restore it, with new contents
    unlink(join(bob_dir, "boom.backup"))
    with open(join(bob_dir, "boom"), "w") as f:
        f.write("bob wrote this again, because reasons")

    util.await_file_contents(
        join(alice_dir, "boom"),
        "bob wrote this again, because reasons",
    )
Example #4
0
def test_bob_writes_alice_receives(magic_folder):
    alice_dir, bob_dir = magic_folder

    with open(join(bob_dir, "second_file"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(join(alice_dir, "second_file"), "bob wrote this")
    return
Example #5
0
def test_alice_writes_bob_receives(magic_folder):
    alice_dir, bob_dir = magic_folder

    with open(join(alice_dir, "first_file"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(join(bob_dir, "first_file"), "alice wrote this")
    return
Example #6
0
def test_alice_creates_bob_edits(magic_folder):
    alice_dir, bob_dir = magic_folder

    # alice writes a file
    with open(join(alice_dir, "editfile"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(join(bob_dir, "editfile"), "alice wrote this")

    # now bob edits it
    with open(join(bob_dir, "editfile"), "w") as f:
        f.write("bob says foo")

    util.await_file_contents(join(alice_dir, "editfile"), "bob says foo")
def test_alice_writes_bob_receives_old_timestamp(magic_folder):
    alice_dir, bob_dir = magic_folder
    fname = join(alice_dir, "ts_file")
    ts = time.time() - (60 * 60 * 36)  # 36 hours ago

    with open(fname, "w") as f:
        f.write("alice wrote this")
    utime(fname, (time.time(), ts))

    fname = join(bob_dir, "ts_file")
    util.await_file_contents(fname, "alice wrote this")
    # make sure the timestamp is correct
    assert int(getmtime(fname)) == int(ts)
    return
Example #8
0
def test_alice_creates_bob_edits(magic_folder):
    alice_dir, bob_dir = magic_folder

    # alice writes a file
    with open(join(alice_dir, "editfile"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(join(bob_dir, "editfile"), "alice wrote this")

    # now bob edits it
    with open(join(bob_dir, "editfile"), "w") as f:
        f.write("bob says foo")

    util.await_file_contents(join(alice_dir, "editfile"), "bob says foo")
Example #9
0
def test_bob_conflicts_with_alice_preexisting(magic_folder):
    # both alice and bob edit a file at "the same time" (similar to
    # above, but the file already exists before the edits)
    alice_dir, bob_dir = magic_folder

    # have bob create the file
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("original beta (from bob)\n")
    util.await_file_contents(join(alice_dir, 'beta'), "original beta (from bob)\n")

    # both alice and bob now have a "beta" file, at version 0

    # really, we fudge this a little: in reality, either alice or bob
    # "wins" by uploading to the DMD first. So we make sure bob wins
    # this one by giving him a massive head start
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("this is bob's beta\n")
    time.sleep(0.5)
    with open(join(alice_dir, 'beta'), 'w') as f:
        f.write("this is alice's beta\n")

    # since bob uploaded first, alice should see a backup
    util.await_file_contents(join(bob_dir, 'beta'), "this is bob's beta\n")
    util.await_file_contents(join(alice_dir, 'beta'), "this is bob's beta\n")
    util.await_file_contents(join(alice_dir, 'beta.backup'), "this is alice's beta\n")
Example #10
0
def test_alice_writes_bob_receives_old_timestamp(magic_folder):
    alice_dir, bob_dir = magic_folder
    fname = join(alice_dir, "ts_file")
    ts = time.time() - (60 * 60 * 36)  # 36 hours ago

    with open(fname, "w") as f:
        f.write("alice wrote this")
    utime(fname, (time.time(), ts))

    fname = join(bob_dir, "ts_file")
    util.await_file_contents(fname, "alice wrote this")
    # make sure the timestamp is correct
    assert int(getmtime(fname)) == int(ts)
    return
Example #11
0
def test_bob_conflicts_with_alice_preexisting(magic_folder):
    # both alice and bob edit a file at "the same time" (similar to
    # above, but the file already exists before the edits)
    alice_dir, bob_dir = magic_folder

    # have bob create the file
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("original beta (from bob)\n")
    util.await_file_contents(join(alice_dir, 'beta'),
                             "original beta (from bob)\n")

    # both alice and bob now have a "beta" file, at version 0

    # really, we fudge this a little: in reality, either alice or bob
    # "wins" by uploading to the DMD first. So we make sure bob wins
    # this one by giving him a massive head start
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("this is bob's beta\n")
    time.sleep(1.0)
    with open(join(alice_dir, 'beta'), 'w') as f:
        f.write("this is alice's beta\n")

    # since bob uploaded first, alice should see a backup
    util.await_file_contents(join(bob_dir, 'beta'), "this is bob's beta\n")
    util.await_file_contents(join(alice_dir, 'beta'), "this is bob's beta\n")
    util.await_file_contents(join(alice_dir, 'beta.backup'),
                             "this is alice's beta\n")
Example #12
0
def test_alice_deletes(magic_folder):
    # alice writes a file, waits for bob to get it and then deletes it.
    alice_dir, bob_dir = magic_folder

    with open(join(alice_dir, "delfile"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(join(bob_dir, "delfile"), "alice wrote this")

    # bob has the file; now alices deletes it
    unlink(join(alice_dir, "delfile"))

    # bob should remove his copy, but preserve a backup
    util.await_file_vanishes(join(bob_dir, "delfile"))
    util.await_file_contents(join(bob_dir, "delfile.backup"), "alice wrote this")
    return
Example #13
0
def test_bob_creates_alice_deletes_alice_restores(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob creates a file
    with open(join(bob_dir, "boom2"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(join(alice_dir, "boom2"), "bob wrote this")

    # alice deletes it (so bob should as well
    unlink(join(alice_dir, "boom2"))
    util.await_file_vanishes(join(bob_dir, "boom2"))

    # alice restore it, with new contents
    with open(join(alice_dir, "boom2"), "w") as f:
        f.write("alice re-wrote this again, because reasons")
Example #14
0
def test_alice_deletes(magic_folder):
    # alice writes a file, waits for bob to get it and then deletes it.
    alice_dir, bob_dir = magic_folder

    with open(join(alice_dir, "delfile"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(join(bob_dir, "delfile"), "alice wrote this")

    # bob has the file; now alices deletes it
    unlink(join(alice_dir, "delfile"))

    # bob should remove his copy, but preserve a backup
    util.await_file_vanishes(join(bob_dir, "delfile"))
    util.await_file_contents(join(bob_dir, "delfile.backup"), "alice wrote this")
    return
Example #15
0
def test_bob_creates_sub_directory(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob makes a sub-dir, with a file in it
    mkdir(join(bob_dir, "subdir"))
    with open(join(bob_dir, "subdir", "a_file"), "w") as f:
        f.write("bob wuz here")

    # alice gets it
    util.await_file_contents(join(alice_dir, "subdir", "a_file"), "bob wuz here")

    # now bob deletes it again
    shutil.rmtree(join(bob_dir, "subdir"))

    # alice should delete it as well
    util.await_file_vanishes(join(alice_dir, "subdir", "a_file"))
    # i *think* it's by design that the subdir won't disappear,
    # because a "a_file.backup" should appear...
    util.await_file_contents(join(alice_dir, "subdir", "a_file.backup"), "bob wuz here")
Example #16
0
def test_bob_creates_alice_deletes_alice_restores(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob creates a file
    with open(join(bob_dir, "boom2"), "w") as f:
        f.write("bob wrote this")

    util.await_file_contents(
        join(alice_dir, "boom2"),
        "bob wrote this"
    )

    # alice deletes it (so bob should as well
    unlink(join(alice_dir, "boom2"))
    util.await_file_vanishes(join(bob_dir, "boom2"))

    # alice restore it, with new contents
    with open(join(alice_dir, "boom2"), "w") as f:
        f.write("alice re-wrote this again, because reasons")
Example #17
0
def test_bob_creates_sub_directory(magic_folder):
    alice_dir, bob_dir = magic_folder

    # bob makes a sub-dir, with a file in it
    mkdir(join(bob_dir, "subdir"))
    with open(join(bob_dir, "subdir", "a_file"), "w") as f:
        f.write("bob wuz here")

    # alice gets it
    util.await_file_contents(join(alice_dir, "subdir", "a_file"), "bob wuz here")

    # now bob deletes it again
    shutil.rmtree(join(bob_dir, "subdir"))

    # alice should delete it as well
    util.await_file_vanishes(join(alice_dir, "subdir", "a_file"))
    # i *think* it's by design that the subdir won't disappear,
    # because a "a_file.backup" should appear...
    util.await_file_contents(join(alice_dir, "subdir", "a_file.backup"), "bob wuz here")
def test_bob_conflicts_with_alice_preexisting(magic_folder):
    # both alice and bob edit a file at "the same time" (similar to
    # above, but the file already exists before the edits)
    alice_dir, bob_dir = magic_folder

    # have bob create the file
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("original beta (from bob)\n")
    util.await_file_contents(join(alice_dir, 'beta'), "original beta (from bob)\n")

    # both alice and bob now have a "beta" file, at version 0

    # either alice or bob will "win" by uploading to the DMD first
    # (however, they should both detect a conflict)
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("this is bob's beta\n")
    with open(join(alice_dir, 'beta'), 'w') as f:
        f.write("this is alice's beta\n")

    # both alice and bob should see a conflict
    _bob_conflicts_alice_await_conflicts("beta", alice_dir, bob_dir)
def test_bob_conflicts_with_alice_preexisting(magic_folder):
    # both alice and bob edit a file at "the same time" (similar to
    # above, but the file already exists before the edits)
    alice_dir, bob_dir = magic_folder

    # have bob create the file
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("original beta (from bob)\n")
    util.await_file_contents(join(alice_dir, 'beta'), "original beta (from bob)\n")

    # both alice and bob now have a "beta" file, at version 0

    # either alice or bob will "win" by uploading to the DMD first
    # (however, they should both detect a conflict)
    with open(join(bob_dir, 'beta'), 'w') as f:
        f.write("this is bob's beta\n")
    with open(join(alice_dir, 'beta'), 'w') as f:
        f.write("this is alice's beta\n")

    # both alice and bob should see a conflict
    _bob_conflicts_alice_await_conflicts("beta", alice_dir, bob_dir)
Example #20
0
def test_alice_writes_bob_receives_multiple(magic_folder):
    """
    When Alice does a series of updates, Bob should just receive them
    with no .backup or .conflict files being produced.
    """
    alice_dir, bob_dir = magic_folder

    unwanted_files = [
        join(bob_dir, "multiple.backup"),
        join(bob_dir, "multiple.conflict")
    ]

    # first update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(
        join(bob_dir, "multiple"),
        "alice wrote this",
        error_if=unwanted_files,
    )

    # second update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("someone changed their mind")

    util.await_file_contents(
        join(bob_dir, "multiple"),
        "someone changed their mind",
        error_if=unwanted_files,
    )

    # third update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("absolutely final version ship it")

    util.await_file_contents(
        join(bob_dir, "multiple"),
        "absolutely final version ship it",
        error_if=unwanted_files,
    )

    # forth update, but both "at once" so one should conflict
    time.sleep(2)
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("okay one more attempt")
    with open(join(bob_dir, "multiple"), "w") as f:
        f.write("...but just let me add")

    bob_conflict = join(bob_dir, "multiple.conflict")
    alice_conflict = join(alice_dir, "multiple.conflict")

    found = util.await_files_exist([
        bob_conflict,
        alice_conflict,
    ])

    assert len(found) > 0, "Should have found a conflict"
    print("conflict found (as expected)")
def test_alice_writes_bob_receives_multiple(magic_folder):
    """
    When Alice does a series of updates, Bob should just receive them
    with no .backup or .conflict files being produced.
    """
    alice_dir, bob_dir = magic_folder

    unwanted_files = [
        join(bob_dir, "multiple.backup"),
        join(bob_dir, "multiple.conflict")
    ]

    # first update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("alice wrote this")

    util.await_file_contents(
        join(bob_dir, "multiple"), "alice wrote this",
        error_if=unwanted_files,
    )

    # second update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("someone changed their mind")

    util.await_file_contents(
        join(bob_dir, "multiple"), "someone changed their mind",
        error_if=unwanted_files,
    )

    # third update
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("absolutely final version ship it")

    util.await_file_contents(
        join(bob_dir, "multiple"), "absolutely final version ship it",
        error_if=unwanted_files,
    )

    # forth update, but both "at once" so one should conflict
    time.sleep(2)
    with open(join(alice_dir, "multiple"), "w") as f:
        f.write("okay one more attempt")
    with open(join(bob_dir, "multiple"), "w") as f:
        f.write("...but just let me add")

    bob_conflict = join(bob_dir, "multiple.conflict")
    alice_conflict = join(alice_dir, "multiple.conflict")

    found = util.await_files_exist([
        bob_conflict,
        alice_conflict,
    ])

    assert len(found) > 0, "Should have found a conflict"
    print("conflict found (as expected)")
Example #22
0
def test_bob_conflicts_with_alice_fresh(magic_folder):
    # both alice and bob make a file at "the same time".
    alice_dir, bob_dir = magic_folder

    # really, we fudge this a little: in reality, either alice or bob
    # "wins" by uploading to the DMD first. So we make sure bob wins
    # this one by giving him a massive head start
    with open(join(bob_dir, 'alpha'), 'w') as f:
        f.write("this is bob's alpha\n")
    time.sleep(1.0)
    with open(join(alice_dir, 'alpha'), 'w') as f:
        f.write("this is alice's alpha\n")

    # since bob uploaded first, alice should see a backup
    util.await_file_contents(join(alice_dir, 'alpha'), "this is bob's alpha\n")
    util.await_file_contents(join(alice_dir, 'alpha.backup'), "this is alice's alpha\n")

    util.await_file_contents(join(bob_dir, 'alpha'), "this is alice's alpha\n")
    util.await_file_contents(join(bob_dir, 'alpha.backup'), "this is bob's alpha\n")
Example #23
0
def test_bob_conflicts_with_alice_fresh(magic_folder):
    # both alice and bob make a file at "the same time".
    alice_dir, bob_dir = magic_folder

    # really, we fudge this a little: in reality, either alice or bob
    # "wins" by uploading to the DMD first. So we make sure bob wins
    # this one by giving him a massive head start
    with open(join(bob_dir, 'alpha'), 'w') as f:
        f.write("this is bob's alpha\n")
    time.sleep(0.2)
    with open(join(alice_dir, 'alpha'), 'w') as f:
        f.write("this is alice's alpha\n")

    # since bob uploaded first, alice should see a backup
    util.await_file_contents(join(alice_dir, 'alpha'), "this is bob's alpha\n")
    util.await_file_contents(join(alice_dir, 'alpha.backup'), "this is alice's alpha\n")

    util.await_file_contents(join(bob_dir, 'alpha'), "this is alice's alpha\n")
    util.await_file_contents(join(bob_dir, 'alpha.backup'), "this is bob's alpha\n")