Merge pull request #1352 from PowerShell/andschwa/username

Implement Get-Process -IncludeUserName for Linux
This commit is contained in:
Andy Schwartzmeyer
2016-07-13 17:27:11 -07:00
committed by GitHub
23 changed files with 491 additions and 215 deletions
+3 -3
View File
@@ -201,9 +201,9 @@ function Start-PSBuild {
try {
Push-Location $Native
cmake -DCMAKE_BUILD_TYPE=Debug .
make -j
make test
Start-NativeExecution { cmake -DCMAKE_BUILD_TYPE=Debug . }
Start-NativeExecution { make -j }
Start-NativeExecution { ctest --verbose }
} finally {
Pop-Location
}
@@ -866,6 +866,9 @@ namespace Microsoft.PowerShell.Commands
private static string RetrieveProcessUserName(Process process, Cmdlet cmdlet)
{
string userName = null;
#if LINUX
userName = Platform.NonWindowsGetUserFromPid(process.Id);
#else
IntPtr tokenUserInfo = IntPtr.Zero;
IntPtr processTokenHandler = IntPtr.Zero;
@@ -955,6 +958,7 @@ namespace Microsoft.PowerShell.Commands
}
}
#endif
return userName;
}
@@ -354,6 +354,18 @@ namespace System.Management.Automation
}
}
internal static string NonWindowsGetUserFromPid(int path)
{
if (!IsWindows)
{
return LinuxPlatform.GetUserFromPid(path);
}
else
{
throw new PlatformNotSupportedException();
}
}
#if CORECLR
internal static string NonWindowsGetFolderPath(SpecialFolder folder)
{
@@ -740,6 +752,11 @@ namespace System.Management.Automation
return Native.FollowSymLink(path);
}
public static string GetUserFromPid(int pid)
{
return Native.GetUserFromPid(pid);
}
[StructLayout(LayoutKind.Sequential)]
internal class SetDateInfoInternal
{
@@ -809,6 +826,9 @@ namespace System.Management.Automation
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string FollowSymLink([MarshalAs(UnmanagedType.LPStr)]string filePath);
[DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string GetUserFromPid(int pid);
}
}
@@ -960,21 +960,20 @@ namespace System.Management.Automation
internal static bool IsAdministrator()
{
// Porting note: only Windows supports the
// SecurityPrincipal API of .net for now assume Linux
// users have no concept of "Administrator" for now and
// specifically do not map to a check for root user
if (Platform.IsWindows)
{
System.Security.Principal.WindowsIdentity currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(currentIdentity);
// Porting note: only Windows supports the SecurityPrincipal API of .NET. Due to
// advanced privilege models, the correct approach on Unix is to assume the user has
// permissions, attempt the task, and error gracefully if the task fails due to
// permissions. To fit into PowerShell's existing model of pre-emptively checking
// permissions (which cannot be assumed on Unix), we "assume" the user is an
// administrator by returning true, thus nullifying this check on Unix.
#if LINUX
return true;
#else
System.Security.Principal.WindowsIdentity currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(currentIdentity);
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
}
else
{
return false;
}
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
#endif
}
internal static bool NativeItemExists(string path)
+4
View File
@@ -1,4 +1,8 @@
add_library(psl-native SHARED
getstat.cpp
getpwuid.cpp
getuserfrompid.cpp
getfileowner.cpp
getcurrentprocessorid.cpp
getusername.cpp
getcomputername.cpp
+47 -103
View File
@@ -37,124 +37,68 @@
char* FollowSymLink(const char* fileName)
{
errno = 0;
errno = 0;
// if filename is null, return null value
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return NULL;
}
//if lstat in IsSymLink returns -1, path does not exist
if (IsSymLink(fileName) == -1)
// return null for non symlinks
if (!IsSymLink(fileName))
{
return NULL;
}
/*If the path is a symlink, the function return the absolute filepath if valid. if not valid, return null*/
if (IsSymLink(fileName))
// attempt to resolve with the absolute file path
char buffer[PATH_MAX];
char* realPath = realpath(fileName, buffer);
if (realPath)
{
//Attempt to resolve with the absolute filepath
char actualpath[PATH_MAX+1];
char* realPath = realpath(fileName, actualpath);
//if realPath is null, go onto the readlink implementation
if (realPath == NULL)
{
char buffer[PATH_MAX];
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
if (sz == -1)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS; /*If the path is a symlink, the function return the absolute filepath if valid. if not valid, return null*/
break;
case EINVAL:
errno = ERROR_INVALID_NAME;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_BAD_PATH_NAME;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return strndup(realPath, strlen(realPath) + 1);
}
return NULL;
}
buffer[sz] = '\0';
return strndup(buffer, sz + 1);
}
else
// if the path wasn't resolved, use readlink
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
if (sz == -1)
{
switch(errno)
{
return strndup(realPath, strlen(realPath) + 1 );
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case EINVAL:
errno = ERROR_INVALID_NAME;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_BAD_PATH_NAME;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return NULL;
}
else
{
char buffer[PATH_MAX];
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
if (sz == -1)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS; /*If the path is a symlink, the function return the absolute filepath if valid. if not valid, return null*/
break;
case EINVAL:
errno = ERROR_INVALID_NAME;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_BAD_PATH_NAME;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return NULL;
}
buffer[sz] = '\0';
return strndup(buffer, sz + 1);
}
buffer[sz] = '\0';
return strndup(buffer, sz + 1);
}
+50
View File
@@ -0,0 +1,50 @@
//! @file getfileowner.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief returns the owner of a file
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include "getstat.h"
#include "getpwuid.h"
#include "getfileowner.h"
//! @brief GetFileOwner returns the owner of a file
//!
//! GetFileOwner
//!
//! @param[in] fileName
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes this error via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//!
//! @retval file owner, or NULL if unsuccessful
//!
char* GetFileOwner(const char* fileName)
{
int32_t ret = 0;
errno = 0;
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return NULL;
}
struct stat buf;
ret = GetStat(fileName, &buf);
if (ret != 0)
{
return NULL;
}
return GetPwUid(buf.st_uid);
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char* GetFileOwner(const char* fileName);
PAL_END_EXTERNC
@@ -27,12 +27,12 @@ char *GetFullyQualifiedName()
char *computerName = GetComputerName();
if (computerName == NULL)
{
return NULL;
return NULL;
}
if (strchr(computerName, '.') != NULL)
{
return computerName;
return computerName;
}
struct addrinfo hints, *info;
@@ -51,7 +51,7 @@ char *GetFullyQualifiedName()
if (getaddrinfo(computerName, "http", &hints, &info) != 0)
{
errno = ERROR_BAD_NET_NAME;
return NULL;
return NULL;
}
// info is actually a link-list. We'll just return the first full name
+81
View File
@@ -0,0 +1,81 @@
//! @file getpwuid.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief returns the username for a uid
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include "getpwuid.h"
//! @brief GetPwUid returns the username for a uid
//!
//! GetPwUid
//!
//! @param[in] uid
//! @parblock
//! The user identifier to lookup.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_NO_SUCH_USER: user lookup unsuccessful
//! - ERROR_OUTOFMEMORY insufficient kernel memory
//! - ERROR_GEN_FAILURE: anything else
//!
//! @retval username as UTF-8 string, or NULL if unsuccessful
//!
char* GetPwUid(uid_t uid)
{
int32_t ret = 0;
struct passwd pwd;
struct passwd* result = NULL;
char* buf;
int buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
if (buflen < 1)
{
buflen = 2048;
}
allocate:
buf = (char*)calloc(buflen, sizeof(char));
ret = getpwuid_r(uid, &pwd, buf, buflen, &result);
if (ret != 0)
{
switch(errno)
{
case ERANGE:
free(buf);
buflen *= 2;
goto allocate;
case ENOENT:
case ESRCH:
case EBADF:
case EPERM:
errno = ERROR_NO_SUCH_USER;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
default:
errno = ERROR_GEN_FAILURE;
}
return NULL;
}
// no result
if (result == NULL)
{
return NULL;
}
// allocate copy on heap so CLR can free it
size_t userlen = strnlen(pwd.pw_name, buflen);
char* username = strndup(pwd.pw_name, userlen);
free(buf);
return username;
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <sys/types.h>
#include "pal.h"
PAL_BEGIN_EXTERNC
char* GetPwUid(uid_t uid);
PAL_END_EXTERNC
+96
View File
@@ -0,0 +1,96 @@
//! @file getstat.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief returns the stat of a file
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include "getstat.h"
//! @brief GetStat returns the stat of a file. This simply delegates to the
//! stat() system call and maps errno to the expected values for GetLastError.
//!
//! GetStat
//!
//! @param[in] path
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @param[in] stat
//! @parblock
//! A pointer to the buffer in which to place the stat information
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_STOPPED_ON_SYMLINK: too many symbolic links
//! - ERROR_GEN_FAILURE: I/O error occurred
//! - ERROR_INVALID_NAME: file provided is not a symbolic link
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long
//! - ERROR_OUTOFMEMORY insufficient kernel memory
//!
//! @retval 0 if successful
//! @retval -1 if failed
//!
int32_t GetStat(const char* path, struct stat* buf)
{
errno = 0;
if (!path)
{
errno = ERROR_INVALID_PARAMETER;
return -1;
}
int32_t ret = stat(path, buf);
if (ret != 0)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EBADF:
errno = ERROR_FILE_NOT_FOUND;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_GEN_FAILURE;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_NO_SUCH_USER;
break;
case ENOTDIR:
errno = ERROR_INVALID_NAME;
break;
case EOVERFLOW:
errno = ERROR_BUFFER_OVERFLOW;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return -1;
}
return 0;
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <sys/stat.h>
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t GetStat(const char* path, struct stat* buf);
PAL_END_EXTERNC
+47
View File
@@ -0,0 +1,47 @@
#include <string>
#include <sstream>
#include <errno.h>
#include <sys/sysctl.h>
#include "pal.h"
#include "getfileowner.h"
#include "getpwuid.h"
#include "getuserfrompid.h"
char* GetUserFromPid(pid_t pid)
{
#if defined(__linux__)
// Get effective owner of pid from procfs
std::stringstream ss;
ss << "/proc/" << pid;
std::string path;
ss >> path;
return GetFileOwner(path.c_str());
#elif defined(__APPLE__) && defined(__MACH__)
// Get effective owner of pid from sysctl
struct kinfo_proc oldp;
size_t oldlenp = sizeof(oldp);
int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
u_int namelen = sizeof(name)/sizeof(int);
// Read-only query
int ret = sysctl(name, namelen, &oldp, &oldlenp, NULL, 0);
if (ret != 0 || oldlenp == 0)
{
errno = ERROR_GEN_FAILURE;
return NULL;
}
return GetPwUid(oldp.kp_eproc.e_ucred.cr_uid);
#else
return NULL;
#endif
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char* GetUserFromPid(pid_t pid);
PAL_END_EXTERNC
+2 -50
View File
@@ -2,64 +2,16 @@
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Implements GetUserName for Linux
#include <errno.h>
#include <locale.h>
#include <unistd.h>
#include <string>
#include <pwd.h>
#include "getpwuid.h"
#include "getusername.h"
//! @brief GetUserName retrieves the name of the user associated with
//! the current thread.
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_NO_SUCH_USER: there was no corresponding user
//! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons
//!
//! @retval username as UTF-8 string, or null if unsuccessful
char* GetUserName()
{
errno = 0;
struct passwd pwd;
struct passwd* result;
// gets the initial suggested size for buf
int buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
if (buflen == -1)
{
errno = ERROR_GEN_FAILURE;
return NULL;
}
std::string buf(buflen, 0);
// geteuid() gets the effective user ID of the calling process, and is always successful
int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result);
// Map errno to Win32 Error Codes
if (ret)
{
switch (errno)
{
case ENOENT:
case ESRCH:
case EBADF:
case EPERM:
errno = ERROR_NO_SUCH_USER;
break;
default:
errno = ERROR_GEN_FAILURE;
}
return NULL;
}
// Check if no user matched
if (result == NULL)
{
errno = ERROR_NO_SUCH_USER;
return NULL;
}
// allocate copy on heap so CLR can free it
return strdup(result->pw_name);
return GetPwUid(geteuid());
}
+2
View File
@@ -1,7 +1,9 @@
add_subdirectory(googletest)
add_executable(psl-native-test
test-getfileowner.cpp
test-locale.cpp
test-getuserfrompid.cpp
test-getcurrentprocessid.cpp
test-getusername.cpp
test-getcomputername.cpp
+20 -16
View File
@@ -32,19 +32,19 @@ protected:
// First create a temp file
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
file = fileTemplateBuf;
// Create a temp directory
dir = mkdtemp(dirTemplateBuf);
// Create a temp directory
dir = mkdtemp(dirTemplateBuf);
EXPECT_TRUE(dir != NULL);
// Create symbolic link to file
int ret1 = CreateSymLink(fileSymLink.c_str(), file);
EXPECT_EQ(ret1, 1);
int ret1 = CreateSymLink(fileSymLink.c_str(), file);
EXPECT_EQ(ret1, 1);
// Create symbolic link to directory
int ret2 = CreateSymLink(dirSymLink.c_str(), dir);
EXPECT_EQ(ret2, 1);
int ret2 = CreateSymLink(dirSymLink.c_str(), dir);
EXPECT_EQ(ret2, 1);
}
~CreateSymLinkTest()
@@ -52,16 +52,16 @@ protected:
int ret;
ret = unlink(fileSymLink.c_str());
EXPECT_EQ(0, ret);
EXPECT_EQ(0, ret);
ret = unlink(dirSymLink.c_str());
EXPECT_EQ(0, ret);
EXPECT_EQ(0, ret);
ret = unlink(file);
EXPECT_EQ(0, ret);
EXPECT_EQ(0, ret);
ret = rmdir(dir);
EXPECT_EQ(0, ret);
ret = rmdir(dir);
EXPECT_EQ(0, ret);
}
};
@@ -77,7 +77,7 @@ TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
std::string invalidFile = "/tmp/symlinktest_invalidFile";
std::string invalidLink = "/tmp/symlinktest_invalidLink";
// make sure neither exists
// make sure neither exists
unlink(invalidFile.c_str());
unlink(invalidLink.c_str());
@@ -97,7 +97,9 @@ TEST_F(CreateSymLinkTest, SymLinkToFile)
EXPECT_EQ(1, retVal);
std::string target = FollowSymLink(fileSymLink.c_str());
EXPECT_EQ(target, file);
char buffer[PATH_MAX];
std::string expected = realpath(file, buffer);
EXPECT_EQ(target, expected);
}
TEST_F(CreateSymLinkTest, SymLinkToDirectory)
@@ -106,7 +108,9 @@ TEST_F(CreateSymLinkTest, SymLinkToDirectory)
EXPECT_EQ(1, retVal);
std::string target = FollowSymLink(dirSymLink.c_str());
EXPECT_EQ(target, dir);
char buffer[PATH_MAX];
std::string expected = realpath(dir, buffer);
EXPECT_EQ(target, expected);
}
TEST_F(CreateSymLinkTest, SymLinkAgain)
@@ -0,0 +1,25 @@
//! @file test-getfileowner.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Tests GetFileOwner
#include <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include "getfileowner.h"
TEST(GetFileOwnerTest, CanGetOwnerOfRoot)
{
EXPECT_STREQ(GetFileOwner("/"), "root");
}
TEST(GetFileOwnerTest, CannotGetOwnerOfFakeFile)
{
EXPECT_STREQ(GetFileOwner("SomeMadeUpFileNameThatDoesNotExist"), NULL);
EXPECT_EQ(errno, ERROR_FILE_NOT_FOUND);
}
TEST(GetFileOwnerTest, ReturnsNullForNullInput)
{
EXPECT_STREQ(GetFileOwner(NULL), NULL);
EXPECT_EQ(errno, ERROR_INVALID_PARAMETER);
}
@@ -3,38 +3,35 @@
//! @brief Unit tests for GetFullyQualifiedName
#include <gtest/gtest.h>
#include "getcomputername.h"
#include "getfullyqualifiedname.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string>
//! Test fixture for GetComputerNameTest
class GetFullyQualifiedNameTest : public ::testing::Test
{
};
TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName)
TEST(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName)
{
std::string actual(GetFullyQualifiedName());
std::string hostname(_POSIX_HOST_NAME_MAX, 0);
ASSERT_FALSE(gethostname(&hostname[0], hostname.length()));
// trim null characters from string
hostname = std::string(hostname.c_str());
std::string hostname(GetComputerName());
struct addrinfo hints, *info;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
ASSERT_FALSE(getaddrinfo(hostname.c_str(), "http", &hints, &info));
// FQDN starts with hostname (which may be fully qualified)
EXPECT_LE(hostname, actual);
// Compare hostname part of FQDN
ASSERT_EQ(hostname, actual.substr(0, hostname.length()));
// hostname did not include domain name, so test it separately
if (hostname < actual)
{
struct addrinfo hints, *info;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
EXPECT_FALSE(getaddrinfo(hostname.c_str(), "http", &hints, &info));
// Compare canonical name to FQDN
ASSERT_EQ(info->ai_canonname, actual);
// Compare canonical name to FQDN
EXPECT_STREQ(info->ai_canonname, actual.c_str());
freeaddrinfo(info);
freeaddrinfo(info);
}
}
@@ -0,0 +1,13 @@
//! @file test-getuserfrompid.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Unit tests for GetUserFromPid
#include <gtest/gtest.h>
#include <pwd.h>
#include "getuserfrompid.h"
TEST(GetUserFromPid, Success)
{
char* expected = getpwuid(geteuid())->pw_name;
EXPECT_STREQ(GetUserFromPid(getpid()), expected);
}
+1 -5
View File
@@ -2,9 +2,6 @@
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Unit tests for GetUserName
#include <string>
#include <vector>
#include <unistd.h>
#include <gtest/gtest.h>
#include <pwd.h>
#include "getusername.h"
@@ -12,6 +9,5 @@
TEST(GetUserName, Success)
{
char* expected = getpwuid(geteuid())->pw_name;
ASSERT_TRUE(expected != NULL);
ASSERT_EQ(GetUserName(), std::string(expected));
EXPECT_STREQ(GetUserName(), expected);
}
@@ -1,4 +1,8 @@
Describe "Get-Process" {
It "Should support -IncludeUserName" {
(Get-Process powershell -IncludeUserName | Select-Object -First 1).UserName | Should Match $env:USERNAME
}
# These tests are no good, please replace!
It "Should return a type of Object[] for Get-Process cmdlet" -Pending:$IsOSX {
(Get-Process).GetType().BaseType | Should Be 'array'