//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: task.cpp // // Contents: The global task list and helper function implementations // // Classes: // // Functions: HandleTestEnd // RunAllTests // RunApp // RunTestOnThread // // History: dd-mmm-yy Author Comment // 06-Jan-95 t-scotth added apartment thread test and RunTestOnThread // 06-Feb-94 alexgo author // // Notes: // Folks adding new tests will need to insert their test // into the global array. // //-------------------------------------------------------------------------- #include "oletest.h" #include "cotest.h" #include "letest.h" #include "attest.h" // global, zero'ed task item TaskItem vzTaskItem; // the global task list array. // Multi-test entries go first, followed by individual tests. #ifdef WIN32 const TaskItem vrgTaskList[] = { // the constant should be the index at which individual tests // begin. RunAllTests will run every test in this list after // that index. { "Run All Tests", RunAllTests, (void *)2}, // the constant below should be the index at which individual // upper layer unit tests exist. All tests at that index and // beyond will be run { "Run All Upper Layer Tests", RunAllTests, (void *)5 }, { "OleBind", RunApp, (void *)"olebind.exe"}, { "Threads", RunApi, (void *) ThreadUnitTest }, { "Storage DRT", RunApp, (void *)"stgdrt.exe"}, { "LE: Insert Object Test 1", LETest1, &letiInsertObjectTest1 }, { "LE: Clipboard Test 1", RunApi, (void *)LEClipTest1}, { "LE: Clipboard Test 2 (clipboard data object)", RunApi, (void *)LEClipTest2 }, { "LE: Inplace Test 1", LETest1, &letiInplaceTest1 }, { "LE: Data Advise Holder Test", RunApi, (void *) LEDataAdviseHolderTest}, { "LE: OLE Advise Holder Test", RunApi, (void *) LEOleAdviseHolderTest}, { "LE: OLE1 Clipboard Test 1", RunApi, (void *)LEOle1ClipTest1}, { "LE: Insert Object Test 2", LETest1, &letiInsertObjectTest2 }, { "LE: OLE1 Clipboard Test 2", LEOle1ClipTest2, NULL }, { "LE: OleQueryCreateFromData Test 1", RunApi, (void *)TestOleQueryCreateFromDataMFCHack }, { "LE: Apartment Thread Test", RunTestOnThread, (void *)ATTest }, { 0, 0, 0 } }; #else // Win16 tests const TaskItem vrgTaskList[] = { // the constant should be the index at which individual tests // begin. RunAllTests will run every test in this list after // that index. { "Run All Tests", RunAllTests, (void *)1}, { "LE: Clipboard Test 1", RunApi, (void *)LEClipTest1}, { "LE: Clipboard Test 2 (clipboard data object)", RunApi, (void *)LEClipTest2 }, { "LE: OLE1 Clipboard Test 1", RunApi, (void *)LEOle1ClipTest1}, { 0, 0, 0 } }; #endif //+------------------------------------------------------------------------- // // Function: HandleTestEnd // // Synopsis: Handles processing for the WM_TESTEND message. // // Effects: // // Arguments: void // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: execute the next task in the task stack or sends // a TESTSCOMPLETED message back the message queue // // History: dd-mmm-yy Author Comment // 06-Feb-94 alexgo author // 13-Dec-94 MikeW Allow testing to continue after failures // // Notes: vApp must be initialized correctly for this function to // work properly. // // BUGBUG::Need to add output routines in here. // //-------------------------------------------------------------------------- void HandleTestEnd( void ) { assert(vApp.m_message == WM_TESTEND); switch( vApp.m_wparam ) { case TEST_UNKNOWN: //we usually get this message from a test run //by RunApp (i.e. one that does not communicate //with us via windows messages). We'll check //the exit code and decide what to do. if( vApp.m_lparam != 0 ) { //presumably an error OutputString("Test End, Status Unknown " "( %lx )\r\n\r\n", vApp.m_lparam); vApp.m_fGotErrors = TRUE; break; } // otherwise we fall through to the success case. case TEST_SUCCESS: OutputString("Test Success ( %lx )!\r\n\r\n", vApp.m_lparam); break; case TEST_FAILURE: OutputString("Test FAILED! ( %lx )\r\n\r\n", vApp.m_lparam); vApp.m_fGotErrors = TRUE; break; default: assert(0); //we should never get here break; } vApp.Reset(); // // Now check to see if there are any more tests // while (!vApp.m_TaskStack.IsEmpty()) { TaskItem ti; vApp.m_TaskStack.Pop(&ti); if (ti.szName != (LPSTR) 0) { vApp.m_TaskStack.Push(&ti); break; } } if (vApp.m_TaskStack.IsEmpty()) { PostMessage(vApp.m_hwndMain, WM_TESTSCOMPLETED, vApp.m_wparam, vApp.m_lparam); } else { //if the stack is not empty, run //the next task PostMessage(vApp.m_hwndMain, WM_TESTSTART, 0, 0); } return; } //+------------------------------------------------------------------------- // // Function: HandleTestsCompleted // // Synopsis: Handles processing for the WM_TESTSCOMPLETED message. // // Effects: // // Arguments: void // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 06-Feb-94 alexgo author // // Notes: vApp must be initialized correctly for this function to // work properly. // // BUGBUG::Need to add more output routines in here. // //-------------------------------------------------------------------------- void HandleTestsCompleted( void ) { char szBuf[128]; assert(vApp.m_message == WM_TESTSCOMPLETED); //temporary output switch(vApp.m_fGotErrors) { case FALSE: OutputString("Tests PASSED!!\n"); break; case TRUE: sprintf(szBuf, "Tests FAILED, code %lx", vApp.m_lparam); MessageBox(vApp.m_hwndMain, szBuf, "Ole Test Driver", MB_ICONEXCLAMATION | MB_OK); break; default: assert(0); } // // Reset the got error status // vApp.m_fGotErrors = FALSE; return; } //+------------------------------------------------------------------------- // // Function: RunAllTests // // Synopsis: Runs all the individual tests in the global list // // Effects: // // Arguments: pvArg -- the index at which individual tests // start in the global list. // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 06-Feb-94 alexgo author // // Notes: // Tests will be run in the order they appear in the global // list. // //-------------------------------------------------------------------------- void RunAllTests( void *pvArg ) { ULONG index = (ULONG)pvArg; ULONG i; //find the number of tasks in the list (so we can push //them in reverse order). for (i = 0; vrgTaskList[i].szName != 0; i++ ) { ; } assert( i > 1 ); //now push the tasks onto the stack in reverse order. for (i--; i >= index; i-- ) { vApp.m_TaskStack.Push(vrgTaskList + i); } //start the first one. vApp.m_TaskStack.PopAndExecute(NULL); return; } //+------------------------------------------------------------------------- // // Function: RunApi // // Synopsis: Runs the specified Api // // Effects: // // Arguments: [pvArg] -- the api to run // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 23-Mar-94 alexgo author // // Notes: // //-------------------------------------------------------------------------- void RunApi( void *pvArg ) { HRESULT hresult; hresult = (*((HRESULT (*)(void))pvArg))(); vApp.Reset(); vApp.m_wparam = (hresult == NOERROR) ? TEST_SUCCESS : TEST_FAILURE; vApp.m_lparam = (LPARAM)hresult; vApp.m_message = WM_TESTEND; HandleTestEnd(); } //+------------------------------------------------------------------------- // // Function: RunApp // // Synopsis: Runs the app specified in the argument // // Effects: // // Arguments: pvArg -- a string with the app to execute // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: Create the process and wait for it to finish. The exit // status is then returned. // // History: dd-mmm-yy Author Comment // 06-Feb-94 alexgo author // // Notes: // //-------------------------------------------------------------------------- void RunApp( void *pvArg ) { WPARAM wparam = 0; DWORD error = 0; #ifdef WIN32 PROCESS_INFORMATION procinfo; static STARTUPINFO startinfo; //to make it all zero assert(pvArg); //should be a valid ANSI string. startinfo.cb = sizeof(startinfo); if( CreateProcess(NULL, (LPTSTR)pvArg, NULL, NULL, NULL, NULL, NULL, NULL, &startinfo, &procinfo) ) { //the process started, now wait for it to finish. WaitForSingleObject(procinfo.hProcess, INFINITE); //now get the return code of the process. GetExitCodeProcess(procinfo.hProcess, &error); wparam = TEST_UNKNOWN; } else { wparam = TEST_FAILURE; error = GetLastError(); } #endif // WIN32 // since there will be no WM_TESTEND message, we must do the // test end processing ourselves. vApp.Reset(); vApp.m_wparam = wparam; vApp.m_lparam = error; vApp.m_message = WM_TESTEND; HandleTestEnd(); return; } //+------------------------------------------------------------------------- // // Function: RunTestOnThread // // Synopsis: creates a thread to run a test function // // Effects: creates a new thread // // Arguments: [pvArg] -- a function pointer to the test function // // Requires: // // Returns: void // // Signals: // // Modifies: // // Algorithm: // // History: dd-mmm-yy Author Comment // 04-Jan-95 t-ScottH author // // Notes: // //-------------------------------------------------------------------------- void RunTestOnThread(void *pvArg) { HANDLE hMainTestThread; DWORD dwThreadId = 0; hMainTestThread = CreateThread( NULL, // security attributes 0, // stack size (default) (LPTHREAD_START_ROUTINE)pvArg, // address of thread function NULL, // arguments of thread function 0, // creation flags &dwThreadId ); // address of new thread ID assert(hMainTestThread); CloseHandle(hMainTestThread); return; }