test: Get test code building under Windows

- Initial nmake file based off library nmake file
 - Cast socket call arguments to (char *)
 - Use wrapper sclose() that maps to closesocket() or close()
 - Build a config.h indicating presence of headers
 - Conditionally include netdb.h
 - Remove unnecessary include of sys/socket.h
 - Force longer bitmask for allocation failure tracking
 - Call WSAStartup() / WSACleanup() in main()
 - Set TCP_NODELAY for mock server
 - Turn on tests in AppVeyor build
This commit is contained in:
David Drysdale 2015-12-30 14:29:16 +00:00
parent 830e8fe2b3
commit 3478963873
12 changed files with 418 additions and 17 deletions

View File

@ -7,3 +7,5 @@ build_script:
- if "%platform%" == "x64" call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
- copy ares_build.h.dist ares_build.h
- nmake /f Makefile.msvc
- cd test
- nmake /f Makefile.msvc vtest

4
test/.gitignore vendored
View File

@ -6,4 +6,6 @@ aresfuzz
arestest.log
arestest.trs
test-suite.log
fuzzoutput
fuzzoutput
config.h.in
config.h

364
test/Makefile.msvc Normal file
View File

@ -0,0 +1,364 @@
# Permission to use, copy, modify, and distribute this
# software and its documentation for any purpose and without
# fee is hereby granted, provided that the above copyright
# notice appear in all copies and that both that copyright
# notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in
# advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
# M.I.T. makes no representations about the suitability of
# this software for any purpose. It is provided "as is"
# without express or implied warranty.
# ------------------------------------------------------------------------------
#
# Makefile for building c-ares test suite with MSVC.
#
# Usage: nmake /f makefile.msvc CFG=<config> <target>
#
# <config> can be one of: [ lib-release | lib-debug | dll-release | dll-debug }
# <target> can be one of: [ all | arestest | clean }
#
# If <target> is not specified then all targets are built.
# If <config> is not specified then lib-debug will be assumed.
#
# This makefile must be processed from the subdir where it is located.
#
# All results are generated below a subdirectory named msvcXXX.
#
# ------------------------------------------------------------------------------
# ------------------------------------------------
# c-ares static and dynamic libraries common base
# file names for release and debug configurations
# ------------------------------------------------
LIBNAME = cares
STA_LIB_REL = lib$(LIBNAME)
DYN_LIB_REL = $(LIBNAME)
STA_LIB_DBG = $(STA_LIB_REL)d
DYN_LIB_DBG = $(DYN_LIB_REL)d
# -------------------------------------------
# Base names for c-ares DLL import libraries
# -------------------------------------------
IMP_LIB_REL = $(DYN_LIB_REL)
IMP_LIB_DBG = $(DYN_LIB_DBG)
# --------------------------
# Runtime library selection
# --------------------------
RTLIB = /MD
RTLIBD = /MDd
!IF "$(RTLIBCFG)" == "static"
RTLIB = /MT
RTLIBD = /MTd
!ENDIF
# -------------------------------------------
# Detect NMAKE version deducing MSVC version
# -------------------------------------------
!IFNDEF _NMAKE_VER
! MESSAGE Macro _NMAKE_VER not defined.
! MESSAGE Use MSVC's NMAKE to process this makefile.
! ERROR See previous message.
!ENDIF
!IF "$(_NMAKE_VER)" == "6.00.8168.0"
CC_VERS_NUM = 60
!ELSEIF "$(_NMAKE_VER)" == "6.00.9782.0"
CC_VERS_NUM = 60
!ELSEIF "$(_NMAKE_VER)" == "7.00.8882"
CC_VERS_NUM = 70
!ELSEIF "$(_NMAKE_VER)" == "7.00.9466"
CC_VERS_NUM = 70
!ELSEIF "$(_NMAKE_VER)" == "7.00.9955"
CC_VERS_NUM = 70
!ELSEIF "$(_NMAKE_VER)" == "7.10.2240.8"
CC_VERS_NUM = 71
!ELSEIF "$(_NMAKE_VER)" == "7.10.3077"
CC_VERS_NUM = 71
!ELSEIF "$(_NMAKE_VER)" == "8.00.40607.16"
CC_VERS_NUM = 80
!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.42"
CC_VERS_NUM = 80
!ELSEIF "$(_NMAKE_VER)" == "8.00.50727.762"
CC_VERS_NUM = 80
!ELSEIF "$(_NMAKE_VER)" == "9.00.20706.01"
CC_VERS_NUM = 90
!ELSEIF "$(_NMAKE_VER)" == "9.00.21022.08"
CC_VERS_NUM = 90
!ELSEIF "$(_NMAKE_VER)" == "9.00.30729.01"
CC_VERS_NUM = 90
!ELSEIF "$(_NMAKE_VER)" == "10.00.20506.01"
CC_VERS_NUM = 100
!ELSEIF "$(_NMAKE_VER)" == "10.00.21003.01"
CC_VERS_NUM = 100
!ELSEIF "$(_NMAKE_VER)" == "10.00.30128.01"
CC_VERS_NUM = 100
!ELSEIF "$(_NMAKE_VER)" == "10.00.30319.01"
CC_VERS_NUM = 100
!ELSEIF "$(_NMAKE_VER)" == "10.00.40219.01"
CC_VERS_NUM = 100
!ELSEIF "$(_NMAKE_VER)" == "11.00.50522.1"
CC_VERS_NUM = 110
!ELSEIF "$(_NMAKE_VER)" == "11.00.50727.1"
CC_VERS_NUM = 110
!ELSEIF "$(_NMAKE_VER)" == "11.00.51106.1"
CC_VERS_NUM = 110
!ELSEIF "$(_NMAKE_VER)" == "11.00.60315.1"
CC_VERS_NUM = 110
!ELSEIF "$(_NMAKE_VER)" == "12.00.21005.1"
CC_VERS_NUM = 120
!ELSE
! MESSAGE Unknown value for _NMAKE_VER macro: "$(_NMAKE_VER)"
! MESSAGE Please, report this condition on the c-ares development
! MESSAGE mailing list: http://cool.haxx.se/mailman/listinfo/c-ares/
! ERROR See previous message.
!ENDIF
CC_VERS_STR = msvc$(CC_VERS_NUM)
# ---------------------------------------------------------
# Verify that current subdir is below the c-ares source one
# ---------------------------------------------------------
!IF ! EXIST(..\ares_init.c)
! MESSAGE Can not process Makefile.msvc from outside of c-ares test subdirectory.
! MESSAGE Change to the subdirectory where Makefile.msvc is found, and try again.
! ERROR See previous message.
!ENDIF
# ------------------------------------------------------------------
# Base subdir is the common root from which other subdirs will hang,
# the name depends on MSVC version being used when building c-ares.
# ------------------------------------------------------------------
BASE_DIR = .\$(CC_VERS_STR)
# Look for a built library of the same configuration in the directory above.
LIB_BASE_DIR = ..\$(CC_VERS_STR)
# ----------------------------------------
# Subdir holding sources for all projects
# ----------------------------------------
SRCDIR = .
# -------------------------
# Configuration validation
# -------------------------
!IF "$(CFG)" == ""
CFG = lib-debug
!ENDIF
VALID_CFGSET = FALSE
!IF "$(CFG)" == "lib-release" || "$(CFG)" == "lib-debug" || \
"$(CFG)" == "dll-release" || "$(CFG)" == "dll-debug"
VALID_CFGSET = TRUE
!ENDIF
!IF "$(VALID_CFGSET)" == "FALSE"
! MESSAGE MSVC c-ares makefile
! MESSAGE
! MESSAGE Usage: nmake /f makefile.msvc CFG=<config> <target>
! MESSAGE
! MESSAGE <config> can be one of: [ lib-release | lib-debug | dll-release | dll-debug }
! MESSAGE <target> can be one of: [ all | arestest | clean }
! MESSAGE
! MESSAGE If <target> is not specified then all targets are built.
! MESSAGE If <config> is not specified then lib-debug will be assumed.
! MESSAGE
! ERROR Choose a valid configuration.
!ENDIF
# --------------------------------------------------------
# Project subdirs independent of configuration being used
# --------------------------------------------------------
PROG_DIR = $(BASE_DIR)\arestest
LIB_DIR = $(LIB_BASE_DIR)\cares
GMOCK_DIR = gmock-1.7.0
GTEST_DIR = $(GMOCK_DIR)\gtest
GMOCK_SRC_DIR = $(GMOCK_DIR)\src
GTEST_SRC_DIR = $(GTEST_DIR)\src
# ---------------------------------------------------
# Subdirs which are configuration dependent are only
# defined when a valid configuration has been given.
# ---------------------------------------------------
PROG_OUTDIR = $(PROG_DIR)\$(CFG)
PROG_OBJDIR = $(PROG_OUTDIR)\obj
LIB_OUTDIR = $(LIB_DIR)\$(CFG)
# -------------------------------------
# TCP/IP stack settings
# -------------------------------------
CFLAGS = /DWIN32
EX_LIBS_REL = ws2_32.lib advapi32.lib kernel32.lib
EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib
# -----------------------------------------
# Switches that depend on compiler version
# -----------------------------------------
!IF $(CC_VERS_NUM) == 60
PDB_NONE = /pdb:none
PDBTYPE_CONSOLIDATE = /pdbtype:consolidate
!ELSE
!UNDEF PDB_NONE
!UNDEF PDBTYPE_CONSOLIDATE
!ENDIF
!IF $(CC_VERS_NUM) <= 70
RT_ERROR_CHECKING = /GZ
!ELSE
RT_ERROR_CHECKING = /RTCsu
!ENDIF
# ----------------------------
# Assorted commands and flags
# ----------------------------
CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS $(RT_ERROR_CHECKING)
CC_CFLAGS = $(CFLAGS) /I. /I.. /I $(GTEST_DIR)/include /I $(GMOCK_DIR)/include /W3 /EHsc /FD
RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"
LINK_CMD_LIB = link.exe /lib /nologo
LINK_CMD_DLL = link.exe /dll /nologo /incremental:no /fixed:no
LINK_CMD_EXE = link.exe /nologo /incremental:no /fixed:no /subsystem:console
LINK_CMD_EXE_REL = $(LINK_CMD_EXE) /release $(PDB_NONE)
LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug $(PDBTYPE_CONSOLIDATE)
# ---------------------------------
# Configuration dependent settings
# ---------------------------------
!IF "$(CFG)" == "lib-release"
CARES_TARGET = $(STA_LIB_REL).lib
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB
CARES_LFLAGS =
SPROG_CFLAGS = /DCARES_STATICLIB
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_REL) $(STA_LIB_REL).lib
CARES_LINK = $(LINK_CMD_LIB)
SPROG_LINK = $(LINK_CMD_EXE_REL)
CC_CMD = $(CC_CMD_REL)
!ENDIF
!IF "$(CFG)" == "lib-debug"
CARES_TARGET = $(STA_LIB_DBG).lib
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB /DDEBUGBUILD
CARES_LFLAGS =
SPROG_CFLAGS = /DCARES_STATICLIB
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_DBG) $(STA_LIB_DBG).lib
CARES_LINK = $(LINK_CMD_LIB)
SPROG_LINK = $(LINK_CMD_EXE_DBG)
CC_CMD = $(CC_CMD_DBG)
!ENDIF
!IF "$(CFG)" == "dll-release"
CARES_TARGET = $(DYN_LIB_REL).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY
CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(PROG_OUTDIR)\$(IMP_LIB_REL).lib $(PDB_NONE)
SPROG_CFLAGS =
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib
CARES_LINK = $(LINK_CMD_DLL)
SPROG_LINK = $(LINK_CMD_EXE_REL)
CC_CMD = $(CC_CMD_REL)
USE_RES_FILE = TRUE
RC_CMD = $(RC_CMD_REL)
!ENDIF
!IF "$(CFG)" == "dll-debug"
CARES_TARGET = $(DYN_LIB_DBG).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD
CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(PROG_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(PROG_OUTDIR)\$(DYN_LIB_DBG).pdb $(PDBTYPE_CONSOLIDATE)
SPROG_CFLAGS =
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib
CARES_LINK = $(LINK_CMD_DLL)
SPROG_LINK = $(LINK_CMD_EXE_DBG)
CC_CMD = $(CC_CMD_DBG)
USE_RES_FILE = TRUE
RC_CMD = $(RC_CMD_DBG)
!ENDIF
# --------------------------------------------
# Makefile.inc provides lists of source files
# --------------------------------------------
!INCLUDE .\Makefile.inc
# ----------------------------
# Build lists of object files
# ----------------------------
!IF [ECHO PROG_OBJS=^$(PROG_OBJDIR)\$(TESTSOURCES: = $(PROG_OBJDIR^)\) > .\prog_objs.inc] == 0
!INCLUDE .\prog_objs.inc
!IF [DEL .\prog_objs.inc]
!ENDIF
!ELSE
!ERROR Problem generating PROG_OBJS list.
!ENDIF
PROG_OBJS = $(PROG_OBJS:.cc=.obj)
GTEST_OBJ = $(PROG_OBJDIR)\gtest-all.obj
GMOCK_OBJ = $(PROG_OBJDIR)\gmock-all.obj
# --------------------------------
# Only our custom inference rules
# --------------------------------
.SUFFIXES:
.SUFFIXES: .cc
{$(SRCDIR)}.cc{$(PROG_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(GMOCK_SRC_DIR)}.cc{$(PROG_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /I $(GMOCK_DIR) /Fo$@ /Fd$(@D)\ /c $<
{$(GTEST_SRC_DIR)}.cc{$(PROG_OBJDIR)}.obj:
$(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /I $(GTEST_DIR) /Fo$@ /Fd$(@D)\ /c $<
# ---------------------------------------------------------------------
# Main targets
# ---------------------------------------------------------------------
ALL: arestest
@
test: arestest
$(PROG_OUTDIR)\arestest
vtest: arestest
$(PROG_OUTDIR)\arestest -v
arestest: $(TESTSOURCES) $(PROB_OUTDIR) $(PROG_OBJDIR) $(PROG_OBJS) $(GTEST_OBJ) $(GMOCK_OBJ)
$(SPROG_LINK) $(SPROG_LFLAGS) /out:$(PROG_OUTDIR)\arestest.exe $(PROG_OBJS) $(GTEST_OBJ) $(GMOCK_OBJ)
@if exist $(PROG_OUTDIR)\arestest.exe.manifest mt -nologo -manifest $(PROG_OUTDIR)\arestest.exe.manifest -outputresource:$(PROG_OUTDIR)\arestest.exe;1
$(PROG_OUTDIR): $(PROG_DIR)
@if not exist $(PROG_OUTDIR) mkdir $(PROG_OUTDIR)
$(PROG_OBJDIR): $(PROG_OUTDIR)
@if not exist $(PROG_OBJDIR) mkdir $(PROG_OBJDIR)
clean:
@-RMDIR /S /Q $(PROG_OUTDIR) >NUL 2>&1
$(BASE_DIR):
@if not exist $(BASE_DIR) mkdir $(BASE_DIR)
$(PROG_DIR): $(BASE_DIR)
@if not exist $(PROG_DIR) mkdir $(PROG_DIR)
# End of Makefile.msvc

View File

@ -2,7 +2,7 @@
#include "ares-test.h"
// library initialization is only needed for windows builds
#ifdef USE_WINSOCK
#ifdef WIN32
#define EXPECTED_NONINIT ARES_ENOTINITIALIZED
#else
#define EXPECTED_NONINIT ARES_SUCCESS

View File

@ -10,7 +10,7 @@ extern "C" {
#undef PACKAGE_STRING
#undef PACKAGE_TARNAME
// ... so we can include the library's config without symbol redefinitions.
#include "ares_config.h"
#include "ares_setup.h"
#include "ares_nowarn.h"
#include "ares_inet_net_pton.h"
#include "ares_data.h"

View File

@ -5,7 +5,9 @@
#include "ares-test.h"
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
namespace ares {
namespace test {

View File

@ -13,6 +13,17 @@ int main(int argc, char* argv[]) {
}
}
#ifdef WIN32
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
#endif
int rc = RUN_ALL_TESTS();
#ifdef WIN32
WSACleanup();
#endif
return rc;
}

View File

@ -239,7 +239,7 @@ TEST_F(DefaultChannelTest, SendFailure) {
EXPECT_EQ(ARES_EBADQUERY, result.status_);
}
std::string ExpandName(const std::vector<byte>& data, ssize_t offset,
std::string ExpandName(const std::vector<byte>& data, int offset,
long *enclen) {
char *name = nullptr;
int rc = ares_expand_name(data.data() + offset, data.data(), data.size(),

View File

@ -1,8 +1,6 @@
#include "ares-test.h"
#include "dns-proto.h"
#include <sys/socket.h>
#include <sstream>
#include <vector>
@ -642,7 +640,7 @@ TEST_P(MockChannelTest, SortListV4) {
memset(&options, 0, sizeof(options));
int optmask = 0;
EXPECT_EQ(ARES_SUCCESS, ares_save_options(channel_, &options, &optmask));
EXPECT_TRUE(optmask & ARES_OPT_SORTLIST);
EXPECT_TRUE((optmask & ARES_OPT_SORTLIST) == ARES_OPT_SORTLIST);
ares_destroy_options(&options);
}

View File

@ -5,20 +5,37 @@
#include "nameser.h"
#include "ares_dns.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_NETINET_TCP_H
#include <netinet/tcp.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <functional>
#include <sstream>
#ifdef WIN32
#define BYTE_CAST (char *)
#define sclose(x) closesocket(x)
#else
#define BYTE_CAST
#define sclose(x) close(x)
#endif
namespace ares {
namespace test {
bool verbose = false;
int mock_port = 5300;
unsigned long LibraryTest::fails_ = 0;
unsigned long long LibraryTest::fails_ = 0;
std::map<size_t, int> LibraryTest::size_fails_;
void ProcessWork(ares_channel channel,
@ -69,7 +86,7 @@ void ProcessWork(ares_channel channel,
void LibraryTest::SetAllocFail(int nth) {
assert(nth > 0);
assert(nth <= (int)(8 * sizeof(fails_)));
fails_ |= (1 << (nth - 1));
fails_ |= (1LL << (nth - 1));
}
// static
@ -139,7 +156,10 @@ MockServer::MockServer(int family, int port, int tcpport)
EXPECT_NE(-1, tcpfd_);
int optval = 1;
setsockopt(tcpfd_, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval , sizeof(int));
BYTE_CAST &optval , sizeof(int));
// Send TCP data right away.
setsockopt(tcpfd_, IPPROTO_TCP, TCP_NODELAY,
BYTE_CAST &optval , sizeof(int));
// Create a UDP socket to receive data on.
udpfd_ = socket(family, SOCK_DGRAM, 0);
@ -181,10 +201,10 @@ MockServer::MockServer(int family, int port, int tcpport)
MockServer::~MockServer() {
for (int fd : connfds_) {
close(fd);
sclose(fd);
}
close(tcpfd_);
close(udpfd_);
sclose(tcpfd_);
sclose(udpfd_);
}
void MockServer::ProcessFD(int fd) {
@ -206,13 +226,13 @@ void MockServer::ProcessFD(int fd) {
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
byte buffer[2048];
int len = recvfrom(fd, buffer, sizeof(buffer), 0,
int len = recvfrom(fd, BYTE_CAST buffer, sizeof(buffer), 0,
(struct sockaddr *)&addr, &addrlen);
byte* data = buffer;
if (fd != udpfd_) {
if (len == 0) {
connfds_.erase(std::find(connfds_.begin(), connfds_.end(), fd));
close(fd);
sclose(fd);
return;
}
if (len < 2) {
@ -327,7 +347,7 @@ void MockServer::ProcessRequest(int fd, struct sockaddr_storage* addr, int addrl
addrlen = 0;
}
int rc = sendto(fd, reply.data(), reply.size(), 0,
int rc = sendto(fd, BYTE_CAST reply.data(), reply.size(), 0,
(struct sockaddr *)addr, addrlen);
if (rc < static_cast<int>(reply.size())) {
std::cerr << "Failed to send full reply, rc=" << rc << std::endl;

View File

@ -64,7 +64,7 @@ class LibraryTest : public ::testing::Test {
static void afree(void *ptr);
private:
static bool ShouldAllocFail(size_t size);
static unsigned long fails_;
static unsigned long long fails_;
static std::map<size_t, int> size_fails_;
};

View File

@ -13,5 +13,7 @@ AC_SUBST(LIBTOOL_DEPS)
AX_PTHREAD
AX_CODE_COVERAGE
AC_CHECK_HEADERS(netdb.h netinet/tcp.h)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT