示例#1
0
    def test_nfs_mounted(self, mock_is_nfs_mounted) -> None:
        mock_is_nfs_mounted.return_value = True
        instance = FakeEdenInstance(self.make_temporary_directory())
        checkout = instance.create_test_mount("mount_dir")

        dry_run = True
        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            typing.cast(EdenInstance, instance),
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )
        expected = f"""<yellow>- Found problem:<reset>
Eden's state directory is on an NFS file system: {instance.state_dir}
  This will likely cause performance problems and/or other errors.
The most common cause for this is if your ~/local symlink does not point to local disk.  Make sure that ~/local is a symlink pointing to local disk and then restart Eden.

Checking {checkout.path}
<yellow>- Found problem:<reset>
The Mercurial data directory for {checkout.path}/.hg/sharedpath is at {instance.default_backing_repo}/.hg which is on a NFS filesystem. Accessing files and directories in this repository will be slow.
<yellow>Discovered 2 problems during --dry-run<reset>
"""
        self.assertEqual(expected, out.getvalue())
        self.assertEqual(1, exit_code)
示例#2
0
    def test_privhelper_check_accessible(
            self, mock_check_privhelper_connection) -> None:
        instance = FakeEdenInstance(self.make_temporary_directory())
        mount = instance.create_test_mount("path1").path
        dry_run = False
        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            # pyre-fixme[6]: For 1st param expected `EdenInstance` but got
            #  `FakeEdenInstance`.
            instance,
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            f"""\
Checking {mount}
<green>No issues detected.<reset>
""",
            out.getvalue(),
        )
        self.assertEqual(0, exit_code)
示例#3
0
    def test_privhelper_check_not_accessible(self,
                                             mock_check_privhelper_connection):
        instance = FakeEdenInstance(self.make_temporary_directory())
        mount = instance.create_test_mount("path1").path
        dry_run = False
        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            f"""\
<yellow>- Found problem:<reset>
The PrivHelper process is not accessible.
To restore the connection to the PrivHelper, run `eden restart`

Checking {mount}
<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        self.assertEqual(1, exit_code)
示例#4
0
    def test_edenfs_starting(self, mock_get_roots_for_nuclide, mock_watchman):
        instance = FakeEdenInstance(self.make_temporary_directory(),
                                    status=fb303_status.STARTING)
        instance.create_test_mount("eden-mount")

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            FakeMountTable(),
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            """\
<yellow>- Found problem:<reset>
Eden is currently still starting.
Please wait for edenfs to finish starting.
If Eden seems to be taking too long to start you can try restarting it
with "eden restart"

<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        self.assertEqual(1, exit_code)
示例#5
0
    def test_edenfs_stopping(self, mock_get_roots_for_nuclide, mock_watchman):
        instance = FakeEdenInstance(self.make_temporary_directory(),
                                    status=fb303_status.STOPPING)
        instance.create_test_mount("eden-mount")

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            FakeMountTable(),
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            """\
<yellow>- Found problem:<reset>
Eden is currently shutting down.
Either wait for edenfs to exit, or to forcibly kill Eden, run:

    eden stop --kill

<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        self.assertEqual(1, exit_code)
示例#6
0
    def test_issue_includes_custom_message_from_config(self) -> None:
        self._mock_disk_usage(blocks=100000000, avail=500000)
        instance = FakeEdenInstance(
            self.make_temporary_directory(),
            config={
                "doctor.low-disk-space-message":
                "Ask your administrator for help."
            },
        )
        problems = self._check_disk_usage(instance=instance)
        self.assertEqual(
            problems[0].description(),
            "/ has only 512000000 bytes available. "
            "Eden lazily loads your files and needs enough disk "
            "space to store these files when loaded. Ask your administrator "
            "for help.",
        )

        self._mock_disk_usage(blocks=100000000, avail=2000000)
        instance = FakeEdenInstance(
            self.make_temporary_directory(),
            config={
                "doctor.low-disk-space-message":
                "Ask your administrator for help."
            },
        )
        problems = self._check_disk_usage(instance=instance)
        self.assertEqual(
            problems[0].description(),
            "/ is 98.00% full. "
            "Eden lazily loads your files and needs enough disk "
            "space to store these files when loaded. Ask your administrator "
            "for help.",
        )
示例#7
0
    def test_edenfs_not_running(self, mock_get_roots_for_nuclide,
                                mock_watchman):
        instance = FakeEdenInstance(self.make_temporary_directory(),
                                    status=fb303_status.DEAD)
        instance.create_test_mount("eden-mount")

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            FakeMountTable(),
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            out=out,
        )

        self.assertEqual(
            """\
<yellow>- Found problem:<reset>
Eden is not running.
To start Eden, run:

    eden start

<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        self.assertEqual(1, exit_code)
示例#8
0
    def test_unconfigured_mounts_dont_crash(self, mock_get_roots_for_nuclide):
        # If Eden advertises that a mount is active, but it is not in the
        # configuration, then at least don't throw an exception.
        instance = FakeEdenInstance(self.make_temporary_directory())
        edenfs_path1 = instance.create_test_mount("path1").path
        edenfs_path2 = instance.create_test_mount("path2").path
        # Remove path2 from the list of mounts in the instance
        instance.remove_checkout_configuration(str(edenfs_path2))

        dry_run = False
        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            out=out,
        )

        self.assertEqual(
            f"""\
Checking {edenfs_path1}
Checking {edenfs_path2}
<yellow>- Found problem:<reset>
Checkout {edenfs_path2} is running but not listed in Eden's configuration file.
Running "eden unmount {edenfs_path2}" will unmount this checkout.

<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        self.assertEqual(1, exit_code)
示例#9
0
    def test_twice_failed_bind_unmount(
        self,
        mock_buckd_running: MagicMock,
        mock_expand_path: MagicMock,
        mock_analyze: MagicMock,
        mock_bind_unmount: MagicMock,
    ) -> None:
        temp_dir = self.make_temporary_directory()
        repo_path = os.path.join(temp_dir, "test")

        mock_bind_unmount.return_value = None
        mock_analyze.return_value = RepoPathDisposition.IS_BIND_MOUNT
        mock_expand_path.return_value = Path(repo_path)
        mock_buckd_running.return_value = False

        instance = FakeEdenInstance(temp_dir)
        checkout = instance.create_test_mount("mount_dir")
        redir = Redirection(
            repo_path=Path(repo_path),
            redir_type=RedirectionType.BIND,
            target=None,
            source="mount",
            state=RedirectionState.UNKNOWN_MOUNT,
        )

        with self.assertRaises(Exception) as ex:
            redir.remove_existing(checkout)

        error_msg = f"Failed to remove {repo_path} since the bind unmount failed"
        self.assertEqual(str(ex.exception), error_msg)
示例#10
0
    def _test_hash_check(
        self,
        dirstate_hash_hex: str,
        snapshot_hex: str,
        dirstate_parent2_hash_hex=None,
        commit_checker: Optional[Callable[[str], bool]] = None,
    ) -> Tuple[EdenCheckout, doctor.ProblemFixer, str]:
        instance = FakeEdenInstance(self.make_temporary_directory())
        if dirstate_parent2_hash_hex is None:
            checkout = instance.create_test_mount(
                "path1",
                snapshot=snapshot_hex,
                dirstate_parent=dirstate_hash_hex)
        else:
            checkout = instance.create_test_mount(
                "path1",
                snapshot=snapshot_hex,
                dirstate_parent=(dirstate_hash_hex, dirstate_parent2_hash_hex),
            )

        hg_repo = checkout.instance.get_hg_repo(checkout.path)
        if commit_checker and hg_repo is not None:
            fake_hg_repo = typing.cast(FakeHgRepo, hg_repo)
            fake_hg_repo.commit_checker = commit_checker

        fixer, out = self.create_fixer(dry_run=False)
        check_hg.check_hg(fixer, checkout)
        return checkout, fixer, out.getvalue()
示例#11
0
    def test_fixup_only_eden_redirection(
        self,
        mock_get_effective_redirections: MagicMock,
        mock_require_checkout: MagicMock,
        mock_remove_existing: MagicMock,
        mock_apply: MagicMock,
    ) -> None:
        temp_dir = self.make_temporary_directory()
        repo_path = os.path.join(temp_dir, "test")
        instance = FakeEdenInstance(temp_dir)
        checkout = instance.create_test_mount("mount_dir")
        eden_path = os.path.join(temp_dir, "mount_dir")
        mock_require_checkout.return_value = (instance, checkout, eden_path)

        mock_argument_parser = MagicMock(spec=argparse.ArgumentParser)
        args = argparse.Namespace(mount=eden_path, all_sources=False)

        redir = Redirection(
            repo_path=Path(repo_path),
            redir_type=RedirectionType.BIND,
            target=None,
            source="mount",
            state=RedirectionState.UNKNOWN_MOUNT,
        )
        mock_get_effective_redirections.return_value = {repo_path: redir}

        test_fixup_cmd = FixupCmd(mock_argument_parser)
        test_fixup_cmd.run(args)

        mock_remove_existing.assert_not_called()
        mock_apply.assert_not_called()
示例#12
0
    def test_pwd_not_set(self) -> None:
        tmp_dir = self.make_temporary_directory()
        instance = FakeEdenInstance(tmp_dir)
        mount = instance.create_test_mount("path1").path

        exit_code, out = self._test_with_pwd(instance, pwd=None)
        self.assertEqual(
            out,
            f"""\
Checking {mount}
<green>No issues detected.<reset>
""",
        )
        self.assertEqual(0, exit_code)
示例#13
0
    def test_materialized_are_accessible(self, mock_debugInodeStatus) -> None:
        instance = FakeEdenInstance(self.make_temporary_directory())
        checkout = instance.create_test_mount("path1")
        mount = checkout.path

        # Just create a/b/c folders
        os.makedirs(mount / "a" / "b")

        mock_debugInodeStatus.return_value = [
            # Pretend that a/b is a file (it's a directory)
            TreeInodeDebugInfo(
                1,
                b"a",
                True,
                b"abcd",
                [
                    TreeInodeEntryDebugInfo(b"b", 2, stat.S_IFREG, False, True,
                                            b"dcba")
                ],
                1,
            ),
            # Pretent that a/b/c is a directory (it doesn't exists)
            TreeInodeDebugInfo(
                2,
                b"a/b",
                True,
                b"dcba",
                [
                    TreeInodeEntryDebugInfo(b"c", 3, stat.S_IFREG, False, True,
                                            b"1234")
                ],
                1,
            ),
        ]

        tracker = ProblemCollector()
        check_materialized_are_accessible(tracker,
                                          typing.cast(EdenInstance, instance),
                                          checkout)

        self.assertEqual(
            tracker.problems[0].description(),
            "a/b/c is inaccessible despite EdenFS believing it should be",
        )
        self.assertEqual(
            tracker.problems[1].description(),
            "a/b is known to EdenFS as a file, but is a directory on disk",
        )
示例#14
0
文件: os_test.py 项目: zerkella/eden
 def setUp(self) -> None:
     test_config = {
         "doctor.minimum-kernel-version": "4.11.3-67",
         "doctor.known-bad-kernel-versions": "TODO,TEST",
     }
     tmp_dir = self.make_temporary_directory()
     self.instance = FakeEdenInstance(tmp_dir, config=test_config)
示例#15
0
文件: nfs_test.py 项目: zerkella/eden
    def run_varying_nfs(self, mock_path_read_text):
        instance = FakeEdenInstance(self.make_temporary_directory())
        v = SimpleNamespace(mount_dir="mount_dir",
                            shared_path="shared_path",
                            instance=instance)
        mock_path_read_text.return_value = v.shared_path
        v.client_path = str(instance.create_test_mount(v.mount_dir).path)

        dry_run = True
        out = TestOutput()
        v.exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            out=out,
        )
        v.stdout = out.getvalue()
        return v
示例#16
0
    def run_varying_nfs(self, mock_path_read_text) -> NfsDoctorResult:
        instance = FakeEdenInstance(self.make_temporary_directory())
        shared_path = "shared_path"
        mount_dir = "mount_dir"
        mock_path_read_text.return_value = shared_path
        client_path = str(instance.create_test_mount(mount_dir).path)

        dry_run = True
        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            typing.cast(EdenInstance, instance),
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )
        return NfsDoctorResult(
            mount_dir, shared_path, client_path, instance, exit_code, out.getvalue()
        )
示例#17
0
    def test_not_all_mounts_have_watchman_watcher(self,
                                                  mock_get_roots_for_nuclide,
                                                  mock_watchman) -> None:
        instance = FakeEdenInstance(self.make_temporary_directory())
        edenfs_path = str(
            instance.create_test_mount("eden-mount", scm_type="git").path)
        edenfs_path_not_watched = str(
            instance.create_test_mount("eden-mount-not-watched",
                                       scm_type="git").path)
        side_effects: List[Dict[str, Any]] = []
        calls = []

        calls.append(call(["watch-list"]))
        side_effects.append({"roots": [edenfs_path]})
        calls.append(call(["watch-project", edenfs_path]))
        side_effects.append({"watcher": "eden"})
        mock_watchman.side_effect = side_effects

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            # pyre-fixme[6]: For 1st param expected `EdenInstance` but got
            #  `FakeEdenInstance`.
            instance,
            dry_run,
            mount_table=instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            f"Checking {edenfs_path}\n"
            f"Checking {edenfs_path_not_watched}\n"
            "<green>No issues detected.<reset>\n",
            out.getvalue(),
        )
        mock_watchman.assert_has_calls(calls)
        self.assertEqual(0, exit_code)
示例#18
0
    def test_loaded_content(self, mock_debugInodeStatus, mock_getSHA1) -> None:
        instance = FakeEdenInstance(self.make_temporary_directory())
        checkout = instance.create_test_mount("path1")

        with open(checkout.path / "a", "wb") as f:
            f.write(b"foobar")

        mock_getSHA1.return_value = [SHA1Result(b"\x01\x02\x03\x04")]

        mock_debugInodeStatus.return_value = [
            TreeInodeDebugInfo(
                1,
                b"",
                True,
                b"abcd",
                [
                    TreeInodeEntryDebugInfo(b"a", 2, stat.S_IFREG, True, False,
                                            b"1234")
                ],
            )
        ]

        def fake_PrjGetOnDiskFileState(path: Path) -> PRJ_FILE_STATE:
            if path == checkout.path / "a":
                return PRJ_FILE_STATE.HydratedPlaceholder
            else:
                return PRJ_FILE_STATE.Placeholder

        tracker = ProblemCollector()
        check_loaded_content(
            tracker,
            typing.cast(EdenInstance, instance),
            checkout,
            fake_PrjGetOnDiskFileState,
        )

        self.assertEqual(
            tracker.problems[0].description(),
            "The on-disk file at a is out of sync from EdenFS. Expected SHA1: 01020304, on-disk SHA1: 8843d7f92416211de9ebb963ff4ce28125932878",
        )
示例#19
0
    def _test_remount_checkouts(
        self,
        mock_get_roots_for_nuclide,
        mock_watchman,
        dry_run: bool,
        old_edenfs: bool = False,
    ) -> Tuple[int, str, List[Path]]:
        """Test that `eden doctor` remounts configured mount points that are not
        currently mounted.
        """
        tmp_dir = self.make_temporary_directory()
        instance = FakeEdenInstance(tmp_dir)

        mounts = []
        mount1 = instance.create_test_mount("path1")
        mounts.append(mount1.path)
        mounts.append(instance.create_test_mount("path2", active=False).path)
        if old_edenfs:
            # Mimic older versions of edenfs, and do not return mount state data.
            instance.get_thrift_client_legacy().change_mount_state(
                mount1.path, None)

        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            typing.cast(EdenInstance, instance),
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )
        return exit_code, out.getvalue(), mounts
示例#20
0
    def _check_disk_usage(
            self,
            instance: Optional[FakeEdenInstance] = None) -> List[ProblemBase]:
        problem_collector = ProblemCollector()
        if instance is None:
            instance = FakeEdenInstance(self.make_temporary_directory())

        doctor.check_filesystems.check_disk_usage(
            tracker=problem_collector,
            mount_paths=["/"],
            instance=typing.cast(EdenInstance, instance),
            fs_util=self.fs_util,
        )
        return problem_collector.problems
示例#21
0
    def test_pwd_out_of_date(self) -> None:
        tmp_dir = self.make_temporary_directory()
        instance = FakeEdenInstance(tmp_dir)
        mount = instance.create_test_mount("path1").path

        exit_code, out = self._test_with_pwd(instance, pwd=tmp_dir)
        self.assertEqual(
            out,
            f"""\
<yellow>- Found problem:<reset>
Your current working directory is out-of-date.
This can happen if you have (re)started Eden but your shell is still pointing to
the old directory from before the Eden checkouts were mounted.

Run "cd / && cd -" to update your shell's working directory.

Checking {mount}
<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
        )
        self.assertEqual(1, exit_code)
示例#22
0
    def test_watchman_fails(self, mock_watchman):
        tmp_dir = self.make_temporary_directory()
        instance = FakeEdenInstance(tmp_dir)

        mount = instance.create_test_mount("path1", active=False).path

        # Make calls to watchman fail rather than returning expected output
        side_effects = [{"error": "watchman failed"}]
        mock_watchman.side_effect = side_effects

        out = TestOutput()
        exit_code = doctor.cure_what_ails_you(
            typing.cast(EdenInstance, instance),
            dry_run=False,
            mount_table=instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        # "watchman watch-list" should have been called by the doctor code
        calls = [call(["watch-list"])]
        mock_watchman.assert_has_calls(calls)

        self.assertEqual(
            out.getvalue(),
            f"""\
Checking {mount}
<yellow>- Found problem:<reset>
{mount} is not currently mounted
Remounting {mount}...<green>fixed<reset>

<yellow>Successfully fixed 1 problem.<reset>
""",
        )
        self.assertEqual(exit_code, 0)
示例#23
0
    def test_eden_not_in_use(self, mock_get_roots_for_nuclide, mock_watchman):
        instance = FakeEdenInstance(self.make_temporary_directory(),
                                    status=fb303_status.DEAD)

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            FakeMountTable(),
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            out=out,
        )

        self.assertEqual("EdenFS is not in use.\n", out.getvalue())
        self.assertEqual(0, exit_code)
示例#24
0
    def _test_edenfs_version(
            self, mock_rpm_q,
            rpm_value: str) -> Tuple[doctor.ProblemFixer, str]:
        side_effects: List[str] = []
        calls = []
        calls.append(call())
        side_effects.append(rpm_value)
        mock_rpm_q.side_effect = side_effects

        instance = FakeEdenInstance(
            self.make_temporary_directory(),
            build_info={
                "build_package_version": "20171213",
                "build_package_release": "165642",
            },
        )
        fixer, out = self.create_fixer(dry_run=False)
        doctor.check_edenfs_version(fixer, typing.cast(EdenInstance, instance))
        mock_rpm_q.assert_has_calls(calls)
        return fixer, out.getvalue()
示例#25
0
    def test_eden_not_in_use(self, mock_get_roots_for_nuclide,
                             mock_watchman) -> None:
        instance = FakeEdenInstance(self.make_temporary_directory(),
                                    status=fb303_status.DEAD)

        out = TestOutput()
        dry_run = False
        exit_code = doctor.cure_what_ails_you(
            # pyre-fixme[6]: For 1st param expected `EdenInstance` but got
            #  `FakeEdenInstance`.
            instance,
            dry_run,
            FakeMountTable(),
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual("EdenFS is not in use.\n", out.getvalue())
        self.assertEqual(0, exit_code)
示例#26
0
 def setUp(self) -> None:
     instance = FakeEdenInstance(self.make_temporary_directory())
     self.checkout = instance.create_test_mount("path", )
示例#27
0
    def test_end_to_end_test_with_various_scenarios(self,
                                                    mock_get_roots_for_nuclide,
                                                    mock_watchman):
        side_effects: List[Dict[str, Any]] = []
        calls = []
        instance = FakeEdenInstance(self.make_temporary_directory())

        # In edenfs_path1, we will break the snapshot check.
        edenfs_path1_snapshot = "abcd" * 10
        edenfs_path1_dirstate_parent = "12345678" * 5
        edenfs_path1 = str(
            instance.create_test_mount(
                "path1",
                snapshot=edenfs_path1_snapshot,
                dirstate_parent=edenfs_path1_dirstate_parent,
            ).path)

        # In edenfs_path2, we will break the inotify check and the Nuclide
        # subscriptions check.
        edenfs_path2 = str(
            instance.create_test_mount("path2",
                                       scm_type="git",
                                       setup_path=False).path)

        # In edenfs_path3, we do not create the .hg directory
        edenfs_path3 = str(
            instance.create_test_mount("path3", setup_path=False).path)
        os.makedirs(edenfs_path3)

        # Assume all paths are used as root folders in a connected Nuclide.
        mock_get_roots_for_nuclide.return_value = {
            edenfs_path1,
            edenfs_path2,
            edenfs_path3,
        }

        calls.append(call(["watch-list"]))
        side_effects.append(
            {"roots": [edenfs_path1, edenfs_path2, edenfs_path3]})

        calls.append(call(["watch-project", edenfs_path1]))
        side_effects.append({"watcher": "eden"})

        calls.append(call(["debug-get-subscriptions", edenfs_path1]))
        side_effects.append(
            _create_watchman_subscription(
                filewatcher_subscriptions=[f"filewatcher-{edenfs_path1}"]))

        calls.append(call(["watch-project", edenfs_path2]))
        side_effects.append({"watcher": "inotify"})
        calls.append(call(["watch-del", edenfs_path2]))
        side_effects.append({"watch-del": True, "root": edenfs_path2})
        calls.append(call(["watch-project", edenfs_path2]))
        side_effects.append({"watcher": "eden"})

        calls.append(call(["debug-get-subscriptions", edenfs_path2]))
        side_effects.append(
            _create_watchman_subscription(filewatcher_subscriptions=[]))

        calls.append(call(["watch-project", edenfs_path3]))
        side_effects.append({"watcher": "eden"})
        calls.append(call(["debug-get-subscriptions", edenfs_path3]))
        side_effects.append(
            _create_watchman_subscription(
                filewatcher_subscriptions=[f"filewatcher-{edenfs_path3}"]))

        mock_watchman.side_effect = side_effects

        out = TestOutput()
        dry_run = False

        exit_code = doctor.cure_what_ails_you(
            instance,
            dry_run,
            instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            kerberos_checker=FakeKerberosChecker(),
            out=out,
        )

        self.assertEqual(
            f"""\
Checking {edenfs_path1}
<yellow>- Found problem:<reset>
Found inconsistent/missing data in {edenfs_path1}/.hg:
  mercurial's parent commit is {edenfs_path1_dirstate_parent}, \
but Eden's internal parent commit is {edenfs_path1_snapshot}
Repairing hg directory contents for {edenfs_path1}...<green>fixed<reset>

Checking {edenfs_path2}
<yellow>- Found problem:<reset>
Watchman is watching {edenfs_path2} with the wrong watcher type: \
"inotify" instead of "eden"
Fixing watchman watch for {edenfs_path2}...<green>fixed<reset>

<yellow>- Found problem:<reset>
Nuclide appears to be used to edit the following directories
under {edenfs_path2}:

  {edenfs_path2}

but the following Watchman subscriptions appear to be missing:

  filewatcher-{edenfs_path2}

This can cause file changes to fail to show up in Nuclide.
Currently, the only workaround for this is to run
"Nuclide Remote Projects: Kill And Restart" from the
command palette in Atom.

Checking {edenfs_path3}
<yellow>- Found problem:<reset>
Missing hg directory: {edenfs_path3}/.hg
Repairing hg directory contents for {edenfs_path3}...<green>fixed<reset>

<yellow>Successfully fixed 3 problems.<reset>
<yellow>1 issue requires manual attention.<reset>
Ask in the Eden Users group if you need help fixing issues with Eden:
https://fb.facebook.com/groups/eden.users/
""",
            out.getvalue(),
        )
        mock_watchman.assert_has_calls(calls)
        self.assertEqual(1, exit_code)
示例#28
0
class CorruptHgTest(DoctorTestBase):
    maxDiff = None

    def setUp(self) -> None:
        self.instance = FakeEdenInstance(self.make_temporary_directory())
        self.checkout = self.instance.create_test_mount("test_mount",
                                                        scm_type="hg")
        self.backing_repo = typing.cast(
            FakeEdenInstance, self.checkout.instance).default_backing_repo

    def test_unreadable_hg_shared_path_is_a_problem(self) -> None:
        sharedpath_path = self.checkout.path / ".hg" / "sharedpath"
        sharedpath_path.unlink()
        sharedpath_path.symlink_to(sharedpath_path.name)

        out = self.cure_what_ails_you(dry_run=True)
        self.assertIn(
            "Failed to read .hg/sharedpath: "
            "[Errno 40] Too many levels of symbolic links",
            out.getvalue(),
        )

    def test_truncated_hg_dirstate_is_a_problem(self) -> None:
        dirstate_path = self.checkout.path / ".hg" / "dirstate"
        os.truncate(dirstate_path, dirstate_path.stat().st_size - 1)

        out = self.cure_what_ails_you(dry_run=True)
        self.assertEqual(
            f"""\
Checking {self.checkout.path}
<yellow>- Found problem:<reset>
Found inconsistent/missing data in {self.checkout.path}/.hg:
  error parsing .hg/dirstate: Reached EOF while reading checksum \
hash in {self.checkout.path}/.hg/dirstate.

Would repair hg directory contents for {self.checkout.path}

<yellow>Discovered 1 problem during --dry-run<reset>
""",
            out.getvalue(),
        )

    def test_missing_sharedpath_and_requires(self) -> None:
        sharedpath_path = self.checkout.path / ".hg" / "sharedpath"
        sharedpath_path.unlink()
        requires_path = self.checkout.path / ".hg" / "requires"
        requires_path.unlink()

        out = self.cure_what_ails_you(dry_run=False)
        self.assertEqual(
            f"""\
Checking {self.checkout.path}
<yellow>- Found problem:<reset>
Found inconsistent/missing data in {self.checkout.path}/.hg:
  error reading .hg/requires: [Errno 2] No such file or directory: \
{str(requires_path)!r}
  error reading .hg/sharedpath: [Errno 2] No such file or directory: \
{str(sharedpath_path)!r}
Repairing hg directory contents for {self.checkout.path}...<green>fixed<reset>

<yellow>Successfully fixed 1 problem.<reset>
""",
            out.getvalue(),
        )
        self.assertIn("eden\n", requires_path.read_text())
        self.assertEqual(sharedpath_path.read_text(),
                         str(self.backing_repo / ".hg"))

    def test_missing_hg_dir(self) -> None:
        hg_dir = self.checkout.path / ".hg"
        shutil.rmtree(hg_dir)

        out = self.cure_what_ails_you(dry_run=False)
        self.assertEqual(
            f"""\
Checking {self.checkout.path}
<yellow>- Found problem:<reset>
Missing hg directory: {self.checkout.path}/.hg
Repairing hg directory contents for {self.checkout.path}...<green>fixed<reset>

<yellow>Successfully fixed 1 problem.<reset>
""",
            out.getvalue(),
        )
        self._verify_hg_dir()

    def test_empty_hg_dir(self) -> None:
        hg_dir = self.checkout.path / ".hg"
        shutil.rmtree(hg_dir)
        hg_dir.mkdir()

        out = self.cure_what_ails_you(dry_run=False)
        self.assertEqual(
            f"""\
Checking {self.checkout.path}
<yellow>- Found problem:<reset>
No contents present in hg directory: {self.checkout.path}/.hg
Repairing hg directory contents for {self.checkout.path}...<green>fixed<reset>

<yellow>Successfully fixed 1 problem.<reset>
""",
            out.getvalue(),
        )
        self._verify_hg_dir()

    def test_interrupted_transaction(self) -> None:
        store = self.backing_repo / ".hg" / "store"
        store.mkdir()
        journal = store / "journal"
        journal.write_text("")
        out = self.cure_what_ails_you(dry_run=False)
        self.assertEqual(
            f"""\
Checking {self.checkout.path}
<yellow>- Found problem:<reset>
Found inconsistent/missing data in {self.checkout.path}/.hg:
  Found a journal file in backing repo, might have an interrupted transaction
Repairing hg directory contents for {self.checkout.path}...<green>fixed<reset>

<yellow>Successfully fixed 1 problem.<reset>
""",
            out.getvalue(),
        )

    def _verify_hg_dir(self) -> None:
        hg_dir = self.checkout.path / ".hg"
        self.assertTrue((hg_dir / "dirstate").is_file())
        self.assertTrue((hg_dir / "hgrc").is_file())
        self.assertTrue((hg_dir / "requires").is_file())
        self.assertTrue((hg_dir / "sharedpath").is_file())
        self.assertTrue((hg_dir / "shared").is_file())
        self.assertTrue((hg_dir / "bookmarks").is_file())
        self.assertTrue((hg_dir / "branch").is_file())

        self.assert_dirstate_p0(self.checkout,
                                FakeEdenInstance.default_commit_hash)
        self.assertIn("[extensions]\neden =\n", (hg_dir / "hgrc").read_text())
        self.assertIn("eden\n", (hg_dir / "requires").read_text())
        self.assertEqual((hg_dir / "sharedpath").read_text(),
                         str(self.backing_repo / ".hg"))
        self.assertEqual((hg_dir / "shared").read_text(), "bookmarks\n")
        self.assertEqual((hg_dir / "bookmarks").read_text(), "")
        self.assertEqual((hg_dir / "branch").read_text(), "default\n")

    def cure_what_ails_you(self, dry_run: bool) -> TestOutput:
        out = TestOutput()
        doctor.cure_what_ails_you(
            typing.cast(EdenInstance, self.instance),
            dry_run,
            self.instance.mount_table,
            fs_util=FakeFsUtil(),
            proc_utils=self.make_proc_utils(),
            out=out,
        )
        return out
示例#29
0
 def setUp(self) -> None:
     self.instance = FakeEdenInstance(self.make_temporary_directory())
     self.checkout = self.instance.create_test_mount("test_mount",
                                                     scm_type="hg")
     self.backing_repo = typing.cast(
         FakeEdenInstance, self.checkout.instance).default_backing_repo