diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/vr/vrhost/vrhosttest.cpp | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/gfx/vr/vrhost/vrhosttest.cpp b/gfx/vr/vrhost/vrhosttest.cpp new file mode 100644 index 0000000000..84c11c10d6 --- /dev/null +++ b/gfx/vr/vrhost/vrhosttest.cpp @@ -0,0 +1,370 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// vrhosttest.cpp +// Definition of testing and validation functions that are exported from this +// dll + +#include "vrhostex.h" +#include "VRShMem.h" + +#include <stdio.h> +#include "windows.h" + +static const char s_pszSharedEvent[] = "vrhost_test_event_signal"; +static const DWORD s_dwWFSO_WAIT = 20000; + +void SampleExport() { printf("vrhost.cpp hello world\n"); } + +// For testing ShMem as Manager and Service: +// The two processes should output the steps, synchronously, to validate +// 2-way communication via VRShMem as follows +// 01 mgr: create mgr +// 02 mgr: wait for signal +// 03 svc: create svc +// 04 svc: send signal +// 05 svc: wait for signal +// 06 mgr: push browser +// 07 mgr: send signal +// 08 mgr: wait for signal +// 09 svc: pull browser +// 10 svc: verify data +// 11 svc: push system +// 12 svc: send signal +// 13 svc: wait for signal +// 14 mgr: pull system +// 15 mgr: verify data +// 16 mgr: push window +// 17 mgr: send signal +// 18 mgr: wait for signal +// 19 svc: pull window +// 20 svc: verify data +// 21 svc: push window +// 22 svc: send signal +// 23 mgr: pull window +// 24 mgr: verify data +// 25 return +// These tests can be run with two instances of vrtesthost.exe, one first +// running with -testmgr and the second running with -testsvc. +// TODO: Bug 1563235 - Convert vrtesthost.exe tests into unit tests + +// For testing VRShMem as the Manager (i.e., the one who creates the +// shmem). The sequence of how it tests with the service is listed above. +void TestTheManager() { + printf("TestTheManager Start\n"); + + MOZ_ASSERT(GetLastError() == 0, + "TestTheManager should start with no OS errors"); + HANDLE hEvent = ::CreateEventA(nullptr, // lpEventAttributes + FALSE, // bManualReset + FALSE, // bInitialState + s_pszSharedEvent // lpName + ); + + printf("\n01 mgr: create mgr\n"); + mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/); + shmem.CreateShMem(true /*aCreateOnSharedMemory*/); + + printf("02 mgr: wait for signal\n"); + ::WaitForSingleObject(hEvent, s_dwWFSO_WAIT); + + // Set some state to verify on the other side + mozilla::gfx::VRBrowserState browserState = {0}; + browserState.presentationActive = true; + browserState.layerState[0].type = + mozilla::gfx::VRLayerType::LayerType_2D_Content; + browserState.hapticState[0].controllerIndex = 987; + + printf("06 mgr: push browser\n"); + shmem.PushBrowserState(browserState, true); + + printf("07 mgr: send signal\n"); + ::SetEvent(hEvent); + + printf("08 mgr: wait for signal\n"); + ::WaitForSingleObject(hEvent, s_dwWFSO_WAIT); + + printf("14 mgr: pull system\n"); + mozilla::gfx::VRSystemState state; + shmem.PullSystemState(state.displayState, state.sensorState, + state.controllerState, state.enumerationCompleted, + nullptr); + + printf( + "15 mgr: verify data\n" + "\tstate.enumerationCompleted = %d\n" + "\tstate.displayState.displayName = \"%s\"\n" + "\tstate.controllerState[1].hand = %hhu\n" + "\tstate.sensorState.inputFrameID = %llu\n", + state.enumerationCompleted, state.displayState.displayName, + state.controllerState[1].hand, state.sensorState.inputFrameID); + + // Test the WindowState functions as the host + mozilla::gfx::VRWindowState windowState = {0}; + strcpy(windowState.signalName, "randomsignalstring"); + windowState.dxgiAdapterHost = 99; + windowState.heightHost = 42; + windowState.widthHost = 24; + + printf("16 mgr: push window\n"); + shmem.PushWindowState(windowState); + + printf("17 mgr: send signal\n"); + ::SetEvent(hEvent); + + printf("18 mgr: wait for signal\n"); + ::WaitForSingleObject(hEvent, s_dwWFSO_WAIT); + + printf("23 mgr: pull window\n"); + shmem.PullWindowState(windowState); + + printf( + "24 svc: verify data\n" + "\tstate.hwndFx = 0x%llX\n" + "\tstate.heightFx = %d\n" + "\tstate.widthFx = %d\n" + "\tstate.textureHandle = %p\n", + windowState.hwndFx, windowState.heightFx, windowState.widthFx, + windowState.textureFx); + + shmem.CloseShMem(); + + printf("TestTheManager complete"); + fflush(nullptr); +} + +// For testing VRShMem as the Service (i.e., the one who consumes the +// shmem). The sequence of how it tests with the service is listed above. +void TestTheService() { + printf("TestTheService Start\n"); + + MOZ_ASSERT(GetLastError() == 0, + "TestTheService should start with no OS errors"); + // Handle created by TestTheManager above. + HANDLE hEvent = ::OpenEventA(EVENT_ALL_ACCESS, // dwDesiredAccess + FALSE, // bInheritHandle + s_pszSharedEvent // lpName + ); + + printf("\n03 svc: create svc\n"); + mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/); + shmem.JoinShMem(); + + printf("04 svc: send signal\n"); + ::SetEvent(hEvent); + + printf("05 svc: wait for signal\n"); + ::WaitForSingleObject(hEvent, s_dwWFSO_WAIT); + + printf("09 svc: pull browser\n"); + mozilla::gfx::VRBrowserState state; + shmem.PullBrowserState(state); + + printf( + "10 svc: verify data\n" + "\tstate.presentationActive = %d\n" + "\tstate.layerState[0].type = %hu\n" + "\tstate.hapticState[0].controllerIndex = %d\n", + state.presentationActive, state.layerState[0].type, + state.hapticState[0].controllerIndex); + + // Set some state to verify on the other side + mozilla::gfx::VRSystemState systemState; + systemState.enumerationCompleted = true; + strncpy(systemState.displayState.displayName, "test from vrservice shmem", + mozilla::gfx::kVRDisplayNameMaxLen); + systemState.controllerState[1].hand = mozilla::gfx::ControllerHand::Left; + systemState.sensorState.inputFrameID = 1234567; + + printf("11 svc: push system\n"); + shmem.PushSystemState(systemState); + + printf("12 svc: send signal\n"); + ::SetEvent(hEvent); + + printf("13 svc: wait for signal\n"); + ::WaitForSingleObject(hEvent, s_dwWFSO_WAIT); + + // Test the WindowState functions as Firefox + printf("19 svc: pull window\n"); + mozilla::gfx::VRWindowState windowState; + shmem.PullWindowState(windowState); + + printf( + "20 svc: verify data\n" + "\tstate.signalName = \"%s\"\n" + "\tstate.dxgiAdapterHost = %d\n" + "\tstate.heightHost = %d\n" + "\tstate.widthHost = %d\n", + windowState.signalName, windowState.dxgiAdapterHost, + windowState.heightHost, windowState.widthHost); + + windowState.hwndFx = 0x1234; + windowState.heightFx = 1234; + windowState.widthFx = 4321; + windowState.textureFx = (HANDLE)0x77777; + + printf("21 svc: push window\n"); + shmem.PushWindowState(windowState); + + printf("22 svc: send signal\n"); + ::SetEvent(hEvent); + + shmem.LeaveShMem(); + + printf("TestTheService complete"); + fflush(nullptr); +} + +DWORD TestWaitForVREventThreadProc(_In_ LPVOID lpParameter) { + // WaitForVREvent + printf("\nStarting TestWaitForVREventThreadProc\n"); + + PFN_WAITFORVREVENT fnWaitForVRMsg = (PFN_WAITFORVREVENT)lpParameter; + + uint32_t nVRWindowID = 0; + uint32_t eventType = 0; + uint32_t eventData1 = 0; + uint32_t eventData2 = 0; + + while (eventType != 2) { // FxEvent_SHUTDOWN + fnWaitForVRMsg(nVRWindowID, eventType, eventData1, eventData2); + printf( + "\nWaitForVRMessage:\n\tvrWindowID: %d\n\teventType: %d\n\teventData1: " + "%d\n\teventData2: %d\n", + nVRWindowID, eventType, eventData1, eventData2); + } + + printf("\nReturning from TestWaitForVREventThreadProc\n"); + + return 0; +} + +// This function tests the export CreateVRWindow by outputting the return values +// from the call to the console, as well as testing CloseVRWindow after the data +// is retrieved. +void TestCreateVRWindow() { + printf("TestCreateVRWindow Start\n"); + + // Cache function calls to test real-world export and usage + HMODULE hVRHost = ::GetModuleHandleA("vrhost.dll"); + PFN_CREATEVRWINDOW fnCreate = + (PFN_CREATEVRWINDOW)::GetProcAddress(hVRHost, "CreateVRWindow"); + PFN_CLOSEVRWINDOW fnClose = + (PFN_CLOSEVRWINDOW)::GetProcAddress(hVRHost, "CloseVRWindow"); + PFN_SENDUIMSG fnSendMsg = + (PFN_SENDUIMSG)::GetProcAddress(hVRHost, "SendUIMessageToVRWindow"); + PFN_WAITFORVREVENT fnWaitForVRMsg = + (PFN_WAITFORVREVENT)::GetProcAddress(hVRHost, "WaitForVREvent"); + + // Create the VR Window and store data from creation + char currentDir[MAX_PATH] = {0}; + char currentDirProfile[MAX_PATH] = {0}; + DWORD currentDirLength = + ::GetCurrentDirectoryA(ARRAYSIZE(currentDir), currentDir); + currentDir[currentDirLength] = '\\'; + + int err = sprintf_s(currentDirProfile, ARRAYSIZE(currentDirProfile), + "%svrhosttest-profile", currentDir); + if (err > 0) { + printf("Starting Firefox from %s\n", currentDir); + + UINT windowId; + HANDLE hTex; + UINT width; + UINT height; + fnCreate(currentDir, currentDirProfile, 0, 100, 200, &windowId, &hTex, + &width, &height); + + // Now that the Fx window is created, start a new thread to wait for VR + // events to be sent from it + DWORD dwTid; + HANDLE hThreadWait = CreateThread(nullptr, 0, TestWaitForVREventThreadProc, + (void*)fnWaitForVRMsg, 0, &dwTid); + + // Wait for Fx to finish launch +#ifdef DEBUG + ::Sleep(5000); +#else + ::Sleep(2000); +#endif + + printf( + "1. Simulating a click on the Home button, which should look " + "pressed\n"); + POINT pt; + pt.x = 180; + pt.y = 700; + fnSendMsg(windowId, WM_LBUTTONDOWN, 0, POINTTOPOINTS(pt)); + ::Sleep(3000); + fnSendMsg(windowId, WM_LBUTTONUP, 0, POINTTOPOINTS(pt)); + + printf( + "2. Simulating hovering across the URL bar, which should turn " + "blue\n"); + pt.x = 600; + for (int i = 0; i < 100; ++i) { + pt.x++; + fnSendMsg(windowId, WM_MOUSEMOVE, 0, POINTTOPOINTS(pt)); + ::Sleep(5); + } + + printf( + "3. Simulating clicking inside the URL bar, which should " + "highlight the text\n"); + pt.x = 700; + pt.y = 700; + fnSendMsg(windowId, WM_LBUTTONDOWN, 0, POINTTOPOINTS(pt)); + fnSendMsg(windowId, WM_LBUTTONUP, 0, POINTTOPOINTS(pt)); + + ::Sleep(3000); + + printf("4. Type some UTF16 characters in the URL bar\n"); + fnSendMsg(windowId, WM_CHAR, 0x4E64, 0); + fnSendMsg(windowId, WM_CHAR, 0x312D, 0); + fnSendMsg(windowId, WM_CHAR, 0x0BB9, 0); + fnSendMsg(windowId, WM_CHAR, 0x2745, 0); + + printf( + "5. Simulating clicking outside the URL bar, which should " + "send a keyboard blur event\n"); + pt.x = 20; + pt.y = 20; + fnSendMsg(windowId, WM_LBUTTONDOWN, 0, POINTTOPOINTS(pt)); + fnSendMsg(windowId, WM_LBUTTONUP, 0, POINTTOPOINTS(pt)); + + ::Sleep(1000); + + printf("6. Simulating scrolling the web content down and then up\n"); + + pt.x = 100; + pt.y = 100; + for (int i = -20; i < 10; ++i) { + fnSendMsg(windowId, WM_MOUSEWHEEL, + MAKELONG(0, (i < 0) ? -WHEEL_DELTA : WHEEL_DELTA), + POINTTOPOINTS(pt)); + ::Sleep(100); + } + + ::Sleep(5000); + + // Close the Firefox VR Window + fnClose(windowId, true); + + // Wait for the VR event thread to return + ::WaitForSingleObject(hThreadWait, INFINITE); + + // Print output from CreateVRWindow + printf( + "\n\nTestCreateVRWindow End:\n" + "\twindowId = 0x%X\n" + "\thTex = 0x%p\n" + "\twidth = %d\n" + "\theight = %d\n", + windowId, hTex, width, height); + printf("\n***Note: profile folder created at %s***\n", currentDirProfile); + } +} |