========================================= DSLR Camera Control Bot - Test Suite ========================================= Started: 2026-05-01 13:37:21 UTC --- Configuration Tests (test_config.php) --- PASS: config.php exists PASS: SSH_USERNAME defined PASS: SSH_PASSWORD defined PASS: SUDO_PASSWORD defined PASS: SSH_PORT defined PASS: SSH_USERNAME not empty PASS: SSH_PASSWORD not empty PASS: SSH_PORT is numeric PASS: ENDPOINT_CAPTURE defined PASS: ENDPOINT_SETTINGS defined PASS: ENDPOINT_ERRORS defined PASS: ENDPOINT_TEST_RELAY defined PASS: ENDPOINT_TEST_STORAGE defined PASS: ENDPOINT_CAPTURE is valid URL PASS: ENDPOINT_SETTINGS is valid URL PASS: ENDPOINT_ERRORS is valid URL PASS: DISPLAY_ERRORS defined PASS: DISPLAY_ERRORS is boolean PASS: validateIPAddress function exists PASS: validateIPAddress: valid IP 192.168.1.1 PASS: validateIPAddress: valid IP 10.0.0.1 PASS: validateIPAddress: invalid IP "not_an_ip" PASS: validateIPAddress: invalid IP empty string PASS: validateIPAddress: invalid IP "192.168" PASS: validateIPAddress: valid IP 255.255.255.255 PASS: sanitizeShellParam function exists PASS: sanitizeShellParam: alphanumeric passthrough PASS: sanitizeShellParam: removes special chars PASS: sanitizeShellParam: allows dots PASS: sanitizeShellParam: allows dashes PASS: sanitizeShellParam: allows underscores PASS: sanitizeShellParam: removes backticks PASS: sanitizeShellParam: removes dollar signs PASS: DEBUG_LOG_KEY defined PASS: DEBUG_LOG_KEY is not empty PASS: DEBUG_LOG_MAX_SIZE defined PASS: DEBUG_LOG_MAX_SIZE is positive PASS: DEBUG_LOG_MAX_SIZE is at least 1MB Result: 38 passed, 0 failed --- Shared Functions Tests (test_functions.php) --- PASS: logChatError function exists PASS: validateJsonResponse function exists PASS: validateJsonResponse: valid array PASS: validateJsonResponse: valid nested array PASS: validateJsonResponse: empty array PASS: validateJsonResponse: valid string value PASS: logChatError writes to file PASS: logChatError log contains context PASS: logChatError log contains message PASS: sendJsonResponse function exists PASS: safeJsonResponse function exists PASS: Test log file created PASS: Test log file has content Result: 13 passed, 0 failed --- Lock System Tests (test_lock_system.php) --- PASS: acquireLock function exists PASS: releaseLock function exists PASS: isLocked function exists PASS: cleanupExpiredLocks function exists PASS: getLockMessage function exists PASS: acquireLock returns true on first acquire PASS: isLocked returns true for active lock PASS: acquireLock returns false when already locked PASS: releaseLock returns true PASS: isLocked returns false after release PASS: acquireLock succeeds after release PASS: getLockMessage capture PASS: getLockMessage settings PASS: getLockMessage errors PASS: getLockMessage test_relay PASS: getLockMessage unknown returns default PASS: cleanupExpiredLocks cleans expired locks PASS: Expired lock file removed PASS: releaseLock on non-existent lock returns true Result: 19 passed, 0 failed --- Space Database Tests (test_space_database.php) --- PASS: getSpaceCamera function exists PASS: setSpaceCamera function exists PASS: spaceHasCamera function exists PASS: getSpaceCameraIP function exists PASS: getSpaceCameraName function exists PASS: setSpaceCameraName function exists PASS: sanitizeSpaceId function exists PASS: sanitizeSpaceId removes spaces/ prefix PASS: sanitizeSpaceId handles no prefix PASS: sanitizeSpaceId removes special characters PASS: spaceHasCamera returns false for unset space PASS: getSpaceCamera returns null for unset space PASS: setSpaceCamera returns true PASS: spaceHasCamera returns true after set PASS: getSpaceCamera returns correct VPN PASS: getSpaceCameraIP returns full IP PASS: getSpaceCameraIP is valid IP PASS: setSpaceCameraName returns true PASS: getSpaceCameraName returns correct name PASS: getSpaceCameraIP returns null for no camera PASS: Test cleanup successful Result: 21 passed, 0 failed --- Camera List Tests (test_camera_list.php) --- PASS: formatCameraName function exists PASS: formatCameraName removes tlc_ prefix PASS: formatCameraName multi-part formatting PASS: formatCameraName preserves project code uppercase PASS: formatCameraName handles numbered parts PASS: formatCameraName single part PASS: filterCameras function exists PASS: filterCameras empty search returns all PASS: filterCameras search by client PASS: filterCameras search by project code PASS: filterCameras no match returns empty PASS: getCameraList function exists PASS: getCameraList returns array Result: 13 passed, 0 failed ========================================= SUMMARY ========================================= Total: 104 tests Passed: 104 Failed: 0 Pass Rate: 100% Completed: 2026-05-01 13:37:21 UTC