Пример #1
0
    def test_ensure_ownership_failed_chown(self):
        def stat_side_effect(name, limit, ver, path, buf):
            st = self.convert_stat_pointer(name, buf)
            if path == limit:
                st.st_uid = 2
                st.st_gid = 2
                return 0
            else:
                self.delegate_to_original(name)
                return -1

        with self.run_in_subprocess(
                "chown",
                "getpwnam",
                "__xstat",
                "__xstat64",
        ) as (enter, preloads):
            enter()
            preloads["chown"].return_value = -1
            preloads["getpwnam"].side_effect = (
                lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
            self._set_stat_side_effect(preloads, stat_side_effect,
                                       self.db.props.root)

            self._make_ownership_test()
            self.assertRaisesDatabaseError(
                Click.DatabaseError.ENSURE_OWNERSHIP, self.db.ensure_ownership)
Пример #2
0
    def test_ensure_ownership_quick_if_correct(self):
        def stat_side_effect(name, limit, ver, path, buf):
            st = self.convert_stat_pointer(name, buf)
            if path == limit:
                st.st_uid = 1
                st.st_gid = 1
                return 0
            else:
                self.delegate_to_original(name)
                return -1

        with self.run_in_subprocess(
                "chown",
                "getpwnam",
                "__xstat",
                "__xstat64",
        ) as (enter, preloads):
            enter()
            preloads["getpwnam"].side_effect = (
                lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
            self._set_stat_side_effect(preloads, stat_side_effect,
                                       self.db.props.root)

            self._make_ownership_test()
            self.db.ensure_ownership()
            self.assertFalse(preloads["chown"].called)
Пример #3
0
    def test_gc_fixes_old_user_registrations(self):
        with self.run_in_subprocess("getpwnam") as (enter, preloads):
            enter()

            # Setup the system hook
            preloads["getpwnam"].side_effect = (
                lambda name: self.make_pointer(Passwd(pw_dir=b"/foo")))

            # Setup both databases
            db1 = os.path.join(self.temp_dir, "db1")
            db2 = os.path.join(self.temp_dir, "db2")
            db = Click.DB()
            db.add(db1)
            db.add(db2)

            # Prepare common manifest for the packages
            manifest = {"hooks": {"test-app": {"test": "foo"}}}

            # Setup versions 1.0 and 3.0 of package in db1
            version1 = os.path.join(db1, "test-package", "1.0")
            with mkfile(
                    os.path.join(version1, ".click", "info",
                                 "test-package.manifest")) as f:
                json.dump(manifest, f)

            version3 = os.path.join(db1, "test-package", "3.0")
            with mkfile(
                    os.path.join(version3, ".click", "info",
                                 "test-package.manifest")) as f:
                json.dump(manifest, f)

            # Setup version 0.2 of package in db2
            version2 = os.path.join(db2, "test-package", "2.0")
            with mkfile(
                    os.path.join(version2, ".click", "info",
                                 "test-package.manifest")) as f:
                json.dump(manifest, f)

            # Setup the user registration for 2.0 in db2.
            registrationPath = os.path.join(db2, ".click", "users", "foo",
                                            "test-package")
            os.makedirs(os.path.dirname(registrationPath))
            os.symlink(version2, registrationPath)

            # Run the garbage collection to update the registrations.
            db.gc()

            # Verify that the user still has a registration for the package,
            # and that it's now registered for version 3.0.
            self.assertTrue(os.path.lexists(registrationPath))
            self.assertEqual(version3, os.readlink(registrationPath))

            user_db = Click.User.for_user(db, "foo")
            try:
                version = user_db.get_version("test-package")
                self.assertEqual("3.0", version)
            except:
                self.fail("No user registration for 'test-package'")
Пример #4
0
 def test_gc_ignores_non_directory(self):
     with self.run_in_subprocess("getpwnam") as (enter, preloads):
         enter()
         preloads["getpwnam"].side_effect = (
             lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
         a_path = os.path.join(self.temp_dir, "a", "1.0")
         a_manifest_path = os.path.join(a_path, ".click", "info",
                                        "a.manifest")
         with mkfile(a_manifest_path) as manifest:
             json.dump({"hooks": {"a-app": {}}}, manifest)
         a_user_path = os.path.join(self.temp_dir, ".click", "users",
                                    "test-user", "a")
         os.makedirs(os.path.dirname(a_user_path))
         os.symlink(a_path, a_user_path)
         touch(os.path.join(self.temp_dir, "file"))
         self.db.gc()
         self.assertTrue(os.path.exists(a_path))
Пример #5
0
    def test_ensure_ownership(self):
        def stat_side_effect(name, limit, ver, path, buf):
            st = self.convert_stat_pointer(name, buf)
            if path == limit:
                st.st_uid = 2
                st.st_gid = 2
                return 0
            else:
                self.delegate_to_original(name)
                return -1

        with self.run_in_subprocess(
                "chown",
                "getpwnam",
                "__xstat",
                "__xstat64",
        ) as (enter, preloads):
            enter()
            preloads["getpwnam"].side_effect = (
                lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
            self._set_stat_side_effect(preloads, stat_side_effect,
                                       self.db.props.root)

            self._make_ownership_test()
            self.db.ensure_ownership()
            expected_paths = [
                self.temp_dir,
                os.path.join(self.temp_dir, ".click"),
                os.path.join(self.temp_dir, ".click", "log"),
                os.path.join(self.temp_dir, ".click", "users"),
                os.path.join(self.temp_dir, "a"),
                os.path.join(self.temp_dir, "a", "1.0"),
                os.path.join(self.temp_dir, "a", "1.0", ".click"),
                os.path.join(self.temp_dir, "a", "1.0", ".click", "info"),
                os.path.join(self.temp_dir, "a", "1.0", ".click", "info",
                             "a.manifest"),
                os.path.join(self.temp_dir, "a", "current"),
            ]
            self.assertCountEqual(
                [path.encode() for path in expected_paths],
                [args[0][0] for args in preloads["chown"].call_args_list])
            self.assertCountEqual(
                [(1, 1)],
                set(args[0][1:] for args in preloads["chown"].call_args_list))
Пример #6
0
    def test_ensure_db_ownership(self):
        # getpwnam results are cached properly, in a way that doesn't fail
        # due to confusion with getpwnam returning a pointer to a static
        # buffer.
        with self.run_in_subprocess("chown", "geteuid",
                                    "getpwnam") as (enter, preloads):
            enter()
            preloads["geteuid"].return_value = 0
            getpwnam_result = Passwd()

            def getpwnam_side_effect(name):
                if name == b"clickpkg":
                    getpwnam_result.pw_uid = 1
                    getpwnam_result.pw_gid = 1
                else:
                    getpwnam_result.pw_uid = 2
                    getpwnam_result.pw_gid = 2
                return self.make_pointer(getpwnam_result)

            preloads["getpwnam"].side_effect = getpwnam_side_effect
            registry = Click.User.for_user(self.db, "user")
            os.makedirs(os.path.join(self.temp_dir, "a", "1.0"))
            click_dir = os.path.join(self.temp_dir, ".click")

            registry.set_version("a", "1.0")
            self.assertEqual(3, preloads["chown"].call_count)
            preloads["chown"].assert_any_call(click_dir.encode(), 1, 1)
            preloads["chown"].assert_any_call(
                os.path.join(click_dir, "users").encode(), 1, 1)
            preloads["chown"].assert_any_call(
                os.path.join(click_dir, "users", "user").encode(), 2, 2)

            # Try again, now that both password file entries should be
            # cached.
            shutil.rmtree(os.path.join(self.temp_dir, ".click"))
            preloads["chown"].reset_mock()
            registry.set_version("a", "1.0")
            self.assertEqual(3, preloads["chown"].call_count)
            preloads["chown"].assert_any_call(click_dir.encode(), 1, 1)
            preloads["chown"].assert_any_call(
                os.path.join(click_dir, "users").encode(), 1, 1)
            preloads["chown"].assert_any_call(
                os.path.join(click_dir, "users", "user").encode(), 2, 2)
Пример #7
0
    def test_ensure_db_chown_fails(self):
        with self.run_in_subprocess("chown", "geteuid",
                                    "getpwnam") as (enter, preloads):
            enter()
            preloads["geteuid"].return_value = 0
            getpwnam_result = Passwd()

            def getpwnam_side_effect(name):
                if name == b"clickpkg":
                    getpwnam_result.pw_uid = 1
                    getpwnam_result.pw_gid = 1
                else:
                    getpwnam_result.pw_uid = 2
                    getpwnam_result.pw_gid = 2
                return self.make_pointer(getpwnam_result)

            preloads["getpwnam"].side_effect = getpwnam_side_effect
            preloads["chown"].return_value = -1
            registry = Click.User.for_user(self.db, "user")
            self.assertRaisesUserError(Click.UserError.CHOWN_DB,
                                       registry.set_version, "a", "1.0")
Пример #8
0
 def test_gc(self):
     with self.run_in_subprocess("click_find_on_path", "g_spawn_sync",
                                 "getpwnam") as (enter, preloads):
         enter()
         preloads["getpwnam"].side_effect = (
             lambda name: self.make_pointer(Passwd(pw_uid=1, pw_gid=1)))
         os.environ["TEST_QUIET"] = "1"
         a_path = os.path.join(self.temp_dir, "a", "1.0")
         a_manifest_path = os.path.join(a_path, ".click", "info",
                                        "a.manifest")
         with mkfile(a_manifest_path) as manifest:
             json.dump({"hooks": {"a-app": {}}}, manifest)
         b_path = os.path.join(self.temp_dir, "b", "1.0")
         b_manifest_path = os.path.join(b_path, ".click", "info",
                                        "b.manifest")
         with mkfile(b_manifest_path) as manifest:
             json.dump({"hooks": {"b-app": {}}}, manifest)
         c_path = os.path.join(self.temp_dir, "c", "1.0")
         c_manifest_path = os.path.join(c_path, ".click", "info",
                                        "c.manifest")
         with mkfile(c_manifest_path) as manifest:
             json.dump({"hooks": {"c-app": {}}}, manifest)
         a_user_path = os.path.join(self.temp_dir, ".click", "users",
                                    "test-user", "a")
         os.makedirs(os.path.dirname(a_user_path))
         os.symlink(a_path, a_user_path)
         b_gcinuse_path = os.path.join(self.temp_dir, ".click", "users",
                                       "@gcinuse", "b")
         os.makedirs(os.path.dirname(b_gcinuse_path))
         os.symlink(b_path, b_gcinuse_path)
         preloads["g_spawn_sync"].side_effect = partial(
             self.g_spawn_sync_side_effect, {b"ubuntu-app-pid": 1 << 8})
         preloads["click_find_on_path"].return_value = True
         self.db.gc()
         self.assertTrue(os.path.exists(a_path))
         self.assertFalse(os.path.exists(b_gcinuse_path))
         self.assertFalse(os.path.exists(b_path))
         self.assertFalse(os.path.exists(c_path))