コード例 #1
0
async def test_get_path_in_mountpoint(base_mountpoint, alice_user_fs,
                                      event_bus):
    # Populate a bit the fs first...
    wid = await alice_user_fs.workspace_create(EntryName("mounted_wksp"))
    wid2 = await alice_user_fs.workspace_create(EntryName("not_mounted_wksp"))
    workspace1 = alice_user_fs.get_workspace(wid)
    workspace2 = alice_user_fs.get_workspace(wid2)
    await workspace1.touch("/bar.txt")
    await workspace2.touch("/foo.txt")

    # Now we can start fuse
    async with mountpoint_manager_factory(
        alice_user_fs, event_bus, base_mountpoint) as mountpoint_manager:
        await mountpoint_manager.mount_workspace(wid)

        bar_path = mountpoint_manager.get_path_in_mountpoint(
            wid, FsPath("/bar.txt"))

        assert isinstance(bar_path, PurePath)
        # Windows uses drives, not base_mountpoint
        if sys.platform != "win32":
            expected = base_mountpoint / "mounted_wksp" / "bar.txt"
            assert str(bar_path) == str(expected.absolute())
        assert await trio.Path(bar_path).exists()

        with pytest.raises(MountpointNotMounted):
            mountpoint_manager.get_path_in_mountpoint(wid2, FsPath("/foo.txt"))
コード例 #2
0
ファイル: test_merging.py プロジェクト: Scille/parsec-cloud
def test_created_field_modified_by_remote(gen_date, alice, with_local_changes):
    d1, d2, d3, d4 = [gen_date() for _ in range(4)]

    w1 = WorkspaceEntry.new(name=EntryName("w1"), timestamp=d2)
    base = UserManifest(
        author=alice.device_id,
        timestamp=d2,
        id=alice.user_manifest_id,
        version=1,
        created=d1,
        updated=d2,
        last_processed_message=0,
        workspaces=(w1,),
    )

    local = LocalUserManifest.from_remote(base)
    if with_local_changes:
        w2 = WorkspaceEntry.new(name=EntryName("w1"), timestamp=d3)
        local = local.evolve(
            need_sync=True, updated=d3, last_processed_message=1, workspaces=(w1, w2)
        )

    target = base.evolve(created=d4, version=2)

    expected_merged = local.evolve(base=target)
    merged = merge_local_user_manifests(local, target)
    # Remote always control the value of the create field
    assert merged == expected_merged
コード例 #3
0
async def test_workspace_button_files(qtbot, workspace_fs, core_config,
                                      alice_user_info):
    switch_language(core_config, "en")

    roles = {alice_user_info.user_id: (WorkspaceRole.OWNER, alice_user_info)}
    w = WorkspaceButton.create(
        workspace_name=EntryName("Workspace"),
        workspace_fs=workspace_fs,
        users_roles=roles,
        is_mounted=True,
        files=[
            EntryName("File1.txt"),
            EntryName("File2.txt"),
            EntryName("Dir1")
        ],
    )

    qtbot.add_widget(w)
    w.show()
    assert w.widget_empty.isVisible() is False
    assert w.widget_files.isVisible() is True
    assert w.label_owner.isVisible() is True
    assert w.label_shared.isVisible() is False
    assert w.name == EntryName("Workspace")
    assert w.file1_name.text() == "File1.txt"
    assert w.file2_name.text() == "File2.txt"
    assert w.file3_name.text() == "Dir1"
    assert w.file4_name.text() == ""
コード例 #4
0
async def test_rename_workspace(initial_user_manifest_state, alice_user_fs,
                                alice):
    with freeze_time("2000-01-02"):
        wid = await alice_user_fs.workspace_create(EntryName("w1"))

    with freeze_time("2000-01-03"):
        await alice_user_fs.workspace_rename(wid, EntryName("w2"))

    um = alice_user_fs.get_user_manifest()
    expected_base_um = initial_user_manifest_state.get_user_manifest_v1_for_backend(
        alice)
    expected_um = LocalUserManifest(
        base=expected_base_um,
        need_sync=True,
        updated=datetime(2000, 1, 3),
        last_processed_message=expected_base_um.last_processed_message,
        workspaces=(WorkspaceEntry(
            name=EntryName("w2"),
            id=wid,
            key=KEY,
            encryption_revision=1,
            encrypted_on=datetime(2000, 1, 2),
            role_cached_on=datetime(2000, 1, 2),
            role=WorkspaceRole.OWNER,
        ), ),
        speculative=False,
    )
    um = _update_user_manifest_key(um)
    assert um == expected_um
コード例 #5
0
async def test_root_entry_info(alice_workspace_t2, alice_workspace_t4):
    stat2 = await alice_workspace_t2.transactions.entry_info(FsPath("/"))
    assert stat2 == {
        "type": "folder",
        "id": alice_workspace_t4.transactions.workspace_id,
        "base_version": 1,
        "is_placeholder": False,
        "need_sync": False,
        "created": datetime(1999, 12, 31),
        "updated": datetime(1999, 12, 31),
        "children": [EntryName("foo")],
        "confinement_point": None,
    }

    stat4 = await alice_workspace_t4.transactions.entry_info(FsPath("/"))
    assert stat4 == {
        "type": "folder",
        "id": alice_workspace_t4.transactions.workspace_id,
        "base_version": 2,
        "is_placeholder": False,
        "need_sync": False,
        "created": datetime(1999, 12, 31),
        "updated": datetime(2000, 1, 4),
        "children": [EntryName("files"), EntryName("foo")],
        "confinement_point": None,
    }
コード例 #6
0
async def test_sync(running_backend, alice2_user_fs, alice2):
    with freeze_time("2000-01-02"):
        wid = await alice2_user_fs.workspace_create(EntryName("w1"))

    with freeze_time("2000-01-03"):
        await alice2_user_fs.sync()

    um = alice2_user_fs.get_user_manifest()
    expected_base_um = UserManifest(
        author=alice2.device_id,
        timestamp=datetime(2000, 1, 3),
        id=alice2.user_manifest_id,
        version=2,
        created=datetime(2000, 1, 1),
        updated=datetime(2000, 1, 2),
        last_processed_message=0,
        workspaces=(WorkspaceEntry(
            name=EntryName("w1"),
            id=wid,
            key=KEY,
            encryption_revision=1,
            encrypted_on=datetime(2000, 1, 2),
            role_cached_on=datetime(2000, 1, 2),
            role=WorkspaceRole.OWNER,
        ), ),
    )
    expected_um = LocalUserManifest.from_remote(expected_base_um)
    um = _update_user_manifest_key(um)
    assert um == expected_um
コード例 #7
0
ファイル: test_merging.py プロジェクト: Scille/parsec-cloud
def test_merge_local_user_manifest_changes_placeholder(gen_date, alice, speculative_placeholder):
    d1, d2, d3, d4 = [gen_date() for _ in range(4)]

    w1 = WorkspaceEntry.new(name=EntryName("w1"), timestamp=d2)
    w2 = WorkspaceEntry.new(name=EntryName("w2"), timestamp=d2)
    w3 = WorkspaceEntry.new(name=EntryName("w3"), timestamp=d2)

    diverged = LocalUserManifest.new_placeholder(
        alice.device_id,
        id=alice.user_manifest_id,
        timestamp=d4,
        speculative=speculative_placeholder,
    ).evolve(last_processed_message=30, workspaces=(w1, w3))
    target = UserManifest(
        author=alice.device_id,
        timestamp=d2,
        id=alice.user_manifest_id,
        version=3,
        created=d1,
        updated=d3,
        last_processed_message=20,
        workspaces=(w1, w2),
    )
    expected_merged = LocalUserManifest(
        base=target,
        updated=d4,
        last_processed_message=30,
        workspaces=(w1, w2, w3),
        need_sync=True,
        speculative=False,
    )

    merged = merge_local_user_manifests(diverged, target)
    assert merged == expected_merged
コード例 #8
0
async def test_workspace_button_owned_by(qtbot, workspace_fs, core_config, bob,
                                         alice_user_info, bob_user_info):
    switch_language(core_config, "en")

    roles = {
        bob.user_id: (WorkspaceRole.OWNER, bob_user_info),
        alice_user_info.user_id: (WorkspaceRole.READER, alice_user_info),
    }
    w = WorkspaceButton.create(
        workspace_name=EntryName("Workspace"),
        workspace_fs=workspace_fs,
        users_roles=roles,
        is_mounted=True,
        files=[],
    )

    qtbot.add_widget(w)
    w.show()
    assert w.widget_empty.isVisible() is True
    assert w.widget_files.isVisible() is False
    assert w.label_owner.isVisible() is False
    assert w.label_shared.isVisible() is True
    assert w.name == EntryName("Workspace")
    assert w.label_title.text().startswith("Workspace")
    assert w.label_title.toolTip() == "Workspace (owned by Boby McBobFace)"
    assert w.label_role.text() == _("TEXT_WORKSPACE_ROLE_READER")
コード例 #9
0
async def test_manifest_no_access(running_backend, alice_user_fs, bob_user_fs):
    wid = await create_shared_workspace(EntryName("w"), alice_user_fs, bob_user_fs)
    alice_w = alice_user_fs.get_workspace(wid)
    bob_w = bob_user_fs.get_workspace(wid)
    await alice_w.touch("/foo.txt")
    await alice_w.sync()
    await bob_w.sync()

    # Load workspace manifest
    info = await bob_w.path_info("/")
    assert list(info["children"]) == [EntryName("foo.txt")]

    # Remove access to bob
    await alice_user_fs.workspace_share(wid, bob_user_fs.device.user_id, None)

    # No read access
    with pytest.raises(FSWorkspaceNoAccess) as exc:
        await bob_w.path_info("/foo.txt")
    assert str(exc.value) == "Cannot load manifest: no read access"

    # Touch a file locally
    await bob_w.touch("/bar.txt")
    bar_id = await bob_w.path_id("/bar.txt")

    # No write access
    with pytest.raises(FSWorkspaceNoAccess) as exc:
        await bob_w.sync_by_id(bar_id)
    assert str(exc.value) == "Cannot upload manifest: no write access"
コード例 #10
0
ファイル: test_files.py プロジェクト: Scille/parsec-cloud
async def test_show_inconsistent_dir(
    aqtbot, autoclose_dialog, files_widget_testbed, running_backend
):
    tb = files_widget_testbed

    # Create a new workspace and make user GUI knows about it
    await tb.logged_gui.test_switch_to_workspaces_widget()
    await create_inconsistent_workspace(user_fs=tb.user_fs, name=EntryName("wksp2"))

    # Now wait for GUI to take it into account
    def _workspace_available():
        assert tb.logged_gui.test_get_workspaces_widget().layout_workspaces.count() == 2

    await aqtbot.wait_until(_workspace_available)

    # Jump into the workspace, should be fine
    await tb.logged_gui.test_switch_to_files_widget(workspace_name=EntryName("wksp2"))
    await tb.check_files_view(
        workspace_name=EntryName("wksp2"), path="/", expected_entries=["rep/"]
    )

    # Now go into the folder containing the `newfail.txt` inconsistent file
    await tb.cd("rep")
    await tb.check_files_view(
        workspace_name=EntryName("wksp2"), path="/rep", expected_entries=["foo.txt", "newfail.txt!"]
    )
コード例 #11
0
async def test_share_workspace_then_rename_it(running_backend, alice_user_fs,
                                              bob_user_fs, alice, bob):
    # Share a workspace between Alice and Bob
    with freeze_time("2000-01-02"):
        wid = await alice_user_fs.workspace_create(EntryName("w"))
    await alice_user_fs.workspace_share(wid, bob.user_id,
                                        WorkspaceRole.MANAGER)
    with freeze_time("2000-01-03"):
        await bob_user_fs.process_last_messages()

    # Now Bob and alice both rename the workpsace for there own taste
    await bob_user_fs.workspace_rename(wid, EntryName("from_alice"))
    await alice_user_fs.workspace_rename(wid, EntryName("to_bob"))

    await bob_user_fs.sync()
    await alice_user_fs.sync()

    # This should have not changed the workspace in any way
    bw = bob_user_fs.get_workspace(wid)
    aw = alice_user_fs.get_workspace(wid)
    await bw.touch("/ping_bob.txt")
    await aw.mkdir("/ping_alice")

    await bw.sync()
    await aw.sync()
    await bw.sync()

    aw_stat = await aw.path_info("/")
    bw_stat = await bw.path_info("/")
    assert aw_stat == bw_stat
    assert aw_stat["id"] == wid
コード例 #12
0
async def test_concurrent_devices_agree_on_workspace_manifest(
        running_backend, user_fs_factory, data_base_dir,
        initialize_local_user_manifest, alice, alice2):
    await initialize_local_user_manifest(data_base_dir,
                                         alice,
                                         initial_user_manifest="v1")
    await initialize_local_user_manifest(data_base_dir,
                                         alice2,
                                         initial_user_manifest="v1")

    async with user_fs_factory(alice) as alice_user_fs:
        async with user_fs_factory(alice2) as alice2_user_fs:
            with freeze_time("2000-01-01"):
                wksp_id = await alice_user_fs.workspace_create(
                    EntryName("wksp"))
            # Sync user manifest (containing the workspace entry), but
            # not the corresponding workspace manifest !
            with freeze_time("2000-01-02"):
                await alice_user_fs.sync()

            # Retrieve the user manifest but not the workpace manifest, Alice2 hence has a speculative workspace manifest
            with freeze_time("2000-01-03"):
                await alice2_user_fs.sync()

            # Now workspace diverge between devices
            alice_wksp = alice_user_fs.get_workspace(wksp_id)
            alice2_wksp = alice2_user_fs.get_workspace(wksp_id)
            with freeze_time("2000-01-04"):
                await alice_wksp.mkdir("/from_alice")
            with freeze_time("2000-01-05"):
                await alice2_wksp.mkdir("/from_alice2")

            # Sync user_fs2 first to ensure created_on field is
            # kept even if further syncs have an earlier value
            with freeze_time("2000-01-06"):
                await alice2_wksp.sync()
            with freeze_time("2000-01-07"):
                await alice_wksp.sync()
            with freeze_time("2000-01-08"):
                await alice2_wksp.sync()

            # Now, both user fs should have the same view on workspace
            expected_alice_wksp_stat = {
                "id": wksp_id,
                "base_version": 3,
                "created": datetime(2000, 1, 1),
                "updated": datetime(2000, 1, 7),
                "is_placeholder": False,
                "need_sync": False,
                "type": "folder",
                "children":
                [EntryName("from_alice"),
                 EntryName("from_alice2")],
                "confinement_point": None,
            }
            alice_wksp_stat = await alice_wksp.path_info("/")
            alice2_wksp_stat = await alice2_wksp.path_info("/")
            assert alice_wksp_stat == expected_alice_wksp_stat
            assert alice2_wksp_stat == expected_alice_wksp_stat
コード例 #13
0
ファイル: test_types.py プロジェクト: Scille/parsec-cloud
def test_entry_name_normalization():
    nfc_str = normalize("NFC",
                        "àáâäæãåāçćčèéêëēėęîïíīįìłñńôöòóœøōõßśšûüùúūÿžźż")
    nfd_str = normalize("NFD", nfc_str)

    assert nfc_str != nfd_str
    assert EntryName(nfd_str).str == nfc_str
    assert EntryName(nfc_str).str == nfc_str
    assert EntryName(nfc_str + nfd_str).str == nfc_str + nfc_str
コード例 #14
0
 def _new_workspace_listed():
     assert w_w.layout_workspaces.count() == 2
     wk_button1 = w_w.layout_workspaces.itemAt(0).widget()
     wk_button2 = w_w.layout_workspaces.itemAt(1).widget()
     assert isinstance(wk_button1, WorkspaceButton)
     assert isinstance(wk_button2, WorkspaceButton)
     assert wk_button1.name in [EntryName("Workspace1"), EntryName("Workspace2")]
     assert wk_button2.name in [EntryName("Workspace1"), EntryName("Workspace2")]
     assert not w_w.filter_remove_button.isVisible()
コード例 #15
0
ファイル: test_winfsp.py プロジェクト: Scille/parsec-cloud
 async def _bootstrap(user_fs, mountpoint_manager):
     nonlocal x_path, y_path
     xid = await user_fs.workspace_create(EntryName("x"))
     xworkspace = user_fs.get_workspace(xid)
     await xworkspace.touch("/foo.txt")
     yid = await user_fs.workspace_create(EntryName("y"))
     x_path = await mountpoint_manager.mount_workspace(xid)
     y_path = await mountpoint_manager.mount_workspace(yid)
     print(x_path, y_path)
コード例 #16
0
async def test_autosync_placeholder_workspace_manifest(
    frozen_clock,
    running_backend,
    backend_data_binder,
    event_bus_factory,
    core_config,
    coolorg,
    alice,
    alice2,
):
    # Workspace created before user manifest placeholder sync
    await backend_data_binder.bind_organization(
        coolorg, alice, initial_user_manifest="not_synced")
    # Don't use `core_factory` fixture given it whole point is to waits for
    # monitors to be idle before returning the core
    async with logged_core_factory(
        core_config, alice, event_bus=event_bus_factory()) as alice_core:
        with alice_core.event_bus.listen() as spy:
            w1id = await alice_core.user_fs.workspace_create(EntryName("w1"))
            # Wait for the sync monitor to sync the new workspace
            await frozen_clock.sleep_with_autojump(60)
            await spy.wait_multiple_with_timeout(
                [
                    (CoreEvent.FS_ENTRY_SYNCED, {
                        "id": alice.user_manifest_id
                    }),
                    (CoreEvent.FS_ENTRY_SYNCED, {
                        "workspace_id": w1id,
                        "id": w1id
                    }),
                ],
                in_order=False,
            )

    # Workspace created on a synced user manifest
    await backend_data_binder.bind_device(alice2)
    async with logged_core_factory(
            core_config, alice2, event_bus=event_bus_factory()) as alice2_core:
        # Workspace created before user manifest placeholder sync
        with alice2_core.event_bus.listen() as spy:
            w2id = await alice2_core.user_fs.workspace_create(EntryName("w2"))
            await frozen_clock.sleep_with_autojump(60)
            await spy.wait_multiple_with_timeout(
                [
                    (CoreEvent.FS_ENTRY_SYNCED, {
                        "id": alice2.user_manifest_id
                    }),
                    (CoreEvent.FS_ENTRY_SYNCED, {
                        "workspace_id": w2id,
                        "id": w2id
                    }),
                ],
                in_order=False,
            )
コード例 #17
0
async def test_unshare_ok(running_backend, alice_user_fs, bob_user_fs, alice,
                          bob):
    # Share a workspace...
    with freeze_time("2000-01-02"):
        wid = await alice_user_fs.workspace_create(EntryName("w1"))
    await alice_user_fs.workspace_share(wid, bob.user_id, WorkspaceRole.OWNER)
    await bob_user_fs.process_last_messages()

    # ...and unshare it
    await bob_user_fs.workspace_share(wid, alice.user_id, None)
    with alice_user_fs.event_bus.listen() as spy:
        with freeze_time("2000-01-03"):
            await alice_user_fs.process_last_messages()

    new_events = []
    for event in spy.events:
        if event.event == CoreEvent.SHARING_UPDATED:
            event.kwargs["new_entry"] = event.kwargs["new_entry"].evolve(
                key=KEY)
            event.kwargs["previous_entry"] = event.kwargs[
                "previous_entry"].evolve(key=KEY)
        new_events.append(event)
    spy.events = new_events

    spy.assert_event_occured(
        CoreEvent.SHARING_UPDATED,
        {
            "new_entry":
            WorkspaceEntry(
                name=EntryName("w1"),
                id=wid,
                key=KEY,
                encryption_revision=1,
                encrypted_on=datetime(2000, 1, 2),
                role_cached_on=datetime(2000, 1, 3),
                role=None,
            ),
            "previous_entry":
            WorkspaceEntry(
                name=EntryName("w1"),
                id=wid,
                key=KEY,
                encryption_revision=1,
                encrypted_on=datetime(2000, 1, 2),
                role_cached_on=datetime(2000, 1, 2),
                role=WorkspaceRole.OWNER,
            ),
        },
    )

    aum = alice_user_fs.get_user_manifest()
    aw = aum.workspaces[0]
    assert not aw.role
コード例 #18
0
async def test_sharing_event_on_sync_if_same_role(running_backend,
                                                  alice_user_fs,
                                                  alice2_user_fs, bob_user_fs,
                                                  alice, bob):
    # Share a workspace, alice2 knows about it
    with freeze_time("2000-01-02"):
        wid = await create_shared_workspace(EntryName("w"), bob_user_fs,
                                            alice_user_fs, alice2_user_fs)
    expected_entry_v1 = WorkspaceEntry(
        name=EntryName("w"),
        id=wid,
        key=KEY,
        encryption_revision=1,
        encrypted_on=datetime(2000, 1, 2),
        role_cached_on=datetime(2000, 1, 2),
        role=WorkspaceRole.MANAGER,
    )

    # Then change alice's role...
    await bob_user_fs.workspace_share(wid, alice.user_id, WorkspaceRole.OWNER)
    with freeze_time("2000-01-03"):
        await alice_user_fs.process_last_messages()
    await alice_user_fs.sync()

    # ...and give back alice the same role
    await bob_user_fs.workspace_share(wid, alice.user_id,
                                      WorkspaceRole.MANAGER)
    with freeze_time("2000-01-04"):
        await alice_user_fs.process_last_messages()
    expected_entry_v3 = expected_entry_v1.evolve(
        role_cached_on=datetime(2000, 1, 4))
    await alice_user_fs.sync()

    # A single sharing event should be triggered
    with alice2_user_fs.event_bus.listen() as spy:
        await alice2_user_fs.sync()

    new_events = []
    for event in spy.events:
        if event.event == CoreEvent.SHARING_UPDATED:
            event.kwargs["new_entry"] = event.kwargs["new_entry"].evolve(
                key=KEY)
            event.kwargs["previous_entry"] = event.kwargs[
                "previous_entry"].evolve(key=KEY)
        new_events.append(event)
    spy.events = new_events
    spy.assert_event_occured(
        CoreEvent.SHARING_UPDATED,
        {
            "new_entry": expected_entry_v3,
            "previous_entry": expected_entry_v1
        },
    )
コード例 #19
0
 async def rename_workspace(self, workspace, new_name):
     wid, workspace = workspace
     src = f"/{workspace}"
     dst = f"/{new_name}"
     expected_status = self.oracle_fs.rename_workspace(src, dst)
     if expected_status == "ok":
         await self.user_fs.workspace_rename(wid, EntryName(new_name))
     else:
         with pytest.raises(FSWorkspaceNotFoundError):
             await self.user_fs.workspace_rename(
                 EntryID.new(), EntryName(new_name))
     return wid, new_name
コード例 #20
0
async def test_create_workspace_same_name(alice_user_fs):
    with freeze_time("2000-01-02"):
        w1id = await alice_user_fs.workspace_create(EntryName("w"))

    with freeze_time("2000-01-03"):
        w2id = await alice_user_fs.workspace_create(EntryName("w"))

    um = alice_user_fs.get_user_manifest()
    assert um.updated == datetime(2000, 1, 3)
    assert len(um.workspaces) == 2
    assert sorted((x.id, x.name)
                  for x in um.workspaces) == sorted([(w1id, EntryName("w")),
                                                     (w2id, EntryName("w"))])
コード例 #21
0
def test_entry_name():
    from parsec.api.data.entry import _RsEntryName, EntryName, _PyEntryName

    assert EntryName is _RsEntryName

    py_en = _PyEntryName("entry_name")
    rs_en = EntryName("entry_name")

    assert str(py_en) == str(rs_en)
    assert repr(py_en) == repr(rs_en)
    assert hash(py_en) == hash(rs_en)
    assert EntryName("a") == EntryName("a")
    assert EntryName("a") != EntryName("b")
コード例 #22
0
 def _workspace_filtered():
     assert w_w.isVisible()
     assert w_w.layout_workspaces.count() == 2
     wk_button_1 = w_w.layout_workspaces.itemAt(0).widget()
     wk_button_2 = w_w.layout_workspaces.itemAt(1).widget()
     assert isinstance(wk_button_1, WorkspaceButton)
     assert isinstance(wk_button_2, WorkspaceButton)
     assert wk_button_1.name in [EntryName("Workspace1"), EntryName("Workspace2")]
     assert wk_button_2.name in [EntryName("Workspace1"), EntryName("Workspace2")]
     assert w_w.filter_remove_button.isVisible()
     assert w_w.filter_label.text() == "Common workspaces with {}".format(
         alice.short_user_display
     )
コード例 #23
0
def test_folder_manifest():
    from parsec.api.data.manifest import _RsFolderManifest, FolderManifest, _PyFolderManifest

    assert FolderManifest is _RsFolderManifest

    def _assert_folder_manifest_eq(py, rs):
        assert isinstance(py, _PyFolderManifest)
        assert isinstance(rs, _RsFolderManifest)

        assert py.author == rs.author
        assert py.parent == rs.parent
        assert py.id == rs.id
        assert py.version == rs.version
        assert py.timestamp == rs.timestamp
        assert py.created == rs.created
        assert py.updated == rs.updated
        assert py.children == rs.children

    kwargs = {
        "author": DeviceID("user@device"),
        "id": EntryID.new(),
        "parent": EntryID.new(),
        "version": 42,
        "timestamp": pendulum.now(),
        "created": pendulum.now(),
        "updated": pendulum.now(),
        "children": {
            EntryName("file1.txt"): EntryID.new()
        },
    }
    py_wm = _PyFolderManifest(**kwargs)
    rs_wm = FolderManifest(**kwargs)
    _assert_folder_manifest_eq(py_wm, rs_wm)

    kwargs = {
        "author": DeviceID("a@b"),
        "id": EntryID.new(),
        "parent": EntryID.new(),
        "version": 1337,
        "timestamp": pendulum.now(),
        "created": pendulum.now(),
        "updated": pendulum.now(),
        "children": {
            EntryName("file2.mp4"): EntryID.new()
        },
    }

    py_wm = py_wm.evolve(**kwargs)
    rs_wm = rs_wm.evolve(**kwargs)
    _assert_folder_manifest_eq(py_wm, rs_wm)
コード例 #24
0
ファイル: winify.py プロジェクト: Scille/parsec-cloud
def winify_entry_name(name: EntryName) -> str:
    name = name.str
    prefix, *suffixes = name.split(".", 1)
    if prefix in _WIN32_RES_NAMES:
        full_suffix = f".{'.'.join(suffixes)}" if suffixes else ""
        name = f"{prefix[:-1]}~{ord(prefix[-1]):02x}{full_suffix}"

    else:
        for reserved in _WIN32_RES_CHARS:
            name = name.replace(reserved, f"~{ord(reserved):02x}")

    if name[-1] in (".", " "):
        name = f"{name[:-1]}~{ord(name[-1]):02x}"

    return name
コード例 #25
0
async def test_file_history(aqtbot, running_backend, logged_gui,
                            autoclose_dialog, catch_file_history_widget):
    core = logged_gui.test_get_core()
    wid = await core.user_fs.workspace_create(EntryName("wksp1"))
    wfs = core.user_fs.get_workspace(wid)

    w_w = logged_gui.test_get_workspaces_widget()

    def _workspace_available():
        assert w_w.layout_workspaces.count() == 1

    await aqtbot.wait_until(_workspace_available)

    f_w = await logged_gui.test_switch_to_files_widget(EntryName("wksp1"))

    # Add an entry to the workspace
    await wfs.touch("/file.txt")
    await wfs.sync()
    await wfs.write_bytes("/file.txt", data=b"v2")
    await wfs.sync()

    def _entry_available():
        assert f_w.table_files.rowCount() == 2

    await aqtbot.wait_until(_entry_available)

    # First select the entry...
    f_w.table_files.setRangeSelected(
        QtWidgets.QTableWidgetSelectionRange(1, 0, 1, 0), True)

    def _entry_selected():
        assert f_w.table_files.selectedItems()

    await aqtbot.wait_until(_entry_selected)

    # ...then ask for history
    f_w.table_files.show_history_clicked.emit()

    hf_w = await catch_file_history_widget()

    def _history_displayed():
        assert hf_w.isVisible()
        assert hf_w.layout_history.count() == 1
        hb2_w = hf_w.layout_history.itemAt(0).widget()
        assert hb2_w.label_user.text() == "Boby McBobFace"
        assert hb2_w.label_version.text() == "2"

    await aqtbot.wait_until(_history_displayed)
コード例 #26
0
async def test_outsider_profil_limit(
    aqtbot, running_backend, adam, core_config, gui_factory, alice_user_fs
):
    wid = await alice_user_fs.workspace_create(EntryName("workspace1"))
    await alice_user_fs.workspace_share(wid, adam.user_id, WorkspaceRole.READER)
    await alice_user_fs.process_last_messages()
    await alice_user_fs.sync()

    gui = await gui_factory()
    await gui.test_switch_to_logged_in(adam)

    w_w = await gui.test_switch_to_workspaces_widget()

    def _workspace_button_shown():
        layout_workspace = w_w.layout_workspaces.itemAt(0)
        assert layout_workspace is not None
        workspace_button = layout_workspace.widget()
        assert not isinstance(workspace_button, QtWidgets.QLabel)

    await aqtbot.wait_until(_workspace_button_shown)
    layout_workspace = w_w.layout_workspaces.itemAt(0)
    workspace_button = layout_workspace.widget()
    assert workspace_button.button_share.isVisible() is False
    assert w_w.button_add_workspace.isVisible() is False

    c_w = gui.test_get_central_widget()
    assert c_w.menu.button_users.isVisible() is False
コード例 #27
0
async def testbed(running_backend, alice_user_fs, alice, bob):
    with freeze_time("2000-01-01"):
        wid = await alice_user_fs.workspace_create(EntryName("w1"))
        workspace = alice_user_fs.get_workspace(wid)
        await workspace.sync()
        local_manifest = await workspace.local_storage.get_manifest(wid)
    with freeze_time("2000-01-03"):
        await alice_user_fs.workspace_share(wid, bob.user_id,
                                            WorkspaceRole.MANAGER)

    class TestBed:
        def __init__(self):
            self._next_version = 2
            self.defaults = {
                "local_manifest": local_manifest,
                "blob": None,
                "signed_author": alice.device_id,
                "backend_author": alice.device_id,
                "signed_timestamp": datetime(2000, 1, 2),
                "backend_timestamp": datetime(2000, 1, 2),
                "author_signkey": alice.signing_key,
                "key": workspace.get_workspace_entry().key,
            }

        async def run(self, exc_msg, **kwargs):
            options = {**self.defaults, **kwargs}

            if options["blob"] is None:
                to_sync_um = options["local_manifest"].to_remote(
                    author=options["signed_author"],
                    timestamp=options["signed_timestamp"])
                options["blob"] = to_sync_um.dump_sign_and_encrypt(
                    author_signkey=options["author_signkey"],
                    key=options["key"])

            await running_backend.backend.vlob.update(
                organization_id=alice.organization_id,
                author=options["backend_author"],
                encryption_revision=1,
                vlob_id=VlobID(wid.uuid),
                version=self._next_version,
                timestamp=options["backend_timestamp"],
                blob=options["blob"],
            )
            self._next_version += 1

            # This should trigger FSError
            with pytest.raises(FSError) as exc:
                await workspace.sync()
            assert str(exc.value) == exc_msg

            # Also test timestamped workspace
            # Note: oxidation doesn't implement WorkspaceStorageTimestamped
            if not IS_OXIDIZED:
                with pytest.raises(FSError) as exc:
                    await workspace.to_timestamped(options["backend_timestamp"]
                                                   )
                assert str(exc.value) == exc_msg

    return TestBed()
コード例 #28
0
ファイル: test_files.py プロジェクト: Scille/parsec-cloud
        async def check_files_view(self, path, expected_entries, workspace_name=EntryName("wksp1")):
            expected_table_files = []
            # Parent dir line brings to workspaces list if we looking into workspace's root
            if path == "/":
                expected_table_files.append(("Workspaces list", FileType.ParentWorkspace))
            else:
                expected_table_files.append(("Parent folder", FileType.ParentFolder))
            # Table contains one line per files + the "parent dir" line
            for name in expected_entries:
                if name.endswith("/"):
                    expected_table_files.append((name[:-1], FileType.Folder))
                elif name.endswith("!"):
                    expected_table_files.append((name[:-1], FileType.Inconsistency))
                else:
                    expected_table_files.append((name, FileType.File))

            def _view_ok():
                # Check title (top part of the GUI)
                assert c_w.navigation_bar_widget.workspace_name == workspace_name
                assert str(c_w.navigation_bar_widget.get_current_path()) == path
                # Now check actual files view
                assert f_w.workspace_fs.get_workspace_name() == workspace_name
                assert f_w.table_files.rowCount() == len(expected_table_files)
                for i, (name, type) in enumerate(expected_table_files):
                    assert f_w.table_files.item(i, 1).text() == name
                    for j in range(5):
                        assert f_w.table_files.item(i, j).data(TYPE_DATA_INDEX) == type

            await aqtbot.wait_until(_view_ok)
コード例 #29
0
async def test_realm_notif_maintenance(running_backend, alice_backend_conn, alice2_user_fs):
    wid = await alice2_user_fs.workspace_create(EntryName("foo"))
    await alice2_user_fs.sync()

    with alice_backend_conn.event_bus.listen() as spy:
        # Start maintenance
        job = await alice2_user_fs.workspace_start_reencryption(wid)

        await spy.wait_multiple_with_timeout(
            [
                (
                    CoreEvent.BACKEND_REALM_MAINTENANCE_STARTED,
                    {"realm_id": wid, "encryption_revision": 2},
                ),
                # Receive the message containing the new key and encryption revision
                CoreEvent.BACKEND_MESSAGE_RECEIVED,
            ]
        )

    with alice_backend_conn.event_bus.listen() as spy:
        # Finish maintenance
        total, done = await job.do_one_batch()
        assert total == done

        await spy.wait_with_timeout(
            CoreEvent.BACKEND_REALM_MAINTENANCE_FINISHED,
            {"realm_id": wid, "encryption_revision": 2},
        )
コード例 #30
0
async def test_block_no_access(running_backend, alice_user_fs, bob_user_fs):
    wid = await create_shared_workspace(EntryName("w"), alice_user_fs, bob_user_fs)
    alice_w = alice_user_fs.get_workspace(wid)
    bob_w = bob_user_fs.get_workspace(wid)
    await alice_w.touch("/foo.txt")
    await alice_w.write_bytes("/foo.txt", b"foo data")
    await alice_w.sync()
    await bob_w.sync()

    # Ensure file manifest is in cache (but not blocks)
    await bob_w.path_info("/foo.txt")

    # Remove access to bob
    await alice_user_fs.workspace_share(wid, bob_user_fs.device.user_id, None)

    # Try to access blocks
    with pytest.raises(FSWorkspaceNoAccess) as exc:
        await bob_w.read_bytes("/foo.txt")
    assert str(exc.value) == "Cannot load block: no read access"

    await bob_w.touch("/bar.txt")
    bar_id = await bob_w.path_id("/bar.txt")
    await bob_w.write_bytes("/bar.txt", b"bar data")
    with pytest.raises(FSWorkspaceNoAccess) as exc:
        await bob_w.sync_by_id(bar_id)
    assert str(exc.value) == "Cannot upload block: no write access"