From 44636cecf5a007f021a0d3039fab60d949d6e195 Mon Sep 17 00:00:00 2001 From: molhot Date: Thu, 10 Aug 2023 22:32:17 +0900 Subject: [PATCH 1/9] =?UTF-8?q?socket=E4=BD=9C=E6=88=90=E9=83=A8=E5=88=86?= =?UTF-8?q?=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- srcs/Socket/Socket.cpp | 87 +++++++++++++++++++++++++++++++++++ srcs/TestMain/test_socket.cpp | 18 ++++++++ srcs/includes/Socket.hpp | 39 ++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 srcs/Socket/Socket.cpp create mode 100644 srcs/TestMain/test_socket.cpp create mode 100644 srcs/includes/Socket.hpp diff --git a/srcs/Socket/Socket.cpp b/srcs/Socket/Socket.cpp new file mode 100644 index 00000000..e51e16e8 --- /dev/null +++ b/srcs/Socket/Socket.cpp @@ -0,0 +1,87 @@ +#include "../includes/Socket.hpp" + +Socket::Socket(std::string &port) +{ + this->_status = makesocket(port); +} + +Socket::Socket(const Socket &other) +{ + this->_status = other._status; + this->_socketFD = other._socketFD; +} + +Socket& Socket::operator=(const Socket &other) +{ + if (this == &other) + return (*this); + this->_status = other._status; + this->_socketFD = other._socketFD; + return (*this); +} + +Socket::~Socket() +{ + +} + +int Socket::makesocket(std::string const &port) +{ + struct addrinfo *addr_inf = NULL; + + if (makeAddressInfo(port, &addr_inf) == -1) + return (-1); + _socketFD = socket(addr_inf->ai_family, addr_inf->ai_socktype, addr_inf->ai_protocol); + if (_socketFD == -1) + { + std::cout << "socket func is missed" << std::endl; + close(_socketFD); + freeaddrinfo(addr_inf); + } + + int opt = 1; + if (setsockopt(_socketFD, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { + perror("setsockopt"); + close(_socketFD); + freeaddrinfo(addr_inf); + return (-1); + } + + if (bind(_socketFD, addr_inf->ai_addr, addr_inf->ai_addrlen) == -1) + { + std::cout << "bind func is missed" << std::endl; + close(_socketFD); + freeaddrinfo(addr_inf); + return (-1); + } + + if (listen(_socketFD, SOMAXCONN) == -1) { + perror("listen"); + close(_socketFD); + freeaddrinfo(addr_inf); + return (-1); + } + + fcntl(_socketFD, F_SETFL, O_NONBLOCK); + freeaddrinfo(addr_inf); + return (0); +} + +int Socket::makeAddressInfo(std::string const &port, struct addrinfo **res) +{ + struct addrinfo hints; + int errcode; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET;//TCPとか ipv4とか + hints.ai_socktype = SOCK_STREAM;//安定生のある通信 + hints.ai_flags = AI_PASSIVE;//bindするのに最適 + + if ((errcode = getaddrinfo(NULL, port.c_str(), &hints, res)) != 0) + { + perror("getaddrinfo"); + return (-1); + } + return (0); +} + diff --git a/srcs/TestMain/test_socket.cpp b/srcs/TestMain/test_socket.cpp new file mode 100644 index 00000000..f9dfd519 --- /dev/null +++ b/srcs/TestMain/test_socket.cpp @@ -0,0 +1,18 @@ +#include +#include + + +int main() +{ + std::vector test_portset; + test_portset.push_back("4242"); + test_portset.push_back("2424"); + + std::vector::iterator it = test_portset.begin(); + + while (it != test_portset.end()) + { + + it++; + } +} \ No newline at end of file diff --git a/srcs/includes/Socket.hpp b/srcs/includes/Socket.hpp new file mode 100644 index 00000000..26b70b54 --- /dev/null +++ b/srcs/includes/Socket.hpp @@ -0,0 +1,39 @@ +#ifndef SOCKET_HPP +#define SOCKET_HPP + +# include +# include +# include +# include + +# include +# include +# include +# include + +# include +# include +# include + +# include + +class Socket +{ + private: + int _socketFD; + int _status; + + int makesocket(std::string const &port); + int makeAddressInfo(std::string const &port, struct addrinfo **res); + + public: + Socket(std::string&); + Socket(const Socket &other); + Socket &operator=(const Socket &other); + ~Socket(); + + int get_socketFD(void) const; + int get_status(void) const; +}; + +#endif \ No newline at end of file From 2584313a284527d8601b0fdcf1efb2b6d68bc6d3 Mon Sep 17 00:00:00 2001 From: takira Date: Mon, 21 Aug 2023 16:01:41 +0900 Subject: [PATCH 2/9] update: mv files and update Makefile after cherry-pick --- .gitignore | 2 +- Makefile | 7 ++++++- srcs/Socket/Socket.cpp | 2 +- srcs/{includes => Socket}/Socket.hpp | 0 test/unit_test/is_valid_file_path/.gitignore | 11 ++++++++++- .../unit_test/socket}/test_socket.cpp | 0 6 files changed, 18 insertions(+), 4 deletions(-) rename srcs/{includes => Socket}/Socket.hpp (100%) rename {srcs/TestMain => test/unit_test/socket}/test_socket.cpp (100%) diff --git a/.gitignore b/.gitignore index 3cb87c1e..10c06f50 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ !config !srcs -!srcs/** +!srcs/Socket !www !includes !test diff --git a/Makefile b/Makefile index 2afe1a7c..758d3ceb 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,11 @@ SRCS_DIR = srcs SRCS = main.cpp \ get_valid_config_file_path.cpp +#socket +SOCKET_DIR = Socket +SRCS += $(SOCKET_DIR)/Socket.cpp +INCLUDES_DIR += $(SRCS_DIR)/$(SOCKET_DIR) + # OBJS ------------------------------------------------------------------------- OBJS_DIR = objs @@ -22,7 +27,7 @@ DEPS = $(OBJS:%.o=%.d) # INCLUDES --------------------------------------------------------------------- -INCLUDES_DIR = includes srcs/includes +INCLUDES_DIR = includes INCLUDES = $(addprefix -I, $(INCLUDES_DIR)) diff --git a/srcs/Socket/Socket.cpp b/srcs/Socket/Socket.cpp index e51e16e8..354f6ddc 100644 --- a/srcs/Socket/Socket.cpp +++ b/srcs/Socket/Socket.cpp @@ -1,4 +1,4 @@ -#include "../includes/Socket.hpp" +#include "Socket.hpp" Socket::Socket(std::string &port) { diff --git a/srcs/includes/Socket.hpp b/srcs/Socket/Socket.hpp similarity index 100% rename from srcs/includes/Socket.hpp rename to srcs/Socket/Socket.hpp diff --git a/test/unit_test/is_valid_file_path/.gitignore b/test/unit_test/is_valid_file_path/.gitignore index 702061f4..c33dd865 100644 --- a/test/unit_test/is_valid_file_path/.gitignore +++ b/test/unit_test/is_valid_file_path/.gitignore @@ -9,4 +9,13 @@ !*.hpp !*.sh -!Makefile \ No newline at end of file +!Makefile +/files/dir/file_--- +/files/dir/file_---.conf +/files/dir/file_--r +/files/dir/file_--r.conf +/files/dir/file_-r-.conf +/files/dir/file_-rr.conf +/files/dir/file_r-- +/files/dir/file_r-r +/files/no_x_dir \ No newline at end of file diff --git a/srcs/TestMain/test_socket.cpp b/test/unit_test/socket/test_socket.cpp similarity index 100% rename from srcs/TestMain/test_socket.cpp rename to test/unit_test/socket/test_socket.cpp From 03f81d2c563f908f8ab30133f36af50546379956 Mon Sep 17 00:00:00 2001 From: takira Date: Tue, 22 Aug 2023 10:09:30 +0900 Subject: [PATCH 3/9] update(socket): update Socket class, and add getter --- Makefile | 10 +-- includes/webserv.hpp | 4 +- srcs/Socket/Socket.cpp | 177 ++++++++++++++++++++++++++--------------- srcs/Socket/Socket.hpp | 69 ++++++++-------- 4 files changed, 151 insertions(+), 109 deletions(-) diff --git a/Makefile b/Makefile index 758d3ceb..8b93cea1 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,6 @@ SRCS = main.cpp \ #socket SOCKET_DIR = Socket SRCS += $(SOCKET_DIR)/Socket.cpp -INCLUDES_DIR += $(SRCS_DIR)/$(SOCKET_DIR) # OBJS ------------------------------------------------------------------------- @@ -27,21 +26,20 @@ DEPS = $(OBJS:%.o=%.d) # INCLUDES --------------------------------------------------------------------- -INCLUDES_DIR = includes +INCLUDES_DIR = includes \ + $(SRCS_DIR)/$(SOCKET_DIR) INCLUDES = $(addprefix -I, $(INCLUDES_DIR)) # RULES ------------------------------------------------------------------------ .PHONY : all -all : $(OBJS_DIR) $(NAME) +all : $(NAME) $(NAME) : $(OBJS) $(CXX) $(CXXFLAGS) -o $@ $^ -$(OBJS_DIR) : - @mkdir -p $@ - $(OBJS_DIR)/%.o : $(SRCS_DIR)/%.cpp + @mkdir -p $$(dirname $@) $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< .PHONY : clean diff --git a/includes/webserv.hpp b/includes/webserv.hpp index 2b32404f..66ad5780 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -10,7 +10,9 @@ # define PATH_DELIM '/' # define EXTENSION_DELIM '.' -# define STAT_ERROR (-1) +# define STAT_ERROR (-1) +# define ERROR (-1) +# define OK 0 # define INVALID_ARGUMENT_ERROR_MSG "[Error] invalid argument" # define INVALID_PATH_ERROR_MSG "[Error] invalid file path" diff --git a/srcs/Socket/Socket.cpp b/srcs/Socket/Socket.cpp index 354f6ddc..efeba795 100644 --- a/srcs/Socket/Socket.cpp +++ b/srcs/Socket/Socket.cpp @@ -1,87 +1,136 @@ +#include +#include +#include +#include +#include +#include "webserv.hpp" #include "Socket.hpp" -Socket::Socket(std::string &port) -{ - this->_status = makesocket(port); +Socket::Socket() : _status(ERROR), + _socket_fd(ERROR), + _addr_info(NULL), + _server_ip(SERVER_IP), + _server_port(SERVER_PORT) { + if (create_socket() == ERROR) { + return; + } + if (bind_socket() == ERROR) { + return; + } + if (listen_socket() == ERROR) { + return; + } + if (set_fd_to_nonblock() == ERROR) { + return; + } + this->_status = OK; } -Socket::Socket(const Socket &other) -{ - this->_status = other._status; - this->_socketFD = other._socketFD; +Socket::~Socket() { + if (this->_addr_info != NULL) { + freeaddrinfo(this->_addr_info); + } + if (this->_socket_fd != ERROR) { + close_socket_fd(this->_socket_fd); + } } -Socket& Socket::operator=(const Socket &other) -{ - if (this == &other) - return (*this); - this->_status = other._status; - this->_socketFD = other._socketFD; - return (*this); +int Socket::create_socket() { + int errcode; + int ai_family, ai_socktype, ai_protocol; + + errcode = set_addr_info(&this->_addr_info); + if (errcode != OK) { + std::cerr << gai_strerror(errcode) << std::endl; + return ERROR; + } + + ai_family = this->_addr_info->ai_family; + ai_socktype = this->_addr_info->ai_socktype; + ai_protocol = this->_addr_info->ai_protocol; + errno = 0; + this->_socket_fd = socket(ai_family, ai_socktype, ai_protocol); + if (this->_socket_fd == ERROR) { + std::cerr << strerror(errno) << std::endl; + return ERROR; + } + return OK; } -Socket::~Socket() -{ +/* + listen 192.168.1.2:80; + listen 80; + */ +int Socket::set_addr_info(const char *ip, const char *port, struct addrinfo **result) { + struct addrinfo hints = {}; + int errcode; + set_addr_hints(&hints); + errcode = getaddrinfo(ip, port, &hints, result); + return errcode; } -int Socket::makesocket(std::string const &port) -{ - struct addrinfo *addr_inf = NULL; - - if (makeAddressInfo(port, &addr_inf) == -1) - return (-1); - _socketFD = socket(addr_inf->ai_family, addr_inf->ai_socktype, addr_inf->ai_protocol); - if (_socketFD == -1) - { - std::cout << "socket func is missed" << std::endl; - close(_socketFD); - freeaddrinfo(addr_inf); - } +void Socket::set_addr_hints(struct addrinfo *hints) { + memset(hints, 0, sizeof(struct addrinfo)); + hints->ai_socktype = SOCK_STREAM; + hints->ai_family = AF_UNSPEC; // allows IPv4 and IPv6 + hints->ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV; // socket, IP, PORT + hints->ai_protocol = IPPROTO_TCP; +} - int opt = 1; - if (setsockopt(_socketFD, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) { - perror("setsockopt"); - close(_socketFD); - freeaddrinfo(addr_inf); - return (-1); - } +int Socket::bind_socket() const { + const struct sockaddr *ai_addr; + socklen_t ai_addrlen; - if (bind(_socketFD, addr_inf->ai_addr, addr_inf->ai_addrlen) == -1) - { - std::cout << "bind func is missed" << std::endl; - close(_socketFD); - freeaddrinfo(addr_inf); - return (-1); + if (set_socket_opt(this->_socket_fd) == ERROR) { + return ERROR; } - - if (listen(_socketFD, SOMAXCONN) == -1) { - perror("listen"); - close(_socketFD); - freeaddrinfo(addr_inf); - return (-1); + ai_addr = this->_addr_info->ai_addr; + ai_addrlen = this->_addr_info->ai_addrlen; + errno = 0; + if (bind(this->_socket_fd, ai_addr, ai_addrlen) == ERROR) { + std::cerr << strerror(errno) << std::endl; + return ERROR; } + return OK; +} + +int Socket::set_socket_opt(int socket_fd) { + int opt_val = 1; + socklen_t opt_len = sizeof(opt_val); - fcntl(_socketFD, F_SETFL, O_NONBLOCK); - freeaddrinfo(addr_inf); - return (0); + errno = 0; + if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt_val, opt_len) == ERROR) { + std::cout << strerror(errno) << std::endl; + return ERROR; + } + return OK; } -int Socket::makeAddressInfo(std::string const &port, struct addrinfo **res) -{ - struct addrinfo hints; - int errcode; +int Socket::listen_socket() const { + errno = 0; + if (listen(this->_socket_fd, SOMAXCONN) == ERROR) { + std::cerr << strerror(errno) << std::endl; + return ERROR; + } + return OK; +} - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET;//TCPとか ipv4とか - hints.ai_socktype = SOCK_STREAM;//安定生のある通信 - hints.ai_flags = AI_PASSIVE;//bindするのに最適 +int Socket::set_fd_to_nonblock() const { + errno = 0; + if (fcntl(this->_socket_fd, F_SETFL, O_NONBLOCK | FD_CLOEXEC) == ERROR) { + std::cerr << strerror(errno) << std::endl; + return ERROR; + } + return OK; +} - if ((errcode = getaddrinfo(NULL, port.c_str(), &hints, res)) != 0) - { - perror("getaddrinfo"); - return (-1); +void Socket::close_socket_fd(int socket_fd) { + errno = 0; + if (close(socket_fd) == ERROR) { + std::cerr << strerror(errno) << std::endl; } - return (0); } +int Socket::get_socket_fd() const { return this->_socket_fd; } +int Socket::get_status() const { return this->_status; } diff --git a/srcs/Socket/Socket.hpp b/srcs/Socket/Socket.hpp index 26b70b54..d7e1ea3f 100644 --- a/srcs/Socket/Socket.hpp +++ b/srcs/Socket/Socket.hpp @@ -1,39 +1,32 @@ -#ifndef SOCKET_HPP -#define SOCKET_HPP - -# include -# include -# include -# include - -# include -# include -# include -# include - -# include -# include -# include - -# include - -class Socket -{ - private: - int _socketFD; - int _status; - - int makesocket(std::string const &port); - int makeAddressInfo(std::string const &port, struct addrinfo **res); - - public: - Socket(std::string&); - Socket(const Socket &other); - Socket &operator=(const Socket &other); - ~Socket(); - - int get_socketFD(void) const; - int get_status(void) const; +#pragma once + +# define SERVER_IP "127.0.0.1" +# define SERVER_PORT "8080" + +// todo: config -> port, protocol +// todo: signal +class Socket { + public: + Socket(); + ~Socket(); + + int get_socket_fd() const; + int get_status() const; + + private: + int _status; + int _socket_fd; + struct addrinfo *_addr_info; + const char *_server_ip; // Nullable + const char *_server_port; + + int create_socket(); + int bind_socket() const; + int listen_socket() const; + int set_fd_to_nonblock() const; + + static int set_addr_info(const char *ip, const char *port, struct addrinfo **result); + static void set_addr_hints(struct addrinfo *hints); + static int set_socket_opt(int socket_fd); + static void close_socket_fd(int socket_fd); }; - -#endif \ No newline at end of file From a6f91556cb734dc46fe69e48842110986e9ee479 Mon Sep 17 00:00:00 2001 From: takira Date: Thu, 24 Aug 2023 00:15:22 +0900 Subject: [PATCH 4/9] fix(is_valid_config_file_path): change to throw error when argc == 1 --- includes/webserv.hpp | 5 +++-- srcs/get_valid_config_file_path.cpp | 8 +------- srcs/main.cpp | 5 +---- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/includes/webserv.hpp b/includes/webserv.hpp index 66ad5780..f3f5fdd8 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -1,6 +1,7 @@ #pragma once -# define EXECUTABLE_FILE_ONLY_ARGC 1 +#include + # define CONFIG_FILE_GIVEN_ARGC 2 # define CONFIG_FILE_INDEX 1 @@ -17,5 +18,5 @@ # define INVALID_ARGUMENT_ERROR_MSG "[Error] invalid argument" # define INVALID_PATH_ERROR_MSG "[Error] invalid file path" -std::string get_valid_config_file_path(int argc, char **argv); +std::string get_valid_config_file_path(const char *path); bool is_valid_config_file_path(const char *path); // todo: static diff --git a/srcs/get_valid_config_file_path.cpp b/srcs/get_valid_config_file_path.cpp index 9a9e249c..12dfdd78 100644 --- a/srcs/get_valid_config_file_path.cpp +++ b/srcs/get_valid_config_file_path.cpp @@ -61,13 +61,7 @@ bool is_valid_config_file_path(const char *path) { return true; } -// if config file is not given, path is 'default' todo: empty string ? -std::string get_valid_config_file_path(int argc, char **argv) { - const char *path = argv[CONFIG_FILE_INDEX]; - - if (argc == EXECUTABLE_FILE_ONLY_ARGC) { - return std::string(DEFAULT_CONFIG); - } +std::string get_valid_config_file_path(const char *path) { if (!is_valid_config_file_path(path)) { throw std::invalid_argument(INVALID_PATH_ERROR_MSG); } diff --git a/srcs/main.cpp b/srcs/main.cpp index 0ab280c9..cf9e174b 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -3,9 +3,6 @@ #include "webserv.hpp" static void validate_argc(int argc) { - if (argc == EXECUTABLE_FILE_ONLY_ARGC) { - return; - } if (argc == CONFIG_FILE_GIVEN_ARGC) { return; } @@ -19,7 +16,7 @@ int main(int argc, char **argv) { try { validate_argc(argc); - config_file_path = get_valid_config_file_path(argc, argv); + config_file_path = get_valid_config_file_path(argv[CONFIG_FILE_INDEX]); std::cout << "config_file_path=[" << config_file_path << "]" << std::endl; // if path is 'default', config set to default From 53d8f2a7e946ab841a22e5e796cf6f71e1556536 Mon Sep 17 00:00:00 2001 From: takira Date: Thu, 24 Aug 2023 11:04:36 +0900 Subject: [PATCH 5/9] add(test): add test for get_valid_confg_file_path, use gtest --- .github/workflows/gtest.yml | 21 +++++ .gitignore | 3 +- CMakeLists.txt | 54 ++++++++++++ Makefile | 11 ++- .../test_get_valid_config_file_path.cpp | 87 +++++++++++++++++++ 5 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/gtest.yml create mode 100644 CMakeLists.txt create mode 100644 test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp diff --git a/.github/workflows/gtest.yml b/.github/workflows/gtest.yml new file mode 100644 index 00000000..0987d48f --- /dev/null +++ b/.github/workflows/gtest.yml @@ -0,0 +1,21 @@ +name: GOOGLE_TEST +on: [push] +jobs: + run-google-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: build + run: | + cmake -S . -B build + cmake --build build + + - name: run-all-test + run: ./build/unit_test + + - uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + status: ${{ job.status }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 10c06f50..3cebcd57 100644 --- a/.gitignore +++ b/.gitignore @@ -22,8 +22,9 @@ !Makefile !CPPLINT.cfg !webserv.drawio +!CMakeLists.txt .idea .vscode .DS_Store -CMakeLists.txt \ No newline at end of file +CMakeCache.txt \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..8a832d4b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.23) +project(webserv) + +set(CMAKE_CXX_STANDARD 98) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + + +# google test ------------------------------------------------------------------ +include(FetchContent) +include(GoogleTest) + +FetchContent_Declare( + googletest + DOWNLOAD_EXTRACT_TIMESTAMP true + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) +enable_testing() + + +# when you .cpp or .hpp is added, add the following +# include, webserv srcs, unit_test_srcs +# includes --------------------------------------------------------------------- +include_directories( + includes +) + +# webserv_srcs ----------------------------------------------------------------- +set(webserv_srcs + srcs/get_valid_config_file_path.cpp +) + +add_executable(webserv + srcs/main.cpp + ${webserv_srcs} +) + +# unit_test_srcs --------------------------------------------------------------- +set (unit_test_srcs + test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp) + +add_executable(unit_test + ${webserv_srcs} + ${unit_test_srcs} + ) + +# test ------------------------------------------------------------------------- +target_link_libraries( + unit_test + GTest::gtest_main +) + +gtest_discover_tests(unit_test) \ No newline at end of file diff --git a/Makefile b/Makefile index 8b93cea1..75db8a63 100644 --- a/Makefile +++ b/Makefile @@ -57,9 +57,16 @@ re : fclean all lint : cpplint --recursive srcs +#.PHONY : unit +#unit : +# ./test/unit_test/run_unit_test.sh + .PHONY : unit unit : - ./test/unit_test/run_unit_test.sh - + rm -rf build + cmake -S . -B build + cmake --build build + #cd build && ctest + ./build/unit_test -include $(DEPS) \ No newline at end of file diff --git a/test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp b/test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp new file mode 100644 index 00000000..36b7bd14 --- /dev/null +++ b/test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp @@ -0,0 +1,87 @@ +#include "gtest/gtest.h" +#include "webserv.hpp" + +// TEST(Test, Test) { +// EXPECT_EQ("OK", "OK"); +// EXPECT_EQ("NG", "OK"); +// EXPECT_EQ(1, func(1)); +// EXPECT_EQ(2, func(2)); +// EXPECT_EQ(3, func(3)); +// } + +TEST(TestGetValidConfigFilePath, SimpleTest) { + EXPECT_EQ("test/unit_test/is_valid_file_path/files/file.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/file.conf")); + // EXPECT_EQ("test/unit_test/is_valid_file_path/files/file.CONF", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/file.CONF")); // not supported in Linux...? + // EXPECT_EQ("test/unit_test/is_valid_file_path/files/file.Conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/file.Conf")); // not supported in Linux...? + // EXPECT_EQ("test/unit_test/is_valid_file_path/files/file.conF", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/file.conF")); // not supported in Linux...? + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/file")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/nothing.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/nothing")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/conf")); + + EXPECT_EQ("test/unit_test/is_valid_file_path/files/a.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/a.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/ a.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/a.conf ")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/ a.conf ")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/X.conf")); + + EXPECT_EQ("test/unit_test/is_valid_file_path/files/a.b.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/a.b.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/a.conf.b")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/conf.a")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/conf.a.")); + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)".")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"..")); + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir.conf")); +} + +TEST(TestGetValidConfigFilePath, TestDirPermissionRWX) { + EXPECT_EQ("test/unit_test/is_valid_file_path/files/dir/file_rrr.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_rrr.conf")); + EXPECT_EQ("test/unit_test/is_valid_file_path/files/dir/file_rr-.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_rr-.conf")); + EXPECT_EQ("test/unit_test/is_valid_file_path/files/dir/file_r-r.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_r-r.conf")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_-rr")); // git add permission denied + EXPECT_EQ("test/unit_test/is_valid_file_path/files/dir/file_r--.conf", get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_r--.conf")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_-r-")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_--r")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_---")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/this_is_dir.conf")); + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_rrr")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_rrr")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_rr-")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_-rr")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_r-r")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_-r-")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_--r")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_---")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/file_r--")); + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/dir/this_is_dir")); + +} + +TEST(TestGetValidConfigFilePath, TestDirPermissionRW) { + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_rrr.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_rr-.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_r-r.conf")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_-rr.conf")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_r--.conf")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_-r-.conf")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_--r.conf")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_---.conf")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/thid_is_dir.conf")); + + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_rrr")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_rr-")); + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_r-r")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_-rr")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_r--")); + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_-r-")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_--r")); // git add permission denied + // EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/file_---")); // git add permission denied + EXPECT_ANY_THROW(get_valid_config_file_path((char *)"test/unit_test/is_valid_file_path/files/no_x_dir/thid_is_dir")); +} From 2286b8d636096b122c7acd972d5bcbced61a1ed9 Mon Sep 17 00:00:00 2001 From: takira Date: Thu, 24 Aug 2023 23:25:55 +0900 Subject: [PATCH 6/9] add(test): add test_socket --- .github/workflows/gtest.yml | 27 ++- .github/workflows/unit_test.yml | 2 +- CMakeLists.txt | 6 +- Makefile | 5 +- srcs/Socket/Socket.cpp | 46 ++++- srcs/Socket/Socket.hpp | 5 + test/unit_test/TestSocket.cpp | 263 ++++++++++++++++++++++++++ test/unit_test/socket/test_socket.cpp | 18 -- 8 files changed, 344 insertions(+), 28 deletions(-) create mode 100644 test/unit_test/TestSocket.cpp delete mode 100644 test/unit_test/socket/test_socket.cpp diff --git a/.github/workflows/gtest.yml b/.github/workflows/gtest.yml index 0987d48f..77c7c7f1 100644 --- a/.github/workflows/gtest.yml +++ b/.github/workflows/gtest.yml @@ -1,7 +1,7 @@ -name: GOOGLE_TEST +name: UNIT_TEST on: [push] jobs: - run-google-test: + Linux: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -11,11 +11,30 @@ jobs: cmake -S . -B build cmake --build build - - name: run-all-test + - name: run all tests on Linux run: ./build/unit_test - uses: sarisia/actions-status-discord@v1 if: always() with: webhook: ${{ secrets.DISCORD_WEBHOOK }} - status: ${{ job.status }} \ No newline at end of file + status: ${{ job.status }} + + macOS: + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + + - name: build + run: | + cmake -S . -B build + cmake --build build + + - name: run all tests on macOS + run: ./build/unit_test + + - uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + status: ${{ job.status }} diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml index f4163fb3..92add2e2 100644 --- a/.github/workflows/unit_test.yml +++ b/.github/workflows/unit_test.yml @@ -1,4 +1,4 @@ -name: UNIT_TEST +name: UNIT_TEST_SH on: [push] jobs: run-unit-test: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a832d4b..3e16670d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,11 +24,13 @@ enable_testing() # includes --------------------------------------------------------------------- include_directories( includes + srcs/Socket ) # webserv_srcs ----------------------------------------------------------------- set(webserv_srcs srcs/get_valid_config_file_path.cpp + srcs/Socket/Socket.cpp ) add_executable(webserv @@ -38,7 +40,9 @@ add_executable(webserv # unit_test_srcs --------------------------------------------------------------- set (unit_test_srcs - test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp) + test/unit_test/is_valid_file_path/test_get_valid_config_file_path.cpp + test/unit_test/TestSocket.cpp +) add_executable(unit_test ${webserv_srcs} diff --git a/Makefile b/Makefile index 75db8a63..e821fb29 100644 --- a/Makefile +++ b/Makefile @@ -63,10 +63,11 @@ lint : .PHONY : unit unit : - rm -rf build + #rm -rf build cmake -S . -B build cmake --build build - #cd build && ctest + #./build/unit_test 2>/dev/null ./build/unit_test + #cd build && ctest -include $(DEPS) \ No newline at end of file diff --git a/srcs/Socket/Socket.cpp b/srcs/Socket/Socket.cpp index efeba795..b0458302 100644 --- a/srcs/Socket/Socket.cpp +++ b/srcs/Socket/Socket.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include #include "webserv.hpp" #include "Socket.hpp" @@ -26,20 +28,59 @@ Socket::Socket() : _status(ERROR), this->_status = OK; } +Socket::Socket(const char *server_ip, const char *server_port) : _status(ERROR), + _socket_fd(ERROR), + _addr_info(NULL), + _server_ip(server_ip), + _server_port(server_port) { + if (create_socket() == ERROR) { + return; + } + if (bind_socket() == ERROR) { + return; + } + if (listen_socket() == ERROR) { + return; + } + if (set_fd_to_nonblock() == ERROR) { + return; + } + this->_status = OK; +} + +// Socket::Socket(const Socket ©) { +// *this = copy; +// } +// +// Socket &Socket::operator=(const Socket &rhs) { +// if (this != &rhs) { +// _status = rhs._status; +// _socket_fd = rhs._socket_fd; +// _server_ip = rhs._server_ip; +// _server_port = rhs._server_port; +// // _addr_info = rhs._addr_info; +// set_addr_info(this->_server_ip, this->_server_port, &this->_addr_info); +// } +// return *this; +// } + Socket::~Socket() { if (this->_addr_info != NULL) { freeaddrinfo(this->_addr_info); + this->_addr_info = NULL; } if (this->_socket_fd != ERROR) { close_socket_fd(this->_socket_fd); + this->_socket_fd = ERROR; } + // std::cout << "destructor" << std::endl; } int Socket::create_socket() { int errcode; int ai_family, ai_socktype, ai_protocol; - errcode = set_addr_info(&this->_addr_info); + errcode = set_addr_info(this->_server_ip, this->_server_port, &this->_addr_info); if (errcode != OK) { std::cerr << gai_strerror(errcode) << std::endl; return ERROR; @@ -71,7 +112,6 @@ int Socket::set_addr_info(const char *ip, const char *port, struct addrinfo **re } void Socket::set_addr_hints(struct addrinfo *hints) { - memset(hints, 0, sizeof(struct addrinfo)); hints->ai_socktype = SOCK_STREAM; hints->ai_family = AF_UNSPEC; // allows IPv4 and IPv6 hints->ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV; // socket, IP, PORT @@ -134,3 +174,5 @@ void Socket::close_socket_fd(int socket_fd) { int Socket::get_socket_fd() const { return this->_socket_fd; } int Socket::get_status() const { return this->_status; } +// std::string Socket::get_server_port() const { return this->_server_port; } +// std::string Socket::get_server_ip() const { return this->_server_ip; } diff --git a/srcs/Socket/Socket.hpp b/srcs/Socket/Socket.hpp index d7e1ea3f..eb4c1527 100644 --- a/srcs/Socket/Socket.hpp +++ b/srcs/Socket/Socket.hpp @@ -8,10 +8,15 @@ class Socket { public: Socket(); + Socket(const char *server_ip, const char *server_port); ~Socket(); + // Socket(const Socket ©); // for debug + // Socket &operator=(const Socket &rhs); // for debug int get_socket_fd() const; int get_status() const; + // std::string get_server_ip() const; // for debug + // std::string get_server_port() const; // for debug private: int _status; diff --git a/test/unit_test/TestSocket.cpp b/test/unit_test/TestSocket.cpp new file mode 100644 index 00000000..75992957 --- /dev/null +++ b/test/unit_test/TestSocket.cpp @@ -0,0 +1,263 @@ +#include +#include +#include +#include +#include +#include +#include "gtest/gtest.h" +#include "webserv.hpp" +#include "Socket.hpp" +#include "Color.hpp" + +static struct sockaddr_in create_addr(); +static int create_nonblock_client_fd(); + +/* *********************** */ +/* Socket Unit Test */ +/* *********************** */ +TEST(SocketUnitTest, DefaultConstructor) { + Socket socket = Socket(); + + EXPECT_EQ(OK, socket.get_status()); +} + +TEST(SocketUnitTest, ConstructorWithArgument) { + Socket socket = Socket(SERVER_IP, SERVER_PORT); + + EXPECT_EQ(OK, socket.get_status()); + +} + +// TEST(SocketUnitTest, CopyConstructor) { +// Socket socket_src = Socket(SERVER_IP, SERVER_PORT); +// Socket socket_new = Socket(socket_src); +// +// EXPECT_EQ(socket_src.get_status(), socket_new.get_status()); +// EXPECT_EQ(socket_src.get_socket_fd(), socket_new.get_socket_fd()); +// EXPECT_EQ(socket_src.get_server_port(), socket_new.get_server_port()); +// EXPECT_EQ(socket_src.get_server_ip(), socket_new.get_server_ip()); +// } +// +// TEST(SocketUnitTest, CopyAssignmentConstructor) { +// Socket socket_src = Socket(SERVER_IP, SERVER_PORT); +// Socket socket_new = socket_src; +// +// EXPECT_EQ(socket_src.get_status(), socket_new.get_status()); +// EXPECT_EQ(socket_src.get_socket_fd(), socket_new.get_socket_fd()); +// EXPECT_EQ(socket_src.get_server_port(), socket_new.get_server_port()); +// EXPECT_EQ(socket_src.get_server_ip(), socket_new.get_server_ip()); +// } + +TEST(SocketUnitTest, ConstructorWithValidServerIP) { + int port = 49152; + Socket socket1 = Socket("127.0.0.1", std::to_string(port++).c_str()); + Socket socket2 = Socket("0.0.0.0", std::to_string(port++).c_str()); + Socket socket3 = Socket("000.0000.00000.000000", std::to_string(port++).c_str()); + + EXPECT_EQ(OK, socket1.get_status()); + EXPECT_EQ(OK, socket2.get_status()); + EXPECT_EQ(OK, socket3.get_status()); + +} + +TEST(SocketUnitTest, ConstructorWithInvalidServerIP) { + int port = 49152; + Socket socket1 = Socket("127.0.0.0.1", std::to_string(port++).c_str()); + Socket socket2 = Socket("256.0.0.0", std::to_string(port++).c_str()); + Socket socket3 = Socket("-1", std::to_string(port++).c_str()); + Socket socket4 = Socket("a.0.0.0", std::to_string(port++).c_str()); + Socket socket5 = Socket("127:0.0.1", std::to_string(port++).c_str()); + Socket socket6 = Socket("127,0.0.1", std::to_string(port++).c_str()); + Socket socket7 = Socket("127.0.0.-1", std::to_string(port++).c_str()); + Socket socket8 = Socket("2147483647.2147483647.2147483647.2147483647", std::to_string(port++).c_str()); + // Socket socket9 = Socket("", std::to_string(port++).c_str()); todo: ok? + Socket socket10 = Socket("hoge", std::to_string(port++).c_str()); + Socket socket11 = Socket("0001.0001.0001.0001", std::to_string(port++).c_str()); + Socket socket12 = Socket("255.255.255.254", std::to_string(port++).c_str()); + // Socket socket13 = Socket("255.255.255.255", std::to_string(port++).c_str()); // Linux OK, todo:error? + + EXPECT_EQ(ERROR, socket1.get_status()); + EXPECT_EQ(ERROR, socket2.get_status()); + EXPECT_EQ(ERROR, socket3.get_status()); + EXPECT_EQ(ERROR, socket4.get_status()); + EXPECT_EQ(ERROR, socket5.get_status()); + EXPECT_EQ(ERROR, socket6.get_status()); + EXPECT_EQ(ERROR, socket7.get_status()); + EXPECT_EQ(ERROR, socket8.get_status()); + // EXPECT_EQ(ERROR, socket9.get_status()); + EXPECT_EQ(ERROR, socket10.get_status()); + EXPECT_EQ(ERROR, socket11.get_status()); + EXPECT_EQ(ERROR, socket12.get_status()); + // EXPECT_EQ(ERROR, socket13.get_status()); +} + +TEST(SocketUnitTest, ConstructorWithValidServerPort) { + Socket socket1 = Socket(SERVER_IP, "0"); // ephemeral port + Socket socket2 = Socket(SERVER_IP, "0000"); + Socket socket3 = Socket(SERVER_IP, "8080"); + Socket socket4 = Socket(SERVER_IP, "65535"); + + EXPECT_EQ(OK, socket1.get_status()); + EXPECT_EQ(OK, socket2.get_status()); + EXPECT_EQ(OK, socket3.get_status()); + EXPECT_EQ(OK, socket4.get_status()); +} + +TEST(SocketUnitTest, ConstructorWithInvalidServerPort) { + Socket socket1 = Socket(SERVER_IP, "-1"); +// Socket socket2 = Socket(SERVER_IP, "65536"); // uisingned short 65536->0(ephemeral port) + // Socket socket3 = Socket(SERVER_IP, ""); // strtol->0 (tmp) + Socket socket4 = Socket(SERVER_IP, "hoge"); + Socket socket5 = Socket(SERVER_IP, "--123123"); + Socket socket6 = Socket(SERVER_IP, "127.1"); + + EXPECT_EQ(ERROR, socket1.get_status()); +// EXPECT_EQ(ERROR, socket2.get_status()); + // EXPECT_EQ(ERROR, socket3.get_status()); + EXPECT_EQ(ERROR, socket4.get_status()); + EXPECT_EQ(ERROR, socket5.get_status()); + EXPECT_EQ(ERROR, socket6.get_status()); +} + +TEST(SocketUnitTest, Getter) { + Socket socket = Socket(); + + EXPECT_EQ(OK, socket.get_status()); + EXPECT_NE(ERROR, socket.get_socket_fd()); +} + +// TEST(SocketUnitTest, ExceedMaxFd) { +// int limit = 20; +// +// struct rlimit old_limits; +// if (getrlimit(RLIMIT_NOFILE, &old_limits) != 0) { +// std::cerr << "getrlimit failed\n"; +// return; +// } +// printf("old_limit.cur:%llu,\n", old_limits.rlim_cur); +// +// struct rlimit new_limits; +// new_limits.rlim_cur = limit; +// new_limits.rlim_max = old_limits.rlim_max; +// +// printf("new_limit.cur:%llu\n", new_limits.rlim_cur); +// +// if (setrlimit(RLIMIT_NOFILE, &new_limits) != 0) { +// std::cerr << "setrlimit failed\n"; +// return; +// } +// +// int min_fd = 3; +// std::vector sockets; +// for (int i = 0; i < limit + 10; ++i) { +// // Socket socket = Socket(SERVER_IP, std::to_string(49152 + i).c_str()); +// // sockets.push_back(socket); +// // sockets[i] = Socket(SERVER_IP, std::to_string(49152 + i).c_str()); +// sockets.push_back(Socket(SERVER_IP, std::to_string(49152 + i).c_str())); +// printf("%si:%d, fd:%d, status:%d%s\n", YELLOW, i, sockets[i].get_socket_fd(), sockets[i].get_status(), RESET); +// +// if (i + min_fd <= limit) { +// EXPECT_EQ(OK, sockets[i].get_status()); +// EXPECT_NE(ERROR, sockets[i].get_socket_fd()); +// } else { +// EXPECT_EQ(ERROR, sockets[i].get_status()); +// EXPECT_EQ(ERROR, sockets[i].get_socket_fd()); +// } +// } +// +// if (setrlimit(RLIMIT_NOFILE, &old_limits) != 0) { +// std::cerr << "Restoring setrlimit failed\n"; +// return; +// } +// +// printf("old_limit.cur:%llu\n", old_limits.rlim_cur); +// } + +/* *********************** */ +/* Socket Integration Test */ +/* *********************** */ +TEST(SocketIntegrationTest, ConnectToClient) { + Socket server; + + EXPECT_EQ(server.get_status(), OK); + EXPECT_NE(server.get_socket_fd(), ERROR); + + int client_fd = socket(AF_INET, SOCK_STREAM, 0); + struct sockaddr_in addr = {}; + addr.sin_family = AF_INET; + addr.sin_port = htons(std::strtol(SERVER_PORT, NULL, 10)); + addr.sin_addr.s_addr = inet_addr(SERVER_IP); + + EXPECT_EQ(connect(client_fd, (struct sockaddr *)&addr, sizeof(addr)), OK); + + close(client_fd); +} + +TEST(SocketIntegrationTest, ConnectTooManyClient) { + Socket server; + int client_fd; + + EXPECT_EQ(OK, server.get_status()); + EXPECT_NE(ERROR, server.get_socket_fd()); + + // connect under SOMAXCONN + std::vector client_fds; + for (int i = 0; i < SOMAXCONN; ++i) { + client_fd = socket(AF_INET, SOCK_STREAM, 0); + // printf("cnt:%d, client_fd:%d\n", i+1, client_fd); + + EXPECT_NE(ERROR, client_fd); + + if (client_fd != ERROR) { + client_fds.push_back(client_fd); + struct sockaddr_in addr = create_addr(); + + EXPECT_EQ(OK, connect(client_fd, (struct sockaddr *)&addr, sizeof(addr))); + } + } + + // connect over SOMAXCONN -> fd set to nonblock + client_fd = create_nonblock_client_fd(); + // printf("cnt:%d, client_fd:%d\n", SOMAXCONN, client_fd); + + EXPECT_NE(ERROR, client_fd); + + if (client_fd != ERROR) { + client_fds.push_back(client_fd); + struct sockaddr_in addr = create_addr(); + + EXPECT_EQ(ERROR, connect(client_fd, (struct sockaddr *)&addr, sizeof(addr))); + } + + // destruct + for (std::vector::iterator itr = client_fds.begin(); itr != client_fds.end(); ++itr) { + close(*itr); + } + client_fds.clear(); +} + +/* helper funcs */ +static struct sockaddr_in create_addr() { + struct sockaddr_in addr = {}; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(SERVER_IP); + addr.sin_port = htons(std::strtol(SERVER_PORT, NULL, 10)); + return addr; +} + +static int create_nonblock_client_fd() { + int client_fd; + int result_fcntl; + + client_fd = socket(AF_INET, SOCK_STREAM, 0); + if (client_fd == ERROR) { + return ERROR; + } + result_fcntl = fcntl(client_fd, F_SETFL, O_NONBLOCK); + if (result_fcntl == ERROR) { + close(client_fd); + return ERROR; + } + return client_fd; +} diff --git a/test/unit_test/socket/test_socket.cpp b/test/unit_test/socket/test_socket.cpp deleted file mode 100644 index f9dfd519..00000000 --- a/test/unit_test/socket/test_socket.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - - -int main() -{ - std::vector test_portset; - test_portset.push_back("4242"); - test_portset.push_back("2424"); - - std::vector::iterator it = test_portset.begin(); - - while (it != test_portset.end()) - { - - it++; - } -} \ No newline at end of file From 034e571db6a3c85dc82b117a8328ed0c0ad5b671 Mon Sep 17 00:00:00 2001 From: ak0327 Date: Fri, 25 Aug 2023 09:56:57 +0900 Subject: [PATCH 7/9] add playground_socket --- .gitignore | 1 + playground/.gitignore | 5 +++ playground/playground_socket.cpp | 69 ++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 playground/.gitignore create mode 100644 playground/playground_socket.cpp diff --git a/.gitignore b/.gitignore index 3cebcd57..52a48286 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ !www !includes !test +!playground !*.cpp !*.hpp diff --git a/playground/.gitignore b/playground/.gitignore new file mode 100644 index 00000000..0da64b3b --- /dev/null +++ b/playground/.gitignore @@ -0,0 +1,5 @@ +* + +!.gitignore +!*.cpp +!*.hpp \ No newline at end of file diff --git a/playground/playground_socket.cpp b/playground/playground_socket.cpp new file mode 100644 index 00000000..8852f9f3 --- /dev/null +++ b/playground/playground_socket.cpp @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int test_socket(const char *server_ip, const char *server_port) { + int errcode; + int socket_fd; + int ai_family, ai_socktype, ai_protocol; + struct addrinfo *addr_info; + struct addrinfo hints = {}; +// const char *server_ip = "127.0.0.1"; +// const char *server_port = "65536"; + + printf("ip:%s, port:%s\n", server_ip, server_port); + + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; // allows IPv4 and IPv6 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV; // socket, IP, PORT + hints.ai_protocol = IPPROTO_TCP; + + errcode = getaddrinfo(server_ip, server_port, &hints, &addr_info); + if (errcode != 0) { + std::cerr << "[Error] getaddrinfo:" << gai_strerror(errcode) << std::endl; + return 1; + } +// std::cout << "errcode:" << errcode << ", " << + + ai_family = addr_info->ai_family; + ai_socktype = addr_info->ai_socktype; + ai_protocol = addr_info->ai_protocol; + errno = 0; + std::cout << "socket" << std::endl; + socket_fd = socket(ai_family, ai_socktype, ai_protocol); + if (socket_fd == -1) { + std::cerr << "[Error] socket:" << strerror(errno) << std::endl; + return 1; + } + + std::cout << "bind" << std::endl; + errno = 0; + if (bind(socket_fd, addr_info->ai_addr, addr_info->ai_addrlen) == -1) { + std::cerr << "[Error] bind:" << strerror(errno) << std::endl; + return 1; + } + + std::cout << "listen" << std::endl; + if (listen(socket_fd, SOMAXCONN) == -1) { + std::cerr << "[Error] listen:" << strerror(errno) << std::endl; + return 1; + } + + std::cout << "OK" << std::endl; + return 0; +} + +// port 0, 0はエラーにならない +int main() { + int ret1 = test_socket("255.255.255.254", "8080"); + int ret2 = test_socket("255.255.255.254", "8080"); + + std::cout << "ret1:" << ret1 << std::endl; + std::cout << "ret2:" << ret2 << std::endl; +} From 8e999c41ca333f10c65539b856726030848a3176 Mon Sep 17 00:00:00 2001 From: takira Date: Fri, 25 Aug 2023 10:39:00 +0900 Subject: [PATCH 8/9] update(yml): add notification title --- .github/workflows/gtest.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gtest.yml b/.github/workflows/gtest.yml index 77c7c7f1..343647bd 100644 --- a/.github/workflows/gtest.yml +++ b/.github/workflows/gtest.yml @@ -17,6 +17,7 @@ jobs: - uses: sarisia/actions-status-discord@v1 if: always() with: + title: "UNIT_TEST_ON_LINUX" webhook: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} @@ -36,5 +37,6 @@ jobs: - uses: sarisia/actions-status-discord@v1 if: always() with: + title: "UNIT_TEST_ON_MACOS" webhook: ${{ secrets.DISCORD_WEBHOOK }} status: ${{ job.status }} From abf700252cd88891c9ac93a01f1c799da0682737 Mon Sep 17 00:00:00 2001 From: takira Date: Fri, 25 Aug 2023 13:47:22 +0900 Subject: [PATCH 9/9] update(cmake): add CMAKE_CXX_FLAGS --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e16670d..01e4b0b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ project(webserv) set(CMAKE_CXX_STANDARD 98) set(CMAKE_CXX_STANDARD_REQUIRED ON) - +set(CMAKE_CXX_FLAGS "-std=c++98 -Wall -Wextra -Werror -pedantic") # google test ------------------------------------------------------------------ include(FetchContent)