mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 00:45:18 +03:00
c55781c666
Summary: Move the `UserInfo` code from `fuse/privhelper` to `utils`, and also unify the POSIX and Windows implementations of this class. This code was originally put in the `fuse/privhelper` directory since it was written at the same time as the privhelper. However, it's really a lower-level library that doesn't depend on FUSE or any of the other code in the `fuse/` subdirectory. Reviewed By: wez Differential Revision: D21296594 fbshipit-source-id: f58682f6ce86bba0328472c491bb4c0dc3370319
139 lines
4.3 KiB
C++
139 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This software may be used and distributed according to the terms of the
|
|
* GNU General Public License version 2.
|
|
*/
|
|
|
|
#include "eden/fs/utils/UserInfo.h"
|
|
|
|
#include <folly/portability/Stdlib.h>
|
|
#include <folly/test/TestUtils.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "eden/fs/utils/test/ScopedEnvVar.h"
|
|
|
|
namespace facebook {
|
|
namespace eden {
|
|
|
|
#ifndef _WIN32
|
|
TEST(UserInfo, initFromSudo) {
|
|
ScopedEnvVar homeVar{"HOME"};
|
|
ScopedEnvVar sudoUidVar{"SUDO_UID"};
|
|
ScopedEnvVar sudoGidVar{"SUDO_GID"};
|
|
ScopedEnvVar sudoUserVar{"SUDO_USER"};
|
|
|
|
sudoUidVar.unset();
|
|
sudoGidVar.unset();
|
|
sudoUserVar.unset();
|
|
|
|
// initFromSudo() should return false when no SUDO_* variables are defined.
|
|
UserInfo info;
|
|
EXPECT_FALSE(info.initFromSudo());
|
|
|
|
// If SUDO_GID is defined without SUDO_GID or SUDO_USER,
|
|
// initFromSudo should throw
|
|
sudoUidVar.set("65534");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(), std::runtime_error, "SUDO_UID set without SUDO_GID");
|
|
sudoGidVar.set("65534");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"SUDO_UID set without SUDO_USER");
|
|
|
|
// If SUDO_UID or SUDO_GID is bogus, initFromSudo should throw
|
|
sudoUidVar.set("");
|
|
sudoGidVar.set("65534");
|
|
sudoUserVar.set("some_test_user");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(), std::runtime_error, "invalid value for SUDO_UID: ");
|
|
sudoUidVar.set("asdf");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_UID: asdf");
|
|
sudoUidVar.set("-12");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_UID: -12");
|
|
sudoUidVar.set("9999999999999999999");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_UID: 9999999999999999999");
|
|
|
|
sudoUidVar.set("65534");
|
|
sudoGidVar.set("");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(), std::runtime_error, "invalid value for SUDO_GID: ");
|
|
sudoGidVar.set("hello world");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_GID: hello world");
|
|
sudoGidVar.set("-3");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_GID: -3");
|
|
sudoGidVar.set("19999999999999999999");
|
|
EXPECT_THROW_RE(
|
|
info.initFromSudo(),
|
|
std::runtime_error,
|
|
"invalid value for SUDO_GID: 19999999999999999999");
|
|
|
|
// Finally, test a success case
|
|
sudoUidVar.set("65534");
|
|
sudoGidVar.set("65535");
|
|
sudoUserVar.set("eden_test_user");
|
|
setenv("HOME", "/some/path/../to/..//a/home/dir", 1);
|
|
EXPECT_TRUE(info.initFromSudo());
|
|
EXPECT_EQ(65534, info.getUid());
|
|
EXPECT_EQ(65535, info.getGid());
|
|
EXPECT_EQ("eden_test_user", info.getUsername());
|
|
EXPECT_EQ("/some/a/home/dir", info.getHomeDirectory().stringPiece());
|
|
}
|
|
|
|
TEST(UserInfo, lookup) {
|
|
// Call UserInfo::lookup() and try to confirm if it is doing the right thing.
|
|
auto uid = getuid();
|
|
|
|
// It's possible that this could throw if the test is being run by a UID that
|
|
// doesn't actually exist in the passwd database. Throwing in this case is
|
|
// the correct behavior for the code, so we shouldn't really treat that as a
|
|
// test failure if our current UID legitimately doesn't exist. However, we
|
|
// don't really expect the tests to be run with an unknown UID, so we don't
|
|
// try to handle this situation for now.
|
|
auto info = UserInfo::lookup();
|
|
|
|
if (uid != 0) {
|
|
// We don't bother doing much in the way of output validation in this case.
|
|
// The initFromSudo() test above tests most of the sudo-handling logic.
|
|
} else {
|
|
EXPECT_EQ(uid, info.getUid());
|
|
EXPECT_EQ(getgid(), info.getGid());
|
|
// We don't bother testing the return value of getUsername() or
|
|
// getHomeDirectory(), since we can't easily validate them other than just
|
|
// repeating the same logic that UserInfo does.
|
|
// For now this test makes sure we exercise the code path to look them up,
|
|
// but we can't confirm their correctness.
|
|
}
|
|
}
|
|
#else
|
|
|
|
TEST(UserInfoTest, testUserName) {
|
|
auto user = UserInfo::lookup();
|
|
EXPECT_EQ(getenv("USERNAME"), user.getUsername());
|
|
}
|
|
|
|
TEST(UserInfoTest, testHomeDirectory) {
|
|
auto user = UserInfo::lookup();
|
|
EXPECT_EQ(realpath(getenv("USERPROFILE")), user.getHomeDirectory());
|
|
}
|
|
#endif
|
|
|
|
} // namespace eden
|
|
} // namespace facebook
|