Example #1
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)")
Example #2
0
def test_alice_adds_files_while_bob_is_offline(reactor, request, temp_dir,
                                               magic_folder, bob):
    """
    Alice can add new files to a magic folder while Bob is offline.  When Bob
    comes back online his copy is updated to reflect the new files.
    """
    alice_magic_dir, bob_magic_dir = magic_folder
    alice_node_dir = join(temp_dir, "alice")

    # Take Bob offline.
    yield bob.stop_magic_folder()

    # Create a couple files in Alice's local directory.
    some_files = list((name * 3) + ".added-while-offline" for name in "xyz")
    for name in some_files:
        with open(join(alice_magic_dir, name), "w") as f:
            f.write(name + " some content")

    agent = Agent(reactor)

    upload_dircap = load_magic_folders(
        alice_node_dir)["default"]["upload_dircap"]

    # Alice's tahoe-lafs web api
    uri = "http://127.0.0.1:9980/uri/{}?t=json".format(upload_dircap)

    @pytest_twisted.inlineCallbacks
    def good_remote_state(agent):
        response = yield agent.request(
            b"GET",
            uri,
        )
        if response.code != 200:
            returnValue(False)

        files = json.loads((yield readBody(response)))
        print(files)
        returnValue(True)

    yield poll("good-remote-state", partial(good_remote_state, agent), reactor)

    # Start Bob up again
    yield bob.start_magic_folder()

    yield util.await_files_exist(
        list(join(bob_magic_dir, name) for name in some_files),
        await_all=True,
    )
    # Let it settle.  It would be nicer to have a readable status output we
    # could query.  Parsing the current text format is more than I want to
    # deal with right now.
    time.sleep(1.0)
    conflict_files = list(name + ".conflict" for name in some_files)
    assert all(
        list(not exists(join(bob_magic_dir, name))
             for name in conflict_files), )
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 #4
0
def test_alice_adds_files_while_bob_is_offline(reactor, request, temp_dir,
                                               magic_folder):
    """
    Alice can add new files to a magic folder while Bob is offline.  When Bob
    comes back online his copy is updated to reflect the new files.
    """
    alice_magic_dir, bob_magic_dir = magic_folder
    alice_node_dir = join(temp_dir, "alice")
    bob_node_dir = join(temp_dir, "bob")

    # Take Bob offline.
    yield util.cli(request, reactor, bob_node_dir, "stop")

    # Create a couple files in Alice's local directory.
    some_files = list((name * 3) + ".added-while-offline" for name in "xyz")
    for name in some_files:
        with open(join(alice_magic_dir, name), "w") as f:
            f.write(name + " some content")

    good = False
    for i in range(15):
        status = yield util.magic_folder_cli(request, reactor, alice_node_dir,
                                             "status")
        good = status.count(".added-while-offline (36 B): good, version=0"
                            ) == len(some_files) * 2
        if good:
            # We saw each file as having a local good state and a remote good
            # state.  That means we're ready to involve Bob.
            break
        else:
            time.sleep(1.0)

    assert good, ("Timed out waiting for good Alice state.  Last status:\n{}".
                  format(status))

    # Start Bob up again
    magic_text = 'Completed initial Magic Folder scan successfully'
    yield util._run_node(reactor, bob_node_dir, request, magic_text)

    yield util.await_files_exist(
        list(join(bob_magic_dir, name) for name in some_files),
        await_all=True,
    )
    # Let it settle.  It would be nicer to have a readable status output we
    # could query.  Parsing the current text format is more than I want to
    # deal with right now.
    time.sleep(1.0)
    conflict_files = list(name + ".conflict" for name in some_files)
    assert all(
        list(not exists(join(bob_magic_dir, name))
             for name in conflict_files), )
def _bob_conflicts_alice_await_conflicts(name, alice_dir, bob_dir):
    """
    shared code between _fresh and _preexisting conflict test
    """
    found = util.await_files_exist(
        [
            join(bob_dir, '{}.conflict'.format(name)),
            join(alice_dir, '{}.conflict'.format(name)),
        ],
    )

    assert len(found) >= 1, "should be at least one conflict"
    assert open(join(bob_dir, name), 'r').read() == "this is bob's {}\n".format(name)
    assert open(join(alice_dir, name), 'r').read() == "this is alice's {}\n".format(name)

    alice_conflict = join(alice_dir, '{}.conflict'.format(name))
    bob_conflict = join(bob_dir, '{}.conflict'.format(name))
    if exists(bob_conflict):
        assert open(bob_conflict, 'r').read() == "this is alice's {}\n".format(name)
    if exists(alice_conflict):
        assert open(alice_conflict, 'r').read() == "this is bob's {}\n".format(name)
def _bob_conflicts_alice_await_conflicts(name, alice_dir, bob_dir):
    """
    shared code between _fresh and _preexisting conflict test
    """
    found = util.await_files_exist(
        [
            join(bob_dir, '{}.conflict'.format(name)),
            join(alice_dir, '{}.conflict'.format(name)),
        ],
    )

    assert len(found) >= 1, "should be at least one conflict"
    assert open(join(bob_dir, name), 'r').read() == "this is bob's {}\n".format(name)
    assert open(join(alice_dir, name), 'r').read() == "this is alice's {}\n".format(name)

    alice_conflict = join(alice_dir, '{}.conflict'.format(name))
    bob_conflict = join(bob_dir, '{}.conflict'.format(name))
    if exists(bob_conflict):
        assert open(bob_conflict, 'r').read() == "this is alice's {}\n".format(name)
    if exists(alice_conflict):
        assert open(alice_conflict, 'r').read() == "this is bob's {}\n".format(name)
def test_alice_adds_files_while_bob_is_offline(reactor, request, temp_dir, magic_folder):
    """
    Alice can add new files to a magic folder while Bob is offline.  When Bob
    comes back online his copy is updated to reflect the new files.
    """
    alice_magic_dir, bob_magic_dir = magic_folder
    alice_node_dir = join(temp_dir, "alice")
    bob_node_dir = join(temp_dir, "bob")

    # Take Bob offline.
    yield util.cli(reactor, bob_node_dir, "stop")

    # Create a couple files in Alice's local directory.
    some_files = list(
        (name * 3) + ".added-while-offline"
        for name
        in "xyz"
    )
    for name in some_files:
        with open(join(alice_magic_dir, name), "w") as f:
            f.write(name + " some content")

    good = False
    for i in range(15):
        status = yield util.magic_folder_cli(reactor, alice_node_dir, "status")
        good = status.count(".added-while-offline (36 B): good, version=0") == len(some_files) * 2
        if good:
            # We saw each file as having a local good state and a remote good
            # state.  That means we're ready to involve Bob.
            break
        else:
            time.sleep(1.0)

    assert good, (
        "Timed out waiting for good Alice state.  Last status:\n{}".format(status)
    )

    # Start Bob up again
    magic_text = 'Completed initial Magic Folder scan successfully'
    yield util._run_node(reactor, bob_node_dir, request, magic_text)

    yield util.await_files_exist(
        list(
            join(bob_magic_dir, name)
            for name
            in some_files
        ),
        await_all=True,
    )
    # Let it settle.  It would be nicer to have a readable status output we
    # could query.  Parsing the current text format is more than I want to
    # deal with right now.
    time.sleep(1.0)
    conflict_files = list(name + ".conflict" for name in some_files)
    assert all(
        list(
            not exists(join(bob_magic_dir, name))
            for name
            in conflict_files
        ),
    )