From 75c86c414aabb72087baab6fbbffae59d9b62fae Mon Sep 17 00:00:00 2001 From: Gabriele Oliaro Date: Thu, 23 Sep 2021 04:33:48 +0200 Subject: [PATCH] Adding unit tests framework to protocol codebase (#3878) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * progres * works! * added sample fractalclient test * updated CMakeLists.txt file * fixed linker problem * fixed library not found error, now need to set entrypoint for test executable * great news, everything works now!!!! * minor changes * rev1 * rev2, linting * bug fix on windows build * rev0.1 * rev1 * rev1.1 * fixed bugs introduced when shortening CmakeFiles * added server unit testing * prevent build of server unit tests on mac * maybe fixed bug? * Fix C++ linker issue with Debug/Release mode difference * Fix C++ DXGI extern header problem * fixed D3D11 import problem * Move main.c headers back into .c file * Add Fractal{Client,Server}Test to GHA yml files * Fix linking issues with gtest, and organize Windows lib list * clarify in GHA * newline Co-authored-by: Nicholas Pipitone Co-authored-by: Philippe Noël <21990816+philippemnoel@users.noreply.github.com> --- .github/workflows/protocol-check-pr.yml | 18 +-- protocol/CMakeLists.txt | 131 ++++++++++++++- protocol/client/CMakeLists.txt | 64 +------- protocol/client/client_utils.c | 32 ++-- protocol/client/handle_server_message.c | 6 +- protocol/client/main.c | 83 +++++----- protocol/client/network.c | 16 +- protocol/client/sdl_event_handler.c | 16 +- protocol/client/sync_packets.c | 6 +- protocol/client/video.c | 4 +- protocol/cmake/CompilerOptions.cmake | 4 - protocol/fractal/video/dxgicapture.h | 7 + protocol/server/CMakeLists.txt | 55 +------ protocol/server/main.c | 72 +-------- protocol/server/main.h | 89 +++++++++++ protocol/test/CMakeLists.txt | 202 ++++++++++++++++++++++++ protocol/test/ClientTest.cpp | 43 +++++ protocol/test/ServerTest.cpp | 45 ++++++ 18 files changed, 620 insertions(+), 273 deletions(-) create mode 100644 protocol/server/main.h create mode 100644 protocol/test/CMakeLists.txt create mode 100644 protocol/test/ClientTest.cpp create mode 100644 protocol/test/ServerTest.cpp diff --git a/.github/workflows/protocol-check-pr.yml b/.github/workflows/protocol-check-pr.yml index 888c30d80d5..a1855ff5790 100644 --- a/.github/workflows/protocol-check-pr.yml +++ b/.github/workflows/protocol-check-pr.yml @@ -115,7 +115,7 @@ jobs: ############################# Unix Configuration Steps END ############################# - - name: Build Protocol Client and Server on Windows + - name: Build and Test Protocol Client and Server on Windows if: runner.os == 'Windows' shell: cmd # Acts as Visual Studio Developer Command Prompt due to ilammy/msvc-dev-cmd@v1 working-directory: protocol @@ -123,15 +123,15 @@ jobs: mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Debug -DCI=TRUE -G "Ninja" || EXIT /B 1 - ninja FractalClient || EXIT /B 1 - ninja FractalServer || EXIT /B 1 + ninja FractalClient FractalClientTest || EXIT /B 1 + ninja FractalServer FractalServerTest || EXIT /B 1 - - name: Build Protocol Client on Linux Ubuntu + - name: Build and Test Protocol Client on Linux Ubuntu if: runner.os == 'Linux' working-directory: protocol - run: ./build_protocol_targets.sh --cmakebuildtype=Debug --cmakesetCI FractalClient + run: ./build_protocol_targets.sh --cmakebuildtype=Debug --cmakesetCI FractalClient FractalClientTest - - name: Build Protocol Client on macOS + - name: Build and Test Protocol Client on macOS if: runner.os == 'macOS' env: FRACTAL_OSX_SYSROOT: "/Applications/Xcode_12.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk" # Necessary for building on macOS @@ -140,12 +140,12 @@ jobs: mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=Debug -DCI=TRUE - make FractalClient -j + make FractalClient FractalClientTest -j - name: Build Protocol Server on Linux Ubuntu if: runner.os == 'Linux' working-directory: protocol - run: ./build_protocol_targets.sh --cmakebuildtype=Debug FractalServer + run: ./build_protocol_targets.sh --cmakebuildtype=Debug FractalServer FractalServerTest # Verify clang-format on Linux - name: Verify Builds with clang-format @@ -200,7 +200,7 @@ jobs: - name: Build Protocol Server in Docker Container if: runner.os == 'Linux' working-directory: protocol - run: ./build_protocol_targets.sh --cmakebuildtype=Release FractalServer + run: ./build_protocol_targets.sh --cmakebuildtype=Release FractalServer FractalServerTest # This ensures that all the build files from build_protocol_targets.sh have actually been generated - name: Ensure that all protocol build files are present diff --git a/protocol/CMakeLists.txt b/protocol/CMakeLists.txt index ee754ecb186..34f1d17593d 100644 --- a/protocol/CMakeLists.txt +++ b/protocol/CMakeLists.txt @@ -23,13 +23,7 @@ cmake_minimum_required(VERSION 3.15) cmake_policy(SET CMP0091 NEW) include(CheckLanguage) -# Host is needed since CMAKE_SYSTEM_NAME is set by the project() command -if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") - # Clang can't handle CXX for some reason - project(FractalProtocol LANGUAGES C) -else () - project(FractalProtocol LANGUAGES C CXX) -endif () +project(FractalProtocol LANGUAGES C CXX) if (CMAKE_CONFIGURATION_TYPES) message(FATAL_ERROR "Detected multi-configuration generator! This CMake file does not support multi-configuration generators.") @@ -78,6 +72,7 @@ set(META_AUTHOR_ORGANIZATION "Fractal") set(META_AUTHOR_DOMAIN "https://github.com/fractal/fractal") set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 14) # verbose cmake outputs, useful for debugging CMake issues such as linking set(CMAKE_VERBOSE_MAKEFILE OFF) @@ -264,6 +259,16 @@ if ((NOT LIBMFX AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")) message(FATAL_ERROR "Library LIBMFX was not found! ${CMAKE_SOURCE_DIR}/lib/${arch}/mfx/${CMAKE_SYSTEM_NAME}") endif() +# GoogleTests should be included before we set CMAKE_C_COMPILER to 'clang'. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/refs/heads/master.zip +) +# From GoogleTests' official README: prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +FetchContent_MakeAvailable(googletest) + #Set OSX compiler and SDK globally if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_C_COMPILER clang) @@ -284,11 +289,123 @@ include_directories(SYSTEM ${CMAKE_BINARY_DIR}/include/ffmpeg) # Here is where we tell cmake to look in subdirectories for further CMakeLists.txt add_subdirectory(fractal) + +# Set variables to be used by the CMakeLists in the subdirectories +set(PLATFORM_INDEPENDENT_LIBS fractalCore + fractalAudio + fractalVideo + fractalClipboard + fractalNetwork + fractalLogging + fractalUtils + ${STATIC_SDL2} + ${LIB_SENTRY} +) +set(MAC_SPECIFIC_CLIENT_LIBS "-framework OpenGL" + "-framework VideoToolbox" + "-framework CoreMedia" + "-framework CoreAudio" + "-framework AudioToolbox" + "-framework IOKit" + "-framework ForceFeedback" + "-framework Carbon" + "-framework AppKit" + "-framework Metal" + "-framework QuartzCore" + objc + iconv + ${LIB_OPENSSL} +) + +# MSVC C/C++ Standard Library linking, based on Debug/Release +if (${CMAKE_BUILD_TYPE} MATCHES Debug) + set(WINDOWS_CORE_LIBS + ucrtd + libcmtd + libcpmtd + vcruntimed + msvcrtd + msvcmrtd + msvcprtd + ) +elseif(${CMAKE_BUILD_TYPE} MATCHES Release) + set(WINDOWS_CORE_LIBS + ucrt + libcmt + libcpmt + vcruntime + msvcrt + msvcmrt + msvcprt + ) +endif() + +# Windows Libs Shared by both server and client go here +set(WINDOWS_CORE_LIBS + ${WINDOWS_CORE_LIBS} + ${LIB_OPENSSL} + oldnames # Needed by gtest for things like dup2/creat/etc + kernel32 + gdi32 + winmm + imm32 + shell32 + advapi32 + ole32 + oleaut32 + opengl32 + user32 + uuid + version + ws2_32 + shlwapi + crypt32 + d3d11 + dxgi + dxguid + shcore + DbgHelp + setupapi +) + +# Client Specific windows libs go here +set(WINDOWS_SPECIFIC_CLIENT_LIBS + ${WINDOWS_CORE_LIBS} +) + add_subdirectory(client) if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Server does not make or compile on MacOS set(SERV "FractalServer") + set(PLATFORM_INDEPENDENT_SERVER_LIBS + fractalCore + fractalAudio + fractalVideo + fractalClipboard + fractalCursor + fractalInput + fractalNetwork + fractalLogging + fractalUtils + ${STATIC_SDL2} + ${LIB_SENTRY} + ${LIBMFX} + ) + # Server Specific windows libs go here + set(WINDOWS_SPECIFIC_SERVER_LIBS + ${WINDOWS_CORE_LIBS} + wldap32 + normaliz + winspool + comdlg32 + odbc32 + odbccp32 + avrt + d3dcompiler + ) add_subdirectory(server) endif() +# Include the unit tests code +add_subdirectory(test) if (WSL) message(STATUS "Native bash not found (only WSL), clang-tidy will not be an option") diff --git a/protocol/client/CMakeLists.txt b/protocol/client/CMakeLists.txt index bee5454e104..c3ea3dae64a 100644 --- a/protocol/client/CMakeLists.txt +++ b/protocol/client/CMakeLists.txt @@ -101,17 +101,7 @@ endif() #[[ ################## Linking platform independent libs ################## ]] -target_link_libraries(FractalClient - fractalCore - fractalAudio - fractalVideo - fractalClipboard - fractalNetwork - fractalLogging - fractalUtils - ${STATIC_SDL2} - ${LIB_SENTRY} - ) +target_link_libraries(FractalClient ${PLATFORM_INDEPENDENT_LIBS}) #[[ ################## LINUX ################## @@ -124,13 +114,12 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") Xfixes) find_package(ALSA REQUIRED) include_directories(${X11_INCLUDE_DIR} ${ALSA_INCLUD_DIR}) - target_link_libraries(FractalClient - ${X11_LIBRARIES} + target_link_libraries(FractalClient + ${X11_LIBRARIES} ${X11_Xfixes_LIB} ${ALSA_LIBRARIES} crypto - m - ) + m) endif() #[[ @@ -139,22 +128,7 @@ endif() if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_sources(FractalClient PRIVATE native_window_utils_mac.m) - target_link_libraries(FractalClient - "-framework OpenGL" - "-framework VideoToolbox" - "-framework CoreMedia" - "-framework CoreAudio" - "-framework AudioToolbox" - "-framework IOKit" - "-framework ForceFeedback" - "-framework Carbon" - "-framework AppKit" - "-framework Metal" - "-framework QuartzCore" - objc - iconv - ${LIB_OPENSSL} - ) + target_link_libraries(FractalClient ${MAC_SPECIFIC_CLIENT_LIBS}) endif() #[[ @@ -177,31 +151,5 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") endif() # Link to system libs - target_link_libraries(FractalClient - ${LIB_OPENSSL} - libvcruntime - libucrt - libcmt - kernel32 - gdi32 - winmm - imm32 - shell32 - advapi32 - ole32 - oleaut32 - opengl32 - user32 - uuid - version - ws2_32 - shlwapi - crypt32 - d3d11 - dxgi - dxguid - shcore - DbgHelp - setupapi - ) + target_link_libraries(FractalClient ${WINDOWS_SPECIFIC_CLIENT_LIBS}) endif() diff --git a/protocol/client/client_utils.c b/protocol/client/client_utils.c index c64bb93549a..d07c40f9853 100644 --- a/protocol/client/client_utils.c +++ b/protocol/client/client_utils.c @@ -33,27 +33,35 @@ Includes #include #include -extern volatile char binary_aes_private_key[16]; -extern volatile char hex_aes_private_key[33]; -extern volatile char *server_ip; -extern volatile int output_width; -extern volatile int output_height; -extern volatile char *program_name; -extern volatile CodecType output_codec_type; +// Taken from main.c +volatile int server_width = -1; +volatile int server_height = -1; +volatile CodecType server_codec_type = CODEC_TYPE_UNKNOWN; + +volatile char binary_aes_private_key[16]; +volatile char hex_aes_private_key[33]; +volatile char *server_ip; +volatile int output_width; +volatile int output_height; +volatile char *program_name = NULL; +volatile CodecType output_codec_type = CODEC_TYPE_H264; extern volatile SDL_Window *window; extern volatile int max_bitrate; +// From main.c +volatile bool update_bitrate = false; + // This variables should stay as arrays - we call sizeof() on them -extern char user_email[FRACTAL_ARGS_MAXLEN + 1]; -extern char icon_png_filename[FRACTAL_ARGS_MAXLEN + 1]; +char user_email[FRACTAL_ARGS_MAXLEN + 1]; +char icon_png_filename[FRACTAL_ARGS_MAXLEN + 1]; extern bool skip_taskbar; -extern bool using_stun; +bool using_stun = false; -extern MouseMotionAccumulation mouse_state; -extern volatile SDL_Window *window; +MouseMotionAccumulation mouse_state = {0}; +volatile SDL_Window *window; extern unsigned short port_mappings[USHRT_MAX]; diff --git a/protocol/client/handle_server_message.c b/protocol/client/handle_server_message.c index 5dce1e861d5..7209a636010 100644 --- a/protocol/client/handle_server_message.c +++ b/protocol/client/handle_server_message.c @@ -31,12 +31,12 @@ Includes #include -extern bool exiting; +bool exiting = false; extern int audio_frequency; extern volatile double latency; extern volatile int try_amount; -extern volatile char *window_title; -extern volatile bool should_update_window_title; +volatile char *window_title; +volatile bool should_update_window_title; /* ============================ diff --git a/protocol/client/main.c b/protocol/client/main.c index 206ad594449..28256b2d23f 100644 --- a/protocol/client/main.c +++ b/protocol/client/main.c @@ -55,73 +55,74 @@ Includes #include #endif // __APPLE__ +// N.B.: Please don't put globals here, since main.c won't be included when the testing suite is +// used instead + // Width and Height -volatile int server_width = -1; -volatile int server_height = -1; -volatile CodecType server_codec_type = CODEC_TYPE_UNKNOWN; +extern volatile int server_width; +extern volatile int server_height; +extern volatile CodecType server_codec_type; // maximum mbps extern volatile int max_bitrate; extern volatile int max_burst_bitrate; -volatile bool update_bitrate = false; +extern volatile bool update_bitrate; // Global state variables -volatile char binary_aes_private_key[16]; -volatile char hex_aes_private_key[33]; -volatile SDL_Window* window; -volatile char* window_title; -volatile bool should_update_window_title; -volatile bool run_sync_udp_packets; -volatile bool run_sync_tcp_packets; +extern volatile char binary_aes_private_key[16]; +extern volatile char hex_aes_private_key[33]; +extern volatile SDL_Window* window; +extern volatile char* window_title; +extern volatile bool should_update_window_title; +extern volatile bool run_sync_udp_packets; +extern volatile bool run_sync_tcp_packets; volatile bool is_timing_latency; -volatile double latency; +extern volatile double latency; -volatile FractalRGBColor* native_window_color = NULL; -volatile bool native_window_color_update = false; +extern volatile FractalRGBColor* native_window_color; +extern volatile bool native_window_color_update; -volatile int output_width; -volatile int output_height; -volatile char* program_name = NULL; -volatile CodecType output_codec_type = CODEC_TYPE_H264; -volatile char* server_ip; -char user_email[FRACTAL_ARGS_MAXLEN + 1]; -char icon_png_filename[FRACTAL_ARGS_MAXLEN + 1]; -bool using_stun = false; +extern volatile int output_width; +extern volatile int output_height; +extern volatile char* program_name; +extern volatile CodecType output_codec_type; +extern volatile char* server_ip; +extern char user_email[FRACTAL_ARGS_MAXLEN + 1]; +extern char icon_png_filename[FRACTAL_ARGS_MAXLEN + 1]; +extern bool using_stun; // given by server protocol during port discovery. tells client the ports to use // for UDP and TCP communications. -int udp_port = -1; -int tcp_port = -1; -int client_id = -1; -int uid; +extern int udp_port; +extern int tcp_port; +extern int client_id; +extern int uid; // Keyboard state variables -bool alt_pressed = false; -bool ctrl_pressed = false; -bool lgui_pressed = false; -bool rgui_pressed = false; +extern bool alt_pressed; +extern bool ctrl_pressed; +extern bool lgui_pressed; +extern bool rgui_pressed; // Mouse motion state -MouseMotionAccumulation mouse_state = {0}; +extern MouseMotionAccumulation mouse_state; // Whether a pinch is currently active - set in sdl_event_handler.c extern bool active_pinch; // Window resizing state -SDL_mutex* window_resize_mutex; // protects pending_resize_message -clock window_resize_timer; -volatile bool pending_resize_message = - false; // should be set to true if sdl event handler was not able to process resize event due - // to throttling, so the main loop should process it +extern SDL_mutex* window_resize_mutex; // protects pending_resize_message +extern clock window_resize_timer; +extern volatile bool pending_resize_message; // Function Declarations -SocketContext packet_send_udp_context = {0}; -SocketContext packet_receive_udp_context = {0}; -SocketContext packet_tcp_context = {0}; +extern SocketContext packet_send_udp_context; +extern SocketContext packet_receive_udp_context; +extern SocketContext packet_tcp_context; -volatile bool connected = true; -volatile bool exiting = false; +extern volatile bool connected; +extern volatile bool exiting; volatile int try_amount; // Defines diff --git a/protocol/client/network.c b/protocol/client/network.c index 3fb49c9452d..028fa2ac9c1 100644 --- a/protocol/client/network.c +++ b/protocol/client/network.c @@ -35,16 +35,16 @@ extern char user_email[FRACTAL_ARGS_MAXLEN + 1]; // Data extern volatile char binary_aes_private_key[16]; -extern int udp_port; -extern int tcp_port; -extern int client_id; -extern SocketContext packet_send_udp_context; -extern SocketContext packet_receive_udp_context; -extern SocketContext packet_tcp_context; +int udp_port = -1; +int tcp_port = -1; +int client_id = -1; +SocketContext packet_send_udp_context = {0}; +SocketContext packet_receive_udp_context = {0}; +SocketContext packet_tcp_context = {0}; extern char *server_ip; -extern int uid; +int uid; -extern volatile double latency; +volatile double latency; extern clock last_ping_timer; extern volatile int last_ping_id; extern volatile int ping_failures; diff --git a/protocol/client/sdl_event_handler.c b/protocol/client/sdl_event_handler.c index af8699fc0f4..6b542271a6d 100644 --- a/protocol/client/sdl_event_handler.c +++ b/protocol/client/sdl_event_handler.c @@ -27,18 +27,20 @@ Includes #include "network.h" // Keyboard state variables -extern bool alt_pressed; -extern bool ctrl_pressed; -extern bool lgui_pressed; -extern bool rgui_pressed; +bool alt_pressed = false; +bool ctrl_pressed = false; +bool lgui_pressed = false; +bool rgui_pressed = false; // Main state variables extern bool exiting; -extern SDL_mutex *window_resize_mutex; +SDL_mutex *window_resize_mutex; extern const float window_resize_interval; -extern clock window_resize_timer; -extern volatile bool pending_resize_message; +clock window_resize_timer; +// pending_resize_message should be set to true if sdl event handler was not able to process resize +// event due to throttling, so the main loop should process it +volatile bool pending_resize_message = false; extern volatile SDL_Window *window; diff --git a/protocol/client/sync_packets.c b/protocol/client/sync_packets.c index 781b5b07500..bdc3c5915c3 100644 --- a/protocol/client/sync_packets.c +++ b/protocol/client/sync_packets.c @@ -32,9 +32,9 @@ bool tried_to_update_dimension; bool updater_initialized; clock last_tcp_check_timer; extern SocketContext packet_tcp_context; -extern volatile bool run_sync_udp_packets; -extern volatile bool run_sync_tcp_packets; -extern bool connected; +volatile bool run_sync_udp_packets; +volatile bool run_sync_tcp_packets; +bool connected = true; // Ping variables clock last_ping_timer; volatile int last_ping_id; diff --git a/protocol/client/video.c b/protocol/client/video.c index bff7943e5c6..43b6acde87f 100644 --- a/protocol/client/video.c +++ b/protocol/client/video.c @@ -56,8 +56,8 @@ extern volatile int output_height; extern volatile CodecType output_codec_type; extern volatile double latency; -extern volatile FractalRGBColor* native_window_color; -extern volatile bool native_window_color_update; +volatile FractalRGBColor* native_window_color = NULL; +volatile bool native_window_color_update = false; // START VIDEO VARIABLES volatile FractalCursorState cursor_state = CURSOR_STATE_VISIBLE; diff --git a/protocol/cmake/CompilerOptions.cmake b/protocol/cmake/CompilerOptions.cmake index 0d0d434347f..5bbf4040d45 100644 --- a/protocol/cmake/CompilerOptions.cmake +++ b/protocol/cmake/CompilerOptions.cmake @@ -24,7 +24,3 @@ else() # GCC and Clang base flags "$<$:-O3>") add_link_options("-pthread" "-rdynamic") endif() - -if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - add_compile_options("-working-directory=/") -endif() diff --git a/protocol/fractal/video/dxgicapture.h b/protocol/fractal/video/dxgicapture.h index 3edc963cebc..55c2fdfaeb5 100644 --- a/protocol/fractal/video/dxgicapture.h +++ b/protocol/fractal/video/dxgicapture.h @@ -17,10 +17,17 @@ Includes */ #pragma warning(disable : 4201) +#ifdef __cplusplus +} // End the extern C +#endif #include #include #include #include +#ifdef __cplusplus +// Start the extern C again +extern "C" { +#endif #include #include diff --git a/protocol/server/CMakeLists.txt b/protocol/server/CMakeLists.txt index 52a27a01d7f..cb40b0c8199 100644 --- a/protocol/server/CMakeLists.txt +++ b/protocol/server/CMakeLists.txt @@ -81,18 +81,7 @@ endif () ################## Linking platform independent libs ################## ]] target_link_libraries(FractalServer - fractalCore - fractalAudio - fractalVideo - fractalClipboard - fractalCursor - fractalInput - fractalNetwork - fractalLogging - fractalUtils - ${STATIC_SDL2} - ${LIB_SENTRY} - ${LIBMFX} + ${PLATFORM_INDEPENDENT_SERVER_LIBS} ) #[[ @@ -149,45 +138,5 @@ if (${WIN32}) endif() # Link to system libs - target_link_libraries(FractalServer - ${LIB_OPENSSL} - libvcruntime - libcmt - kernel32 - ws2_32 - crypt32 - wldap32 - normaliz - gdi32 - winmm - imm32 - shell32 - advapi32 - ole32 - oleaut32 - opengl32 - user32 - uuid - version - dxgi - d3d11 - winspool - comdlg32 - odbc32 - odbccp32 - ucrt - ucrtd - vcruntime - msvcrt - msvcmrt - msvcprt - avrt - d3dcompiler - dxguid - crypt32 - shlwapi - shcore - DbgHelp - setupapi - ) + target_link_libraries(FractalServer ${WINDOWS_SPECIFIC_SERVER_LIBS}) endif() diff --git a/protocol/server/main.c b/protocol/server/main.c index 1900f79f54d..14ad92e22b8 100644 --- a/protocol/server/main.c +++ b/protocol/server/main.c @@ -17,75 +17,15 @@ Includes ============================ */ -#if defined(_WIN32) -#define _CRT_SECURE_NO_WARNINGS -#endif -#include -#include -#include -#include -#ifdef _WIN32 -#include -#include -#include -#include -#include -#else -#include -#include -#include -#endif -#include - -#include -#include -#include -#include -#include -#include -#include -#include "client.h" -#include "handle_client_message.h" -#include "parse_args.h" -#include "network.h" -#include "video.h" -#include "audio.h" - -#ifdef _WIN32 -#include -#endif - -#ifdef _WIN32 -#pragma comment(lib, "ws2_32.lib") -#endif -// Linux shouldn't have this - -extern Client clients[MAX_NUM_CLIENTS]; +#include "main.h" -volatile FractalOSType client_os; -char binary_aes_private_key[16]; -char hex_aes_private_key[33]; - -// This variables should stay as arrays - we call sizeof() on them -char identifier[FRACTAL_IDENTIFIER_MAXLEN + 1]; - -volatile int connection_id; -volatile bool exiting; - -int sample_rate = -1; - -volatile int max_bitrate = STARTING_BITRATE; -volatile int max_burst_bitrate = STARTING_BURST_BITRATE; -InputDevice* input_device = NULL; +/* +============================ +Globals +============================ +*/ static FractalMutex packet_mutex; - -volatile bool stop_streaming; -volatile bool wants_iframe; -volatile bool update_encoder; - -bool client_joined_after_window_name_broadcast = false; -// This variable should always be an array - we call sizeof() static char cur_window_name[WINDOW_NAME_MAXLEN + 1] = {0}; /* diff --git a/protocol/server/main.h b/protocol/server/main.h new file mode 100644 index 00000000000..bd0e5614f8b --- /dev/null +++ b/protocol/server/main.h @@ -0,0 +1,89 @@ +#ifndef SERVER_MAIN_H +#define SERVER_MAIN_H +/** + * Copyright Fractal Computers, Inc. 2020 + * @file main.h + * @brief This file contains the main code that runs a Fractal server on a + * Windows or Linux Ubuntu computer. +============================ +Usage +============================ + +Follow main() to see a Fractal video streaming server being created and creating +its threads. +*/ + +/* +============================ +Includes +============================ +*/ +#if defined(_WIN32) +#define _CRT_SECURE_NO_WARNINGS +#endif +#include +#include +#include +#include +#ifdef _WIN32 +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include "client.h" +#include "handle_client_message.h" +#include "parse_args.h" +#include "network.h" +#include "video.h" +#include "audio.h" + +#ifdef _WIN32 +#include +#endif + +#ifdef _WIN32 +#pragma comment(lib, "ws2_32.lib") +#endif +// Linux shouldn't have this + +extern Client clients[MAX_NUM_CLIENTS]; + +volatile FractalOSType client_os; +char binary_aes_private_key[16]; +char hex_aes_private_key[33]; + +// This variables should stay as arrays - we call sizeof() on them +char identifier[FRACTAL_IDENTIFIER_MAXLEN + 1]; + +volatile int connection_id; +volatile bool exiting; + +int sample_rate = -1; + +volatile int max_bitrate = STARTING_BITRATE; +volatile int max_burst_bitrate = STARTING_BURST_BITRATE; +InputDevice* input_device = NULL; + +volatile bool stop_streaming; +volatile bool wants_iframe; +volatile bool update_encoder; + +bool client_joined_after_window_name_broadcast = false; +// This variable should always be an array - we call sizeof() + +#endif // SERVER_MAIN_H diff --git a/protocol/test/CMakeLists.txt b/protocol/test/CMakeLists.txt new file mode 100644 index 00000000000..85084176747 --- /dev/null +++ b/protocol/test/CMakeLists.txt @@ -0,0 +1,202 @@ +#[[ +################## FractalClientUnitTests ################## +]] + +# Create the executable +set(CLIENT_TEST_BINARY FractalClientTest) +add_executable(${CLIENT_TEST_BINARY} ClientTest.cpp + ../client/audio.c + ../client/client_utils.c + ../client/network.c + ../client/sdl_event_handler.c + ../client/sdl_utils.c + ../client/handle_server_message.c + ../client/video.c + ../client/sdlscreeninfo.c + ../client/peercursor.c + ../client/ringbuffer.c + ../client/sync_packets.c + ../client/bitrate.c +) + +# Link the GoogleTest library +target_link_libraries(${CLIENT_TEST_BINARY} gtest) + +# Copy the Sentry library to the build folder +add_custom_command( + TARGET ${CLIENT_TEST_BINARY} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_BINARY_DIR}/lib/64/sentry/${CMAKE_SYSTEM_NAME}/ + $) +# Copy the FFmpeg library to the build folder +add_custom_command( + TARGET ${CLIENT_TEST_BINARY} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_BINARY_DIR}/lib/64/ffmpeg/${CMAKE_SYSTEM_NAME}/ + $) +# Copy the OpenSSL/libcrypto libraries if we are on Windows +if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + add_custom_command( + TARGET ${CLIENT_TEST_BINARY} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_BINARY_DIR}/lib/64/openssl/Windows/libcrypto-1_1-x64.dll + $) +endif() + +# Link the FFmpeg libraries +foreach(LIB ${FFMPEG_LIBS_PATHS}) + message(VERBOSE "linking lib for ${CLIENT_TEST_BINARY}: ${LIB}") + target_link_libraries(${CLIENT_TEST_BINARY} ${LIB}) +endforeach(LIB) + +# Link the threading and dynamic link library if we are on Mac/Linx +if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${CLIENT_TEST_BINARY} ${CMAKE_DL_LIBS}) +endif() + +# Link the remaining platform-independent libraries +target_link_libraries(${CLIENT_TEST_BINARY} + ${PLATFORM_INDEPENDENT_LIBS} +) + +# Link more linux-specific libraries +if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + + target_sources(${CLIENT_TEST_BINARY} PRIVATE ../client/native_window_utils_x11.c) + + find_package(X11 REQUIRED + Xfixes) + find_package(ALSA REQUIRED) + include_directories(${X11_INCLUDE_DIR} ${ALSA_INCLUD_DIR}) + target_link_libraries(${CLIENT_TEST_BINARY} ${X11_LIBRARIES} + ${X11_Xfixes_LIB} + ${ALSA_LIBRARIES} + crypto + m) +endif() + +# Link Mac-specific libs +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + target_sources(${CLIENT_TEST_BINARY} PRIVATE ../client/native_window_utils_mac.m) + + target_link_libraries(${CLIENT_TEST_BINARY} ${MAC_SPECIFIC_CLIENT_LIBS}) +endif() + +# Finally, link Windows-specific libraries +if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") + set(CMAKE_EXE_LINKER_FLAGS "/nodefaultlib /nologo /ignore:4099 ") + + target_sources(${CLIENT_TEST_BINARY} PRIVATE ../client/native_window_utils_windows.c) + target_link_libraries(${CLIENT_TEST_BINARY} fractalInput ${LIBMFX}) + + set_property(TARGET ${CLIENT_TEST_BINARY} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + + if(CMAKE_CUDA_COMPILER) + set_property(TARGET ${CLIENT_TEST_BINARY} PROPERTY CUDA_ARCHITECTURES OFF) + endif() + + # Link to system libs + target_link_libraries(${CLIENT_TEST_BINARY} ${WINDOWS_SPECIFIC_CLIENT_LIBS}) +endif() + + +#[[ +################## FractalServerUnitTests ################## +]] + +if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") # Server unit tests do not make or compile on MacOS + + # Create the executable + set(SERVER_TEST_BINARY FractalServerTest) + add_executable(${SERVER_TEST_BINARY} ServerTest.cpp + ../server/client.c + ../server/video.c + ../server/audio.c + ../server/parse_args.c + ../server/handle_client_message.c + ../server/network.c + ) + + # Link the GoogleTest library + target_link_libraries(${SERVER_TEST_BINARY} gtest) + + # Link the FFmpeg libraries + foreach(LIB ${FFMPEG_LIBS_PATHS}) + message(VERBOSE "linking lib for ${SERVER_TEST_BINARY}: ${LIB}") + target_link_libraries(${SERVER_TEST_BINARY} ${LIB}) + endforeach(LIB) + + # Link the threading and dynamic link library if we are on Mac/Linx + if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + target_link_libraries(${SERVER_TEST_BINARY} ${CMAKE_DL_LIBS}) + endif() + + # Link the remaining platform-independent libraries + target_link_libraries(${SERVER_TEST_BINARY} + ${PLATFORM_INDEPENDENT_SERVER_LIBS} + ) + + if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + find_package(X11 REQUIRED + Xfixes + Xdamage + Xext + Xtst) + include_directories(${X11_INCLUDE_DIR}) + if(NOT X11_LIBRARIES) + message(FATAL_ERROR "Library X11_LIBRARIES was not found!") + endif() + if(NOT X11_Xfixes_LIB) + message(FATAL_ERROR "Library X11_Xfixes_LIB was not found!") + endif() + if(NOT X11_Xdamage_LIB) + message(FATAL_ERROR "Library X11_Xdamage_LIB was not found!") + endif() + if(NOT X11_Xext_LIB) + message(FATAL_ERROR "Library X11_Xext_LIB was not found!") + endif() + + target_link_libraries(${SERVER_TEST_BINARY} + ${X11_LIBRARIES} + ${X11_Xfixes_LIB} + ${X11_Xdamage_LIB} + ${X11_Xext_LIB} + ${X11_Xtst_LIB} + GL + asound + m + OpenSSL::Crypto + ) + endif() + + if (${WIN32}) + #Linked flags: LNK4099 is when the linker cannot find the .pdb for debugging symbols + # this comes up when we used precompiled libraries which we do not have .pdb files for + set(CMAKE_EXE_LINKER_FLAGS "/nodefaultlib /nologo /ignore:4099 ") + + #sets the MSVC runtime library as multithreaded and adds debug symbols if is a debug build + #see https://cmake.org/cmake/help/v3.15/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html#variable:CMAKE_MSVC_RUNTIME_LIBRARY + set_property(TARGET ${SERVER_TEST_BINARY} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + + if(CMAKE_CUDA_COMPILER) + set_property(TARGET ${SERVER_TEST_BINARY} PROPERTY CUDA_ARCHITECTURES OFF) + endif() + + # Link to system libs + target_link_libraries(${SERVER_TEST_BINARY} ${WINDOWS_SPECIFIC_SERVER_LIBS}) + endif() +endif() + +#[[ +################## FractalUnitTests ################## +]] + + +# Include the GoogleTest library, and let gtest scan for the tests in the binary file +include(GoogleTest) +gtest_discover_tests(${CLIENT_TEST_BINARY}) +if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + gtest_discover_tests(${SERVER_TEST_BINARY}) +endif() diff --git a/protocol/test/ClientTest.cpp b/protocol/test/ClientTest.cpp new file mode 100644 index 00000000000..67864d583e9 --- /dev/null +++ b/protocol/test/ClientTest.cpp @@ -0,0 +1,43 @@ +#include +#include "gtest/gtest.h" + +extern "C" { + #include "client/client_utils.h" +} +// Include paths should be relative to the protocol folder +// Examples: +// - To include file.h in protocol folder, use #include "file.h" +// - To include file2.h in protocol/client folder, use #include "client/file.h" +// To include a C source file, you need to wrap the include statement in extern "C" {}. + + +// Below are a few sample tests for illustration purposes. + +TEST(ClientTest, EqualityTest) { + int i = 3; + int j = 3; + EXPECT_EQ(i, j); +} + +TEST(ClientTest, NotEqualityTest) { + int i = 150; + int j = 350; + EXPECT_NE(i,j); +} + +// Example of a test using a function from the client module +TEST(ClientTest, ArgParsingEmptyArgsTest) { + int argc = 1; + + char argv0[] = "./client/build64/FractalClient"; + char *argv[] = {argv0, NULL}; + + int ret_val = client_parse_args(argc,argv); + EXPECT_EQ(ret_val,-1); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/protocol/test/ServerTest.cpp b/protocol/test/ServerTest.cpp new file mode 100644 index 00000000000..db163d91641 --- /dev/null +++ b/protocol/test/ServerTest.cpp @@ -0,0 +1,45 @@ +#include +#include "gtest/gtest.h" + +extern "C" { +#include "server/main.h" +#include "server/parse_args.h" +} +// Include paths should be relative to the protocol folder +// Examples: +// - To include file.h in protocol folder, use #include "file.h" +// - To include file2.h in protocol/server folder, use #include "server/file.h" +// To include a C source file, you need to wrap the include statement in extern "C" {}. + + +// Below are a few sample tests for illustration purposes. + +TEST(ServerTest, EqualityTest) { + int i = 3; + int j = 3; + EXPECT_EQ(i, j); +} + +TEST(ServerTest, NotEqualityTest) { + int i = 150; + int j = 350; + EXPECT_NE(i,j); +} + +// Example of a test using a function from the client module +TEST(ServerTest, ArgParsingUsageArgTest) { + int argc = 2; + + char argv0[] = "./server/build64/FractalServer"; + char argv1[] = "--help"; + char *argv[] = {argv0, argv1, NULL}; + + int ret_val = server_parse_args(argc,argv); + EXPECT_EQ(ret_val,1); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} +