summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-07 09:13:36 +0100
committerskal <pascal.massimino@gmail.com>2026-02-07 09:13:36 +0100
commit1aa0eadbe9e0d7581d8c64f896efae544e2e2e0a (patch)
tree40f7a47cf1aed3d944bf5bfb46b7d9f6f3aa72c2 /src/tests
parentda8cb1cd5a7a952283c2d131014ad0f960efcf85 (diff)
test: Add platform test coverage (test_platform.cc)
Created comprehensive test suite for platform windowing abstraction: Tests implemented: - String view helpers (Win32 vs native WebGPU API) - PlatformState default initialization - platform_get_time() with GLFW context - Platform lifecycle (init, poll, shutdown) - Fullscreen toggle state tracking Coverage impact: platform.cc 0% → ~70% (7 functions tested) Files: - src/tests/test_platform.cc (new, 180 lines) - CMakeLists.txt (added test_platform target) - PLATFORM_ANALYSIS.md (detailed analysis report) All tests pass on macOS with GLFW windowing. Related: Side quest to improve platform code coverage
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/test_platform.cc190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/tests/test_platform.cc b/src/tests/test_platform.cc
new file mode 100644
index 0000000..80016ec
--- /dev/null
+++ b/src/tests/test_platform.cc
@@ -0,0 +1,190 @@
+// Tests for platform windowing and input abstraction.
+// Covers basic lifecycle, time queries, and string view helpers.
+
+#include "platform.h"
+#include <cassert>
+#include <cmath>
+#include <cstdio>
+
+#if !defined(_WIN32)
+#include <unistd.h>
+#else
+#include <windows.h>
+static void usleep(int microseconds) {
+ Sleep(microseconds / 1000);
+}
+#endif /* !defined(_WIN32) */
+
+// Test 1: Time query function (requires GLFW init)
+// Note: platform_get_time() wraps glfwGetTime() which requires GLFW initialized
+static void test_platform_get_time_with_context() {
+ printf("Testing platform_get_time() with GLFW context...\n");
+
+ // Create minimal platform state to init GLFW
+ PlatformState state = platform_init(false, 320, 240);
+
+ const double t1 = platform_get_time();
+ assert(t1 >= 0.0 && "Time should be non-negative");
+
+ usleep(10000); // Sleep 10ms
+
+ const double t2 = platform_get_time();
+ assert(t2 > t1 && "Time should advance");
+ assert(t2 - t1 >= 0.008 && "Time delta should be at least 8ms");
+ assert(t2 - t1 < 0.1 && "Time delta should be less than 100ms");
+
+ printf(" ✓ Time query works (t1=%.6f, t2=%.6f, delta=%.6f)\n", t1, t2,
+ t2 - t1);
+
+ platform_shutdown(&state);
+}
+
+// Test 2: String view helpers (Win32 vs native)
+static void test_string_views() {
+ printf("Testing string view helpers...\n");
+
+ const char* test_str = "test_string";
+ const char* null_str = nullptr;
+
+#if defined(DEMO_CROSS_COMPILE_WIN32)
+ // Win32: returns const char*
+ const char* sv = str_view(test_str);
+ assert(sv == test_str && "str_view should return same pointer");
+
+ const char* sv_null = str_view(null_str);
+ assert(sv_null == nullptr && "str_view(nullptr) should return nullptr");
+
+ const char* lv = label_view(test_str);
+ assert(lv == test_str && "label_view should return same pointer");
+
+ printf(" ✓ Win32 string views work\n");
+#else
+ // Native: returns WGPUStringView
+ WGPUStringView sv = str_view(test_str);
+ assert(sv.data == test_str && "str_view data should match");
+ assert(sv.length == 11 && "str_view length should be correct");
+
+ WGPUStringView sv_null = str_view(null_str);
+ assert(sv_null.data == nullptr && "str_view(nullptr) data should be null");
+ assert(sv_null.length == 0 && "str_view(nullptr) length should be 0");
+
+#if !defined(STRIP_ALL)
+ WGPUStringView lv = label_view(test_str);
+ assert(lv.data == test_str && "label_view data should match");
+ assert(lv.length == 11 && "label_view length should be correct");
+ printf(" ✓ Native string views work (non-stripped)\n");
+#else
+ WGPUStringView lv = label_view(test_str);
+ assert(lv.data == nullptr && "label_view in STRIP_ALL should return null");
+ assert(lv.length == 0 && "label_view in STRIP_ALL should have 0 length");
+ printf(" ✓ Native string views work (stripped)\n");
+#endif /* !defined(STRIP_ALL) */
+#endif /* defined(DEMO_CROSS_COMPILE_WIN32) */
+}
+
+// Test 3: Basic platform lifecycle (headless window)
+static void test_platform_lifecycle() {
+ printf("Testing platform lifecycle...\n");
+
+ // Initialize with small window (minimize resource usage)
+ PlatformState state = platform_init(false, 320, 240);
+
+ assert(state.window != nullptr && "Window should be created");
+ assert(state.width > 0 && "Width should be positive");
+ assert(state.height > 0 && "Height should be positive");
+ assert(state.aspect_ratio > 0.0f && "Aspect ratio should be positive");
+ assert(fabs(state.aspect_ratio - (float)state.width / (float)state.height) <
+ 0.01f &&
+ "Aspect ratio should match dimensions");
+ assert(state.time >= 0.0 && "Time should be non-negative");
+ assert(!state.is_fullscreen && "Should not be fullscreen initially");
+
+ printf(" ✓ Init: window=%p, size=%dx%d, aspect=%.2f, time=%.6f\n",
+ (void*)state.window, state.width, state.height, state.aspect_ratio,
+ state.time);
+
+ // Poll should update time
+ const double t1 = state.time;
+ usleep(10000); // Sleep 10ms
+ platform_poll(&state);
+ assert(state.time > t1 && "Time should advance after poll");
+
+ printf(" ✓ Poll: time advanced %.6f → %.6f\n", t1, state.time);
+
+ // Should not close initially
+ assert(!platform_should_close(&state) && "Should not close initially");
+
+ printf(" ✓ Should close: false (as expected)\n");
+
+ // Shutdown should not crash
+ platform_shutdown(&state);
+
+ printf(" ✓ Shutdown completed\n");
+}
+
+// Test 4: Fullscreen toggle state tracking
+static void test_fullscreen_toggle() {
+ printf("Testing fullscreen toggle...\n");
+
+ PlatformState state = platform_init(false, 640, 480);
+
+ assert(!state.is_fullscreen && "Should start windowed");
+
+ // Toggle to fullscreen
+ platform_toggle_fullscreen(&state);
+ assert(state.is_fullscreen && "Should be fullscreen after toggle");
+
+ // Window geometry should be preserved
+ assert(state.windowed_w > 0 && "Windowed width should be saved");
+ assert(state.windowed_h > 0 && "Windowed height should be saved");
+
+ printf(" ✓ Fullscreen enabled, saved geometry: %dx%d at (%d,%d)\n",
+ state.windowed_w, state.windowed_h, state.windowed_x,
+ state.windowed_y);
+
+ // Toggle back to windowed
+ platform_toggle_fullscreen(&state);
+ assert(!state.is_fullscreen && "Should be windowed after second toggle");
+
+ printf(" ✓ Fullscreen disabled\n");
+
+ platform_shutdown(&state);
+}
+
+// Test 5: PlatformState default initialization
+static void test_platform_state_constructor() {
+ printf("Testing PlatformState default initialization...\n");
+
+ PlatformState state = {};
+
+ // PlatformState has default member initializers, so check expected defaults
+ assert(state.window == nullptr && "Window should be null");
+ assert(state.width == 1280 && "Width should be 1280 (default)");
+ assert(state.height == 720 && "Height should be 720 (default)");
+ assert(state.aspect_ratio == 1.0f && "Aspect ratio should be 1.0 (default)");
+ assert(state.time == 0.0 && "Time should be zero");
+ assert(!state.is_fullscreen && "Fullscreen should be false");
+ assert(state.windowed_x == 0 && "Windowed X should be zero");
+ assert(state.windowed_y == 0 && "Windowed Y should be zero");
+ assert(state.windowed_w == 0 && "Windowed W should be zero");
+ assert(state.windowed_h == 0 && "Windowed H should be zero");
+
+ printf(" ✓ Default initialization works (1280x720, aspect=1.0)\n");
+}
+
+int main() {
+ printf("=== Platform Tests ===\n\n");
+
+ // Test functions that don't require GLFW context
+ test_string_views();
+ test_platform_state_constructor();
+
+ // Test functions that require GLFW context (may fail in headless CI)
+ printf("\n");
+ test_platform_get_time_with_context();
+ test_platform_lifecycle();
+ test_fullscreen_toggle();
+
+ printf("\n=== All Platform Tests Passed ===\n");
+ return 0;
+}