Made changes based off feedback from Peter. Also added more unit tests

This commit is contained in:
Aaron 2015-08-04 14:38:53 -07:00
parent c979881804
commit 54618f1750
5 changed files with 103 additions and 65 deletions

View file

@ -4,7 +4,7 @@ project(monad_native)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
#include gtest
include_directories(../ext-src/gtest/fused-src ../ext-src/pal/include impl)
include_directories(../ext-src/gtest/fused-src impl)
link_directories(${monad_native_BINARY_DIR})
# source file definitions

View file

@ -1,11 +1,9 @@
#include "getcomputername.h"
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include <unistd.h>
#include <string>
#include <vector>
#include <scxcorelib/scxstrencodingconv.h>
#include <iostream>
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx
@ -23,13 +21,13 @@
// Returns:
// 1 - succeeded
// 0 - failed
BOOL GetComputerNameW(LPTSTR name, LPDWORD len)
BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len)
{
const std::string utf8 = "UTF-8";
errno = 0;
// Check parameters
if (!name || !len) {
if (!nameOfComputer || !len) {
errno = ERROR_INVALID_PARAMETER;
return 0;
}
@ -42,9 +40,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len)
return 0;
}
// Get username from system in a thread-safe manner
std::string username(LOGIN_NAME_MAX, '\0');
int err = gethostname(&username[0], username.size());
// Get computername from system in a thread-safe manner
std::string computerName(HOST_MAX_NAME, '\0');
int err = gethostname(&computerName[0], computerName.size());
// Map errno to Win32 Error Codes
if (err != 0) {
switch (errno) {
@ -67,28 +65,18 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len)
case ENOTTY:
errno = ERROR_NO_ASSOCIATION;
break;
errno = ERROR_NO_ASSOCIATION;
default:
errno = ERROR_INVALID_FUNCTION;
}
return 0;
}
// "Trim" the username to the first trailing null because
// otherwise the std::string with repeated null characters is
// valid, and the conversion will still include all the null
// characters. Creating a std::string from the C string of the
// original effectively trims it to the first null, without
// the need to manually trim whitespace (nor using Boost).
username = std::string(username.c_str());
//Resize the string to not inlcude extra buffer space
const DWORD length = computerName.find_first_of('\0') + 1;
computerName.resize(length);
// Convert to char * to WCHAR_T * (UTF-8 to UTF-16 LE w/o BOM)
std::vector<unsigned char> output;
SCXCoreLib::Utf8ToUtf16le(username, output);
// The length is the number of characters in the string, which
// is half the string size because UTF-16 encodes two bytes
// per character, plus one for the trailing null.
const DWORD length = output.size()/2 + 1;
//Check if parameters passed enough buffer space
if (length > *len) {
errno = ERROR_INSUFFICIENT_BUFFER;
// Set lpnSize if buffer is too small to inform user
@ -97,27 +85,9 @@ BOOL GetComputerNameW(LPTSTR name, LPDWORD len)
return 0;
}
// Add two null bytes (because it's UTF-16)
output.push_back('\0');
output.push_back('\0');
memcpy(name, &output[0], output.size());
*len = output.size()/2;
memcpy(nameOfComputer, &computerName[0], length);
*len = length;
return 1;
/*
size_t len2 = *len;
int host = gethostname(name, len2);
if(host == 0)
{
return TRUE;
}
else
{
errno = ERROR_BUFFER_OVERFLOW;
return FALSE;
}
*/
}

View file

@ -4,6 +4,6 @@
PAL_BEGIN_EXTERNC
BOOL GetComputerNameW(LPTSTR name, LPDWORD len);
BOOL GetComputerNameW(LPTSTR nameOfComputer, LPDWORD len);
PAL_END_EXTERNC

View file

@ -80,6 +80,7 @@
#define ERROR_NO_SUCH_USER 0x00000525
#define ERROR_INVALID_FUNCTION 0x00000001
#define MAX_PATH 0x00000104
#define HOST_MAX_NAME 256
typedef unsigned long long uint64;
#endif

View file

@ -2,27 +2,94 @@
#include "getcomputername.h"
#include <iostream>
TEST(GetComputerName,simple)
{
char hostname[HOST_NAME_MAX];
std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');
DWORD hostSize = HOST_NAME_MAX;
BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize);
BOOL host = gethostname(hostname, sizeof hostname);
class GetComputerNameTest : public ::testing::Test {
protected:
DWORD lpnSize;
BOOL result;
std::string expectedComputerName;
std::string computerName;
//Get expected result from using linux call
GetComputerNameTest(){
char hostname[HOST_MAX_NAME];
BOOL host = gethostname(hostname, sizeof hostname);
expectedComputerName = hostname;
}
void TestWithSize(DWORD size) {
lpnSize = size;
// allocate a DWORD buffer to receive computername
computerName.assign(lpnSize, '\0');
result = GetComputerNameW(&computerName[0], &lpnSize);
}
void TestSuccess() {
SCOPED_TRACE("");
// returns 1 on success
EXPECT_EQ(1, result);
//Resize to cut off '\0'
computerName.resize(expectedComputerName.length());
ASSERT_EQ(expectedComputerName.size()+1, lpnSize);
EXPECT_EQ(computerName, expectedComputerName);
}
void TestInvalidParameter() {
SCOPED_TRACE("");
// returns 0 on failure
EXPECT_EQ(0, result);
// sets errno to ERROR_INVALID_PARAMETER when lpBuffer is null
EXPECT_EQ(errno, ERROR_INVALID_PARAMETER);
}
void TestInsufficientBuffer() {
SCOPED_TRACE("");
// returns 0 on failure
EXPECT_EQ(0, result);
// sets errno to ERROR_INSUFFICIENT_BUFFER
EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER);
// sets lpnSize to length of username + null
ASSERT_EQ(expectedComputerName.size()+1, lpnSize);
}
};
std::string hostnameString(hostname);
std::string hostnameStringTest(hostnameFunctionTest);
ASSERT_TRUE(getComputerName == TRUE);
ASSERT_EQ(host,0);
ASSERT_EQ(hostnameString,hostnameStringTest);
TEST_F(GetComputerNameTest, BufferAsNullButNotBufferSize) {
lpnSize = 1;
result = GetComputerNameW(NULL, &lpnSize);
TestInvalidParameter();
// does not reset lpnSize
EXPECT_EQ(1, lpnSize);
}
TEST(GetComputerName,bufferttoosmall)
{
std::string hostnameFunctionTest(LOGIN_NAME_MAX, '\0');
DWORD hostSize = 0;
BOOL getComputerName = GetComputerNameW(&hostnameFunctionTest[0], &hostSize);
ASSERT_TRUE(getComputerName == 0);
// EXPECT_EQ(errno, ERROR_BUFFER_OVERFLOW);
TEST_F(GetComputerNameTest, BufferSizeAsNullButNotBuffer) {
computerName.push_back('\0');
result = GetComputerNameW(&computerName[0], NULL);
TestInvalidParameter();
}
TEST_F(GetComputerNameTest, BufferSizeAsZero) {
TestWithSize(0);
EXPECT_EQ(errno, ERROR_INSUFFICIENT_BUFFER);
}
TEST_F(GetComputerNameTest, BufferSizeAsUserNameMinusOne) {
// the buffer is also too small
TestWithSize(expectedComputerName.size()-1);
TestInsufficientBuffer();
}
TEST_F(GetComputerNameTest, BufferSizeAsUserNamePlusOne) {
// the buffer is exactly big enough
TestWithSize(expectedComputerName.size()+1);
TestSuccess();
}
TEST_F(GetComputerNameTest, BufferSizeAsLoginNameMax) {
// the buffer larger than needed
TestWithSize(HOST_MAX_NAME);
TestSuccess();
}