qtestcase.cpp
来自「奇趣公司比较新的qt/emd版本」· C++ 代码 · 共 1,706 行 · 第 1/4 页
CPP
1,706 行
printf(" Usage: %s [options] [testfunctions[:testdata]]...\n" " By default, all testfunction will be run.\n\n" "%s", argv[0], testOptions); exit(0); } else if (strcmp(argv[i], "-functions") == 0) { qPrintTestSlots(); exit(0); } else if (strcmp(argv[i], "-xml") == 0) { QTestLog::setLogMode(QTestLog::XML); } else if (strcmp(argv[i], "-lightxml") == 0) { QTestLog::setLogMode(QTestLog::LightXML); } else if (strcmp(argv[i], "-silent") == 0) { QTestLog::setVerboseLevel(-1); } else if (strcmp(argv[i], "-v1") == 0) { QTestLog::setVerboseLevel(1); } else if (strcmp(argv[i], "-v2") == 0) { QTestLog::setVerboseLevel(2); } else if (strcmp(argv[i], "-vs") == 0) { QSignalDumper::startDump(); } else if (strcmp(argv[i], "-o") == 0) { if (i + 1 >= argc) { printf("-o needs an extra parameter specifying the filename\n"); exit(1); } else { QTestLog::redirectOutput(argv[++i]); } } else if (strcmp(argv[i], "-eventdelay") == 0) { if (i + 1 >= argc) { printf("-eventdelay needs an extra parameter to indicate the delay(ms)\n"); exit(1); } else { QTest::eventDelay = qToInt(argv[++i]); } } else if (strcmp(argv[i], "-keydelay") == 0) { if (i + 1 >= argc) { printf("-keydelay needs an extra parameter to indicate the delay(ms)\n"); exit(1); } else { QTest::keyDelay = qToInt(argv[++i]); } } else if (strcmp(argv[i], "-mousedelay") == 0) { if (i + 1 >= argc) { printf("-mousedelay needs an extra parameter to indicate the delay(ms)\n"); exit(1); } else { QTest::mouseDelay = qToInt(argv[++i]); } } else if (strcmp(argv[i], "-maxwarnings") == 0) { if (i + 1 >= argc) { printf("-maxwarnings needs an extra parameter with the amount of warnings\n"); exit(1); } else { QTestLog::setMaxWarnings(qToInt(argv[++i])); } } else if (strcmp(argv[i], "-keyevent-verbose") == 0) { QTest::keyVerbose = 1; } else if (strcmp(argv[i], "-qws") == 0) { // do nothing } else if (argv[i][0] == '-') { printf("Unknown option: '%s'\n\n%s", argv[i], testOptions); exit(1); } else { int colon = -1; char buf[512], *data=0; for(int off = 0; *(argv[i]+off); ++off) { if (*(argv[i]+off) == ':') { colon = off; break; } } if(colon != -1) { *(argv[i]+colon) = '\0'; data = qstrdup(argv[i]+colon+1); } QTest::qt_snprintf(buf, 512, "%s()", argv[i]); int idx = QTest::currentTestObject->metaObject()->indexOfMethod(buf); if (idx < 0 || !isValidSlot(QTest::currentTestObject->metaObject()->method(idx))) { printf("Unknown testfunction: '%s'\n", buf); printf("Available testfunctions:\n"); qPrintTestSlots(); exit(1); } ++QTest::lastTestFuncIdx; QTest::testFuncs[QTest::lastTestFuncIdx].function = idx; QTest::testFuncs[QTest::lastTestFuncIdx].data = data; QTEST_ASSERT(QTest::lastTestFuncIdx < 512); } }}struct QTestDataSetter{ QTestDataSetter(QTestData *data) { QTestResult::setCurrentTestData(data); } ~QTestDataSetter() { QTestResult::setCurrentTestData(0); }};/*! \internal Call init(), slot_data(), slot(), slot(), slot()..., cleanup() If data is set then it is the only test that is performed If the function was successfully called, true is returned, otherwise false. */static bool qInvokeTestMethod(const char *slotName, const char *data=0){ QTEST_ASSERT(slotName); char member[512]; QTestTable table; char *slot = qstrdup(slotName); slot[strlen(slot) - 2] = '\0'; QTestResult::setCurrentTestFunction(slot); const QTestTable *gTable = QTestTable::globalTestTable(); const int globalDataCount = gTable->dataCount(); int curGlobalDataIndex = 0; /* For each test function that has a *_data() table/function, do: */ do { if (!gTable->isEmpty()) QTestResult::setCurrentGlobalTestData(gTable->testData(curGlobalDataIndex)); if (curGlobalDataIndex == 0) { QTestResult::setCurrentTestLocation(QTestResult::DataFunc); QTest::qt_snprintf(member, 512, "%s_data", slot); QMetaObject::invokeMethod(QTest::currentTestObject, member, Qt::DirectConnection); // if we encounter a SkipAll in the _data slot, we skip the whole // testfunction, no matter how much global data exists if (QTestResult::skipCurrentTest()) { QTestResult::setCurrentGlobalTestData(0); break; } } bool foundFunction = false; if (!QTestResult::skipCurrentTest()) { int curDataIndex = 0; const int dataCount = table.dataCount(); QTestResult::setSkipCurrentTest(false); /* For each entry in the data table, do: */ do { if (!data || !qstrcmp(data, table.testData(curDataIndex)->dataTag())) { foundFunction = true; QTestDataSetter s(table.isEmpty() ? static_cast<QTestData *>(0) : table.testData(curDataIndex)); QTestResult::setCurrentTestLocation(QTestResult::InitFunc); QMetaObject::invokeMethod(QTest::currentTestObject, "init"); if (QTestResult::skipCurrentTest()) break; QTestResult::setCurrentTestLocation(QTestResult::Func); if (!QMetaObject::invokeMethod(QTest::currentTestObject, slot, Qt::DirectConnection)) { QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__); break; } QTestResult::setCurrentTestLocation(QTestResult::CleanupFunc); QMetaObject::invokeMethod(QTest::currentTestObject, "cleanup"); QTestResult::setCurrentTestLocation(QTestResult::NoWhere); if (QTestResult::skipCurrentTest()) // check whether SkipAll was requested break; if (data) break; } ++curDataIndex; } while (curDataIndex < dataCount); } if (data && !foundFunction) { printf("Unknown testdata for function %s: '%s'\n", slotName, data); printf("Available testdata:\n"); for(int i = 0; i < table.dataCount(); ++i) printf("%s\n", table.testData(i)->dataTag()); return false; } QTestResult::setCurrentGlobalTestData(0); ++curGlobalDataIndex; } while (curGlobalDataIndex < globalDataCount); QTestResult::finishedCurrentTestFunction(); QTestResult::setSkipCurrentTest(false); QTestResult::setCurrentTestData(0); delete[] slot; return true;}void *fetchData(QTestData *data, const char *tagName, int typeId){ QTEST_ASSERT(typeId); QTEST_ASSERT_X(data, "QTest::fetchData()", "Test data requested, but no testdata available."); QTEST_ASSERT(data->parent()); int idx = data->parent()->indexOf(tagName); if (idx == -1 || idx >= data->dataCount()) { qFatal("QFETCH: Requested testdata '%s' not available, check your _data function.", tagName); } if (typeId != data->parent()->elementTypeId(idx)) { qFatal("Requested type '%s' does not match available type '%s'.", QMetaType::typeName(typeId), QMetaType::typeName(data->parent()->elementTypeId(idx))); } return data->data(idx);}/*! \fn char* QTest::toHexRepresentation(const char *ba, int length) Returns a pointer to a string that is the string \a ba represented as a space-separated sequence of hex characters. If the input is considered too long, it is truncated. A trucation is indicated in the returned string as an ellipsis at the end. \a length is the length of the string \a ba. */char *toHexRepresentation(const char *ba, int length){ if(length == 0) return qstrdup(""); /* We output at maximum about maxLen characters in order to avoid * running out of memory and flooding things when the byte array * is large. * * maxLen can't be for example 200 because QTestLib is sprinkled with fixed * size char arrays. * */ const int maxLen = 50; const int len = qMin(maxLen, length); char *result = 0; if(length > maxLen) { const int size = len * 3 + 4; result = new char[size]; char *const forElipsis = result + size - 5; forElipsis[0] = ' '; forElipsis[1] = '.'; forElipsis[2] = '.'; forElipsis[3] = '.'; result[size - 1] = '\0'; } else { const int size = len * 3; result = new char[size]; result[size - 1] = '\0'; } const char toHex[] = "0123456789ABCDEF"; int i = 0; int o = 0; while(true) { const char at = ba[i]; result[o] = toHex[(at >> 4) & 0x0F]; ++o; result[o] = toHex[at & 0x0F]; ++i; ++o; if(i == len) break; else { result[o] = ' '; ++o; } } return result;}} // namespace/*! Executes tests declared in \a testObject. In addition, the private slots \c{initTestCase()}, \c{cleanupTestCase()}, \c{init()} and \c{cleanup()} are executed if they exist. See \l{Creating a test} for more details. Optionally, the command line arguments \a argc and \a argv can be provided. For a list of recognized arguments, read \l {QTestLib Command Line Arguments}. For stand-alone tests, the convenience macro \l QTEST_MAIN() can be used to declare a main method that parses the command line arguments and executes the tests. The following example will run all tests in \c MyFirstTestObject and \c{MySecondTestObject}: \code MyFirstTestObject test1; QTest::qExec(&test1); MySecondTestObject test2; QTest::qExec(&test2); \endcode Note: This function is not reentrant, only one test can run at a time. A test that was executed with qExec() can't run another test via qExec() and threads are not allowed to call qExec() simultaneously. \sa QTEST_MAIN()*/int QTest::qExec(QObject *testObject, int argc, char **argv){ #ifndef QT_NO_EXCEPTIONS try { #endif #if defined(Q_OS_WIN) SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX); #endif QTestResult::reset(); QTEST_ASSERT(testObject); QTEST_ASSERT(!currentTestObject); currentTestObject = testObject; const QMetaObject *metaObject = testObject->metaObject(); QTEST_ASSERT(metaObject); QTestResult::setCurrentTestObject(metaObject->className()); qParseArgs(argc, argv); QTestLog::startLogging(); QTestResult::setCurrentTestFunction("initTestCase"); QTestResult::setCurrentTestLocation(QTestResult::DataFunc); QTestTable::globalTestTable(); QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection); if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) { QTestResult::setCurrentTestLocation(QTestResult::InitFunc); QMetaObject::invokeMethod(testObject, "initTestCase"); // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy. const bool previousFailed = QTestResult::testFailed(); QTestResult::finishedCurrentTestFunction(); if(!QTestResult::skipCurrentTest() && !previousFailed) { if (lastTestFuncIdx >= 0) { for (int i = 0; i <= lastTestFuncIdx; ++i) { if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(), testFuncs[i].data)) break; } } else { int methodCount = metaObject->methodCount(); for (int i = 0; i < methodCount; ++i) { QMetaMethod slotMethod = metaObject->method(i); if (!isValidSlot(slotMethod)) continue; if (!qInvokeTestMethod(slotMethod.signature())) break; } } } QTestResult::setSkipCurrentTest(false); QTestResult::setCurrentTestFunction("cleanupTestCase"); QMetaObject::invokeMethod(testObject, "cleanupTestCase"); } QTestResult::finishedCurrentTestFunction(); QTestResult::setCurrentTestFunction(0); QTestTable::clearGlobalTestTable(); #ifndef QT_NO_EXCEPTIONS } catch (...) { QTestResult::addFailure("Caught unhandled exception", __FILE__, __LINE__); if (QTestResult::currentTestFunction()) { QTestResult::finishedCurrentTestFunction(); QTestResult::setCurrentTestFunction(0); } QTestLog::stopLogging(); #ifdef Q_OS_WIN // rethrow exception to make debugging easier throw; #endif return -1; } #endif QTestLog::stopLogging(); currentTestObject = 0;#if defined(QTEST_NOEXITCODE) || defined(QT_BUILD_INTERNAL) return 0;#else return QTestResult::failCount();#endif}/*! \internal */void QTest::qFail(const char *statementStr, const char *file, int line){ QTestResult::addFailure(statementStr, file, line);}/*! \internal */bool QTest::qVerify(bool statement, const char *statementStr, const char *description, const char *file, int line){ return QTestResult::verify(statement, statementStr, description, file, line);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?