diff --git a/CMakeLists.txt b/CMakeLists.txt index abe7f2e..d450514 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,10 @@ FetchContent_Declare( FetchContent_MakeAvailable(unity) -add_executable(test_aswm test/test_aswm.c) +add_executable(test_aswm + test/test_set_up.c + test/aswm/test_aswm.c +) target_include_directories(test_aswm PUBLIC unity) target_link_libraries(test_aswm libaswm unity) diff --git a/test/aswm/test_aswm.c b/test/aswm/test_aswm.c new file mode 100644 index 0000000..bd4bd24 --- /dev/null +++ b/test/aswm/test_aswm.c @@ -0,0 +1,145 @@ +#include "aswm/aswm.h" +#include "../test_set_up.h" +#include +#include +#include + +clock_t USER_DELAY = 1 * CLOCKS_PER_SEC; + +#define MAX_COLOR 65535 + +void run_aswm(void) { + int stat_loc; + // Ensures aswm is running + TEST_ASSERT_EQUAL_INT(0, waitpid(aswm_pid, &stat_loc, WNOHANG)); +} + +void create_single_resizeable_top_level_window(void) { + XColor blue; + blue.blue = MAX_COLOR; + XAllocColor(test_display, XDefaultColormap(test_display, DefaultScreen(test_display)), &blue); + + XColor red; + red.red = MAX_COLOR; + XAllocColor(test_display, XDefaultColormap(test_display, DefaultScreen(test_display)), &red); + + Window window = XCreateSimpleWindow(test_display, test_root, + 10 /*x*/, 10 /*y*/, 128 /*w*/, 128 /*h*/, + 0 /*TODO: border width*/, CopyFromParent /*depth*/, blue.pixel /* background */); + // The top level window might have children. Those must **not** be altered + // by the Window Manager + Window child = XCreateSimpleWindow(test_display, window, + 0, 0, 25, 30, + 0, CopyFromParent, red.pixel); + XSelectInput(test_display, window, VisibilityChangeMask); + XMapWindow(test_display, child); + XMapWindow(test_display, window); + + int visibility; + clock_t start = clock(); + while((clock() - start) < USER_DELAY) { + XEvent e; + XCheckWindowEvent(test_display, window, VisibilityChangeMask, &e); + visibility = e.xvisibility.state; + } + + // The top level window if fully visible + XWindowAttributes attributes; + XGetWindowAttributes(test_display, window, &attributes); + TEST_ASSERT_EQUAL_INT(VisibilityUnobscured, visibility); + TEST_ASSERT_EQUAL_INT(IsViewable, attributes.map_state); + + // Check the child structure is unaltered + Window root; + Window parent; + Window* children; + unsigned int children_count; + XQueryTree(test_display, child, &root, &parent, &children, &children_count); + + TEST_ASSERT_EQUAL(parent, window); + + XWindowAttributes child_attributes; + XGetWindowAttributes(test_display, child, &child_attributes); + + TEST_ASSERT_EQUAL_INT(0, child_attributes.x); + TEST_ASSERT_EQUAL_INT(0, child_attributes.y); + TEST_ASSERT_EQUAL_INT(25, child_attributes.width); + TEST_ASSERT_EQUAL_INT(30, child_attributes.height); + TEST_ASSERT_EQUAL_INT(0, child_attributes.border_width); + TEST_ASSERT_EQUAL_INT(IsViewable, child_attributes.map_state); +} + +void create_multiple_resizeable_top_level_window(void) { + XColor red; + red.red = MAX_COLOR; + XAllocColor(test_display, XDefaultColormap(test_display, DefaultScreen(test_display)), &red); + + const int N = 10; + Window windows[N]; + Window children[N]; + + for(auto i = 0; i < N; i++) { + XColor blue; + blue.blue = (i+1) * MAX_COLOR / N; + XAllocColor(test_display, XDefaultColormap(test_display, DefaultScreen(test_display)), &blue); + + windows[i] = XCreateSimpleWindow(test_display, test_root, + 10 /*x*/, 10 /*y*/, 128 /*w*/, 128 /*h*/, + 0 /*TODO: border width*/, CopyFromParent /*depth*/, blue.pixel /* background */); + // The top level windows might have children. Those must **not** be + // altered by the Window Manager + children[i] = XCreateSimpleWindow(test_display, windows[i], + 0, 0, 25, 30, + 0, CopyFromParent, red.pixel); + XSelectInput(test_display, windows[i], VisibilityChangeMask); + XMapWindow(test_display, children[i]); + XMapWindow(test_display, windows[i]); + } + + + clock_t user_time = clock(); + int visibility[N]; + while((clock() - user_time) < USER_DELAY * N) { + for(auto i = 0; i < N; i++) { + XEvent e; + XCheckWindowEvent(test_display, windows[i], VisibilityChangeMask, &e); + visibility[i] = e.xvisibility.state; + } + } + + for(auto i = 0; i < N; i++) { + // All top level windows must be fully visible + XWindowAttributes attributes; + XGetWindowAttributes(test_display, windows[i], &attributes); + TEST_ASSERT_EQUAL_INT(VisibilityUnobscured, visibility[i]); + TEST_ASSERT_EQUAL_INT(IsViewable, attributes.map_state); + + // Check the children structure is unaltered + Window _root; + Window parent; + Window* _children; + unsigned int _children_count; + XQueryTree(test_display, children[i], &_root, &parent, &_children, &_children_count); + + TEST_ASSERT_EQUAL(parent, windows[i]); + + XWindowAttributes child_attributes; + XGetWindowAttributes(test_display, children[i], &child_attributes); + + TEST_ASSERT_EQUAL_INT(0, child_attributes.x); + TEST_ASSERT_EQUAL_INT(0, child_attributes.y); + TEST_ASSERT_EQUAL_INT(25, child_attributes.width); + TEST_ASSERT_EQUAL_INT(30, child_attributes.height); + TEST_ASSERT_EQUAL_INT(0, child_attributes.border_width); + TEST_ASSERT_EQUAL_INT(IsViewable, child_attributes.map_state); + } +} + +// not needed when using generate_test_runner.rb +int main(void) { + UNITY_BEGIN(); + RUN_TEST(run_aswm); + RUN_TEST(create_single_resizeable_top_level_window); + RUN_TEST(create_multiple_resizeable_top_level_window); + return UNITY_END(); +} diff --git a/test/test_aswm.c b/test/test_set_up.c similarity index 69% rename from test/test_aswm.c rename to test/test_set_up.c index 54d3f37..e6aa1fc 100644 --- a/test/test_aswm.c +++ b/test/test_set_up.c @@ -1,19 +1,20 @@ -#include "unity.h" -#include "aswm/aswm.h" +#include "test_set_up.h" #include #include -#include #include #include -unsigned int display_count = 100; +// Extern definitions char display_name[5]; -char display_fd[128]; -int xephyr_pid; int aswm_pid; Display* test_display; Window test_root; +// Local variables +unsigned int display_count = 100; +char display_fd[128]; +int xephyr_pid; + void run_xephyr() { FILE* displayfd = fopen(display_fd, "w"); // Used to store the name of the // display on which Xephyr is @@ -88,45 +89,3 @@ void tearDown(void) { kill(xephyr_pid, SIGTERM); } -void run_aswm(void) { - int stat_loc; - // Ensures aswm is running - TEST_ASSERT_EQUAL_INT(0, waitpid(aswm_pid, &stat_loc, WNOHANG)); -} - -void create_default_top_level_window(void) { - Window window = XCreateSimpleWindow(test_display, test_root, - 10 /*x*/, 10 /*y*/, 128 /*w*/, 128 /*h*/, - 2 /*border width*/, CopyFromParent /*depth*/, 0xFF00FF00 /* background */); - XMapWindow(test_display, window); - XSelectInput(test_display, window, StructureNotifyMask | VisibilityNotify); - - bool mapped = false; - int visibility_received = false; - int visibility; - while(!mapped && !visibility_received) { - XEvent e; - XNextEvent(test_display, &e); - - switch(e.type) { - case MapNotify: - mapped = true; - break; - case VisibilityNotify: - visibility_received = true; - visibility = e.xvisibility.state; - break; - default: - } - } - - TEST_ASSERT_EQUAL_INT(VisibilityUnobscured, visibility); -} - -// not needed when using generate_test_runner.rb -int main(void) { - UNITY_BEGIN(); - RUN_TEST(run_aswm); - RUN_TEST(create_default_top_level_window); - return UNITY_END(); -} diff --git a/test/test_set_up.h b/test/test_set_up.h new file mode 100644 index 0000000..1d61493 --- /dev/null +++ b/test/test_set_up.h @@ -0,0 +1,14 @@ +#ifndef ASWM_TEST_SET_UP +#define ASWM_TEST_SET_UP + +#include "unity.h" +#include "X11/Xlib.h" + +// Extern variables accessible from any test. +// Defined in test_set_up.c +extern char display_name[5]; +extern int aswm_pid; +extern Display* test_display; +extern Window test_root; + +#endif