diff --git a/rostests/apitests/ws2_32/CMakeLists.txt b/rostests/apitests/ws2_32/CMakeLists.txt index 4f43560bfe2..bbf35a0141f 100644 --- a/rostests/apitests/ws2_32/CMakeLists.txt +++ b/rostests/apitests/ws2_32/CMakeLists.txt @@ -1,14 +1,13 @@ -add_definitions(-D_DLL -D__USE_CRTIMP) - list(APPEND SOURCE + getaddrinfo.c helpers.c ioctlsocket.c recv.c testlist.c) add_executable(ws2_32_apitest ${SOURCE}) -target_link_libraries(ws2_32_apitest wine) +target_link_libraries(ws2_32_apitest wine ${PSEH_LIB}) set_module_type(ws2_32_apitest win32cui) add_importlibs(ws2_32_apitest ws2_32 msvcrt kernel32 ntdll) add_cd_file(TARGET ws2_32_apitest DESTINATION reactos/bin FOR all) diff --git a/rostests/apitests/ws2_32/getaddrinfo.c b/rostests/apitests/ws2_32/getaddrinfo.c new file mode 100644 index 00000000000..26f41be59f9 --- /dev/null +++ b/rostests/apitests/ws2_32/getaddrinfo.c @@ -0,0 +1,264 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for getaddrinfo + * PROGRAMMER: Thomas Faber + */ + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include + +#define StartSeh() ExceptionStatus = STATUS_SUCCESS; _SEH2_TRY { +#define EndSeh(ExpectedStatus) } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExceptionStatus = _SEH2_GetExceptionCode(); } _SEH2_END; ok(ExceptionStatus == ExpectedStatus, "Exception %lx, expected %lx\n", ExceptionStatus, ExpectedStatus) + +#define ok_addrinfo(ai, flags, family, socktype, protocol, addrlen) do \ +{ \ + ok_hex((ai)->ai_flags, flags); \ + ok_dec((ai)->ai_family, family); \ + ok_dec((ai)->ai_socktype, socktype); \ + ok_dec((ai)->ai_protocol, protocol); \ + ok_dec((ai)->ai_addrlen, addrlen); \ +} while (0) + +#define ok_sockaddr_in(sockaddr, family, port, addr) do \ +{ \ + int _i; \ + ok_dec(((SOCKADDR_IN *)(sockaddr))->sin_family, family); \ + ok_dec(ntohs(((SOCKADDR_IN *)(sockaddr))->sin_port), port); \ + ok_hex(((SOCKADDR_IN *)(sockaddr))->sin_addr.S_un.S_addr, \ + inet_addr(addr)); \ + for (_i = 0; _i < 7; _i++) \ + ok_dec(((SOCKADDR_IN *)(sockaddr))->sin_zero[_i], 0); \ +} while (0) + +#define InvalidPointer ((PVOID)0x5555555555555555ULL) + +CHAR LocalAddress[sizeof("255.255.255.255")]; + +static +VOID +TestNodeName(VOID) +{ + int Error; + PADDRINFOA AddrInfo; + ADDRINFOA Hints; + NTSTATUS ExceptionStatus; + struct + { + PCSTR NodeName; + PCSTR ExpectedAddress; + INT Flags; + } Tests[] = + { + { "", LocalAddress }, + { " ", NULL }, + { "doesntexist.reactos.org", NULL }, + { "localhost", "127.0.0.1" }, + { "localhost:80", NULL }, + { "7.8.9.10", "7.8.9.10", AI_NUMERICHOST }, + { "0.0.0.0", "0.0.0.0", AI_NUMERICHOST }, + { "255.255.255.255", "255.255.255.255", AI_NUMERICHOST }, + { "0.0.0.0 ", "0.0.0.0", /* no AI_NUMERICHOST */ }, + { "0.0.0.0:80", NULL }, + { "0.0.0.0.0", NULL }, + { "1.1.1.256", NULL }, + /* let's just assume this one doesn't change any time soon ;) */ + { "google-public-dns-a.google.com", "8.8.8.8" }, + }; + const INT TestCount = sizeof(Tests) / sizeof(Tests[0]); + INT i; + + /* make sure we don't get IPv6 responses */ + ZeroMemory(&Hints, sizeof(Hints)); + Hints.ai_family = AF_INET; + + trace("Nodes\n"); + for (i = 0; i < TestCount; i++) + { + trace("%d: '%s'\n", i, Tests[i].NodeName); + StartSeh(); + AddrInfo = InvalidPointer; + Error = getaddrinfo(Tests[i].NodeName, NULL, &Hints, &AddrInfo); + if (Tests[i].ExpectedAddress) + { + ok_dec(Error, 0); + ok_dec(WSAGetLastError(), 0); + ok(AddrInfo != NULL && AddrInfo != InvalidPointer, + "AddrInfo = %p\n", AddrInfo); + } + else + { + ok_dec(Error, WSAHOST_NOT_FOUND); + ok_dec(WSAGetLastError(), WSAHOST_NOT_FOUND); + ok_ptr(AddrInfo, NULL); + } + if (!Error && AddrInfo && AddrInfo != InvalidPointer) + { + ok_addrinfo(AddrInfo, Tests[i].Flags, AF_INET, + 0, 0, sizeof(SOCKADDR_IN)); + ok_ptr(AddrInfo->ai_canonname, NULL); + ok_sockaddr_in(AddrInfo->ai_addr, AF_INET, + 0, Tests[i].ExpectedAddress); + ok_ptr(AddrInfo->ai_next, NULL); + freeaddrinfo(AddrInfo); + } + EndSeh(STATUS_SUCCESS); + } +} + +static +VOID +TestServiceName(VOID) +{ + int Error; + PADDRINFOA AddrInfo; + ADDRINFOA Hints; + NTSTATUS ExceptionStatus; + struct + { + PCSTR ServiceName; + INT ExpectedPort; + INT SockType; + } Tests[] = + { + { "", 0 }, + { "0", 0 }, + { "1", 1 }, + { "a", -1 }, + { "010", 10 }, + { "0x1a", -1 }, + { "http", 80, SOCK_STREAM }, + { "smtp", 25, SOCK_STREAM }, + { "mail", 25, SOCK_STREAM }, /* alias for smtp */ + { "router", 520, SOCK_DGRAM }, + { "domain", 53, 0 /* DNS supports both UDP and TCP */ }, + { ":0", -1 }, + { "123", 123 }, + { " 123", 123 }, + { " 123", 123 }, + { "32767", 32767 }, + { "32768", 32768 }, + { "65535", 65535 }, + { "65536", 0 }, + { "65537", 1 }, + { "65540", 4 }, + { "65536", 0 }, + { "4294967295", 65535 }, + { "4294967296", 65535 }, + { "9999999999", 65535 }, + { "999999999999999999999999999999999999", 65535 }, + { "+5", 5 }, + { "-1", 65535 }, + { "-4", 65532 }, + { "-65534", 2 }, + { "-65535", 1 }, + { "-65536", 0 }, + { "-65537", 65535 }, + { "28a", -1 }, + { "28 ", -1 }, + { "a28", -1 }, + }; + const INT TestCount = sizeof(Tests) / sizeof(Tests[0]); + INT i; + + /* make sure we don't get IPv6 responses */ + ZeroMemory(&Hints, sizeof(Hints)); + Hints.ai_family = AF_INET; + + trace("Services\n"); + for (i = 0; i < TestCount; i++) + { + trace("%d: '%s'\n", i, Tests[i].ServiceName); + StartSeh() + AddrInfo = InvalidPointer; + Error = getaddrinfo(NULL, Tests[i].ServiceName, &Hints, &AddrInfo); + if (Tests[i].ExpectedPort != -1) + { + ok_dec(Error, 0); + ok_dec(WSAGetLastError(), 0); + ok(AddrInfo != NULL && AddrInfo != InvalidPointer, + "AddrInfo = %p\n", AddrInfo); + } + else + { + ok_dec(Error, WSATYPE_NOT_FOUND); + ok_dec(WSAGetLastError(), WSATYPE_NOT_FOUND); + ok_ptr(AddrInfo, NULL); + } + if (!Error && AddrInfo && AddrInfo != InvalidPointer) + { + ok_addrinfo(AddrInfo, 0, AF_INET, + Tests[i].SockType, 0, sizeof(SOCKADDR_IN)); + ok_ptr(AddrInfo->ai_canonname, NULL); + ok_sockaddr_in(AddrInfo->ai_addr, AF_INET, + Tests[i].ExpectedPort, "127.0.0.1"); + ok_ptr(AddrInfo->ai_next, NULL); + freeaddrinfo(AddrInfo); + } + EndSeh(STATUS_SUCCESS); + } +} + +START_TEST(getaddrinfo) +{ + WSADATA WsaData; + int Error; + PADDRINFOA AddrInfo; + ADDRINFOA Hints; + NTSTATUS ExceptionStatus; + CHAR LocalHostName[128]; + struct hostent *Hostent; + + /* not yet initialized */ + Error = getaddrinfo("127.0.0.1", "80", NULL, &AddrInfo); + ok_dec(Error, WSANOTINITIALISED); + + Error = WSAStartup(MAKEWORD(2, 2), &WsaData); + ok_dec(Error, 0); + + /* initialize LocalAddress for tests */ + Error = gethostname(LocalHostName, sizeof(LocalHostName)); + ok_dec(Error, 0); + ok_dec(WSAGetLastError(), 0); + trace("Local host name is '%s'\n", LocalHostName); + Hostent = gethostbyname(LocalHostName); + ok(Hostent != NULL, "gethostbyname failed with %d\n", WSAGetLastError()); + if (Hostent && Hostent->h_addr_list[0] && Hostent->h_length == sizeof(IN_ADDR)) + { + IN_ADDR Address; + memcpy(&Address, Hostent->h_addr_list[0], sizeof(Address)); + strcpy(LocalAddress, inet_ntoa(Address)); + } + trace("Local address is '%s'\n", LocalAddress); + ok(LocalAddress[0] != '\0', + "Could not determine local address. Following test results may be wrong.\n"); + + ZeroMemory(&Hints, sizeof(Hints)); + /* parameter tests */ + StartSeh(); getaddrinfo(NULL, NULL, NULL, NULL); EndSeh(STATUS_ACCESS_VIOLATION); + StartSeh(); getaddrinfo("", "", &Hints, NULL); EndSeh(STATUS_ACCESS_VIOLATION); + StartSeh(); + AddrInfo = InvalidPointer; + Error = getaddrinfo(NULL, NULL, NULL, &AddrInfo); + ok_dec(Error, WSAHOST_NOT_FOUND); + ok_dec(WSAGetLastError(), WSAHOST_NOT_FOUND); + ok_ptr(AddrInfo, NULL); + EndSeh(STATUS_SUCCESS); + + TestNodeName(); + TestServiceName(); + /* TODO: test passing both node name and service name */ + /* TODO: test hints */ + /* TODO: test IPv6 */ + + Error = WSACleanup(); + ok_dec(Error, 0); + + /* not initialized anymore */ + Error = getaddrinfo("127.0.0.1", "80", NULL, &AddrInfo); + ok_dec(Error, WSANOTINITIALISED); +} diff --git a/rostests/apitests/ws2_32/testlist.c b/rostests/apitests/ws2_32/testlist.c index e760096393e..9c08f5e54f5 100644 --- a/rostests/apitests/ws2_32/testlist.c +++ b/rostests/apitests/ws2_32/testlist.c @@ -5,11 +5,13 @@ #define STANDALONE #include "wine/test.h" +extern void func_getaddrinfo(void); extern void func_ioctlsocket(void); extern void func_recv(void); const struct test winetest_testlist[] = { + { "getaddrinfo", func_getaddrinfo }, { "ioctlsocket", func_ioctlsocket }, { "recv", func_recv },