diff --git a/.gitignore b/.gitignore index a0771e7..ca7b258 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ libSDL2pp.so.* tests/*.exe tests/live_mixer tests/live_rendering +tests/live_window tests/test_error tests/test_optional tests/test_pointrect diff --git a/.travis.yml b/.travis.yml index 73783a2..5f38d1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,7 +28,7 @@ before_install: script: - export PREFIX=`pwd`.prefix - cmake . -DCMAKE_INSTALL_PREFIX=$PREFIX -DSDL2PP_WITH_WERROR=YES -DSDL2PP_CXXSTD=$CXXSTD -DCMAKE_BUILD_TYPE=$BUILD_TYPE - - VERBOSE=1 make && make test && make install + - VERBOSE=1 make && make ARGS=-V test && make install - cppcheck -I . --enable=performance,portability,information,missingInclude --error-exitcode=2 SDL2pp # `style' gives false positive in cppcheck 1.61 which comes with trusty - "if make doxygen 2>&1 | grep 'warning:'; then echo 'FATAL: doxygen warnings!'; false; fi" - "if git ls-files --others --exclude-standard | grep ''; then echo 'FATAL: incomplete .gitignore'; false; fi" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e69b257..9bb294f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ SET(CLI_TESTS # live tests require X11 display and/or audio output SET(LIVE_TESTS live_rendering + live_window ) IF(SDL2PP_WITH_MIXER) diff --git a/tests/live_window.cc b/tests/live_window.cc new file mode 100644 index 0000000..bdc64e7 --- /dev/null +++ b/tests/live_window.cc @@ -0,0 +1,207 @@ +#include + +#include +#include + +#include "testing.h" + +using namespace SDL2pp; + +static void EventSleep(Uint32 ms) { + Uint32 now = SDL_GetTicks(); + Uint32 deadline = now + ms; + + SDL_Event event; + while ((now = SDL_GetTicks()) < deadline) + SDL_WaitEventTimeout(&event, deadline - now); +} + +BEGIN_TEST(int, char*[]) + SDL sdl(SDL_INIT_VIDEO); + Window window("libSDL2pp test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 320, 240, SDL_WINDOW_RESIZABLE); + + { + // Move tests + SDL_Window* win = window.Get(); + + Window window1(std::move(window)); + EXPECT_EQUAL(window1.Get(), win); + EXPECT_TRUE(window.Get() == nullptr); + + std::swap(window, window1); + EXPECT_EQUAL(window.Get(), win); + EXPECT_TRUE(window1.Get() == nullptr); + + window = std::move(window); // self-move + EXPECT_EQUAL(window.Get(), win); + } + + EventSleep(1000); // Process events for newborn window + + { + // Size + EXPECT_EQUAL(window.GetSize(), Point(320, 240), "May fail on some WMs", NON_FATAL); + EXPECT_EQUAL(window.GetWidth(), 320, "May fail on some WMs", NON_FATAL); + EXPECT_EQUAL(window.GetHeight(), 240, "May fail on some WMs", NON_FATAL); + + window.SetSize(400, 300); + EXPECT_EQUAL(window.GetSize(), Point(400, 300)); + EXPECT_EQUAL(window.GetWidth(), 400); + EXPECT_EQUAL(window.GetHeight(), 300); + EventSleep(1000); + + window.SetSize(Point(500, 400)); + EXPECT_EQUAL(window.GetWidth(), 500); + EXPECT_EQUAL(window.GetHeight(), 400); + EventSleep(1000); + } + + { + // Title + EXPECT_EQUAL(window.GetTitle(), "libSDL2pp test"); + + window.SetTitle("libSDL2pp window test"); + EXPECT_EQUAL(window.GetTitle(), "libSDL2pp window test"); + EventSleep(1000); + } + + { + // Drawable size + EXPECT_EQUAL(window.GetDrawableSize(), Point(window.GetDrawableWidth(), window.GetDrawableHeight())); + + // Drawable may be larget than window size, see SDL docs + // Should we compare with multiplies of window size? + EXPECT_TRUE(window.GetDrawableWidth() >= window.GetWidth()); + EXPECT_TRUE(window.GetDrawableHeight() >= window.GetHeight()); + EXPECT_TRUE(window.GetDrawableWidth() > window.GetDrawableHeight()); + } + + { + // Position + Point old_pos = window.GetPosition(); + + window.SetPosition(old_pos + Point(2, 1)); + EXPECT_EQUAL(window.GetPosition(), old_pos + Point(2, 1)); + EventSleep(1000); + + window.SetPosition(old_pos.x + 4, old_pos.y + 2); + EXPECT_EQUAL(window.GetPosition(), old_pos + Point(4, 2)); + EventSleep(1000); + } + + { + // Min/max size + window.SetMinimumSize(16, 16); + window.SetMaximumSize(1600, 1600); + + EXPECT_EQUAL(window.GetMinimumSize(), Point(16, 16)); + EXPECT_EQUAL(window.GetMaximumSize(), Point(1600, 1600)); + + window.SetMinimumSize(Point(32, 32)); + window.SetMaximumSize(Point(3200, 3200)); + + EXPECT_EQUAL(window.GetMinimumSize(), Point(32, 32)); + EXPECT_EQUAL(window.GetMaximumSize(), Point(3200, 3200)); + } + + { + // Grab + EXPECT_TRUE(!window.GetGrab()); + window.SetGrab(true); + EXPECT_TRUE(window.GetGrab()); + EventSleep(1000); + + window.SetGrab(false); + EXPECT_TRUE(!window.GetGrab()); + EventSleep(1000); + } + + { + // Brightness + EXPECT_EQUAL(window.GetBrightness(), 1.0f); + + window.SetBrightness(1.2f); + EXPECT_EQUAL(window.GetBrightness(), 1.2f); + EventSleep(1000); + + window.SetBrightness(1.0f); + EXPECT_EQUAL(window.GetBrightness(), 1.0f); + EventSleep(1000); + } + + { + // Flags + std::cerr << "Window flags: " << std::hex << "0x" << window.GetFlags() << std::dec << std::endl; + + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_SHOWN); + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_RESIZABLE); + + window.Hide(); + EXPECT_TRUE(!(window.GetFlags() & SDL_WINDOW_SHOWN)); + EventSleep(1000); + + window.Show(); + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_SHOWN); + EventSleep(1000); + + window.Maximize(); + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_MAXIMIZED); + EventSleep(1000); + + window.Restore(); + EXPECT_TRUE(!(window.GetFlags() & SDL_WINDOW_MAXIMIZED)); + EventSleep(1000); + + window.Minimize(); + EventSleep(1000); // Minimization may take some time, e.g. on Ubuntu due to animations + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_MINIMIZED, "May fail on some WMs", NON_FATAL); + EventSleep(1000); + + window.Restore(); + EventSleep(1000); // Restore from minimized state may take some time, e.g. on Ubuntu due to animations + EXPECT_TRUE(!(window.GetFlags() & SDL_WINDOW_MINIMIZED)); + EventSleep(1000); + + // May hang until window is moved (SDL bug?) +// window.SetBordered(false); +// EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_BORDERLESS); +// EventSleep(1000); + +// window.SetBordered(true); +// EXPECT_TRUE(!(window.GetFlags() & SDL_WINDOW_BORDERLESS)); +// EventSleep(1000); + + window.Raise(); + EventSleep(1000); + } + + { + // Display index & mode + + // XXX: may throw + int displayindex = 0; + EXPECT_NO_EXCEPTION(displayindex = window.GetDisplayIndex()); + std::cerr << "Display index: " << displayindex << std::endl; + + SDL_DisplayMode mode; + EXPECT_NO_EXCEPTION(window.GetDisplayMode(mode)); + + std::cerr << "Display mode:" << std::endl; + std::cerr << " Format: 0x" << std::hex << mode.format << std::dec << std::endl; + std::cerr << " Width: " << mode.w << std::endl; + std::cerr << " Height: " << mode.h << std::endl; + std::cerr << " Refresh rate: " << mode.refresh_rate << std::endl; + } + + { + // Fullscreen + window.SetFullscreen(SDL_WINDOW_FULLSCREEN_DESKTOP); + EXPECT_TRUE(window.GetFlags() & SDL_WINDOW_FULLSCREEN_DESKTOP); + EventSleep(1000); + + window.SetFullscreen(0); + EXPECT_TRUE(!(window.GetFlags() & SDL_WINDOW_FULLSCREEN_DESKTOP)); + EventSleep(1000); + } + +END_TEST() diff --git a/tests/testing.h b/tests/testing.h index 20178cd..4be9699 100644 --- a/tests/testing.h +++ b/tests/testing.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2015 Dmitry Marakasov + * Copyright (c) 2011-2016 Dmitry Marakasov * All rights reserved. * * See https://github.com/AMDmi3/testing.h for updates, bug reports, @@ -234,6 +234,35 @@ public: RegisterTest(thrown && as_expected, flags, message, description); } + // ExpectNoException + void ExpectNoException(const std::string& expression_str, std::function&& func, const std::string& description, int flags, DummyArgument) { + bool thrown = false; + bool std_exception = false; + + std::string what; + + try { + func(); + } catch (std::exception& e) { + thrown = true; + std_exception = true; + what = e.what(); + } catch (...) { + thrown = true; + } + + std::string message; + + if (thrown && std_exception) + message = Stylify(EXPRESSION, expression_str) + " has thrown unexpected exception derived from std::exception (what(): " + Stylify(LITERAL, what) + ")"; + else if (thrown) + message = Stylify(EXPRESSION, expression_str) + " has thrown unexpected exception not derived from std::exception"; + else + message = Stylify(EXPRESSION, expression_str) + " hasn't thrown any exceptions as expected"; + + RegisterTest(!thrown, flags, message, description); + } + // ExpectTrue overloads void ExpectTrue(const std::string& expression_str, bool sample, DummyArgument dummy) { ExpectTrue(expression_str, sample, "", 0, dummy); @@ -279,12 +308,25 @@ public: return ExpectException(expression_str, std::move(func), exception_str, "", flags, dummy); } + // ExpectNoException overloads + void ExpectNoException(const std::string& expression_str, std::function&& func, DummyArgument dummy) { + return ExpectNoException(expression_str, std::move(func), "", 0, dummy); + } + + void ExpectNoException(const std::string& expression_str, std::function&& func, const std::string& description, DummyArgument dummy) { + return ExpectNoException(expression_str, std::move(func), description, 0, dummy); + } + + void ExpectNoException(const std::string& expression_str, std::function&& func, int flags, DummyArgument dummy) { + return ExpectNoException(expression_str, std::move(func), "", flags, dummy); + } + void RegisterUnexpectedException() { unexpected_exception_ = true; } void PrintSummary() { - std::cerr << num_failures_ << " failures out of " << num_tests_ << " tests"; + std::cerr << num_failures_ << " failure(s) out of " << num_tests_ << " tests"; if (unexpected_exception_) std::cerr << ", and was terminated prematurely due to unexpected exception"; std::cerr << "\n"; @@ -320,16 +362,19 @@ public: // wrappers to allow true variable number of arguments #define METHOD_WRAPPER(method, expr, ...) tester_.method(#expr, expr, __VA_ARGS__) #define METHOD_WRAPPER_EXCEPTION(expr, exception, ...) tester_.ExpectException(#expr, [&](){expr;}, #exception, __VA_ARGS__) +#define METHOD_WRAPPER_NO_EXCEPTION(expr, ...) tester_.ExpectNoException(#expr, [&](){expr;}, __VA_ARGS__) // checks #ifdef _MSC_VER # define EXPECT_TRUE(expr, ...) do { tester_.ExpectTrue(#expr, expr, __VA_ARGS__, Tester::DummyArgument()); } while(0) # define EXPECT_EQUAL(expr, ...) do { tester_.ExpectEqual(#expr, expr, __VA_ARGS__, Tester::DummyArgument()); } while(0) # define EXPECT_EXCEPTION(expr, exception, ...) do { tester_.ExpectException(#expr, [&](){expr;}, #exception, __VA_ARGS__, Tester::DummyArgument()); } while(0) +# define EXPECT_NO_EXCEPTION(expr, ...) do { tester_.ExpectNoException(#expr, [&](){expr;}, __VA_ARGS__, Tester::DummyArgument()); } while(0) #else # define EXPECT_TRUE(...) do { METHOD_WRAPPER(ExpectTrue, __VA_ARGS__, Tester::DummyArgument()); } while(0) # define EXPECT_EQUAL(...) do { METHOD_WRAPPER(ExpectEqual, __VA_ARGS__, Tester::DummyArgument()); } while(0) # define EXPECT_EXCEPTION(...) do { METHOD_WRAPPER_EXCEPTION(__VA_ARGS__, Tester::DummyArgument()); } while(0) +# define EXPECT_NO_EXCEPTION(...) do { METHOD_WRAPPER_NO_EXCEPTION(__VA_ARGS__, Tester::DummyArgument()); } while(0) #endif // functions