115 static QList<QByteArray> splitLines(QByteArray ba) |
115 static QList<QByteArray> splitLines(QByteArray ba) |
116 { |
116 { |
117 ba.replace('\r', ""); |
117 ba.replace('\r', ""); |
118 QList<QByteArray> out = ba.split('\n'); |
118 QList<QByteArray> out = ba.split('\n'); |
119 |
119 |
120 // Replace any ` file="..."' in XML with a generic location. |
120 // Replace any ` file="..."' or ` line="..."' in XML with a generic location. |
121 static const char marker[] = " file=\""; |
121 static const char *markers[][2] = { |
|
122 { " file=\"", " file=\"__FILE__\"" }, |
|
123 { " line=\"", " line=\"__LINE__\"" } |
|
124 }; |
|
125 static const int markerCount = sizeof markers / sizeof markers[0]; |
|
126 |
122 for (int i = 0; i < out.size(); ++i) { |
127 for (int i = 0; i < out.size(); ++i) { |
123 QByteArray& line = out[i]; |
128 QByteArray& line = out[i]; |
124 int index = line.indexOf(marker); |
129 for (int j = 0; j < markerCount; ++j) { |
125 if (index == -1) { |
130 int index = line.indexOf(markers[j][0]); |
126 continue; |
131 if (index == -1) { |
127 } |
132 continue; |
128 int end = line.indexOf('"', index + sizeof(marker)); |
133 } |
129 if (end == -1) { |
134 int end = line.indexOf('"', index + strlen(markers[j][0])); |
130 continue; |
135 if (end == -1) { |
131 } |
136 continue; |
132 line.replace(index, end-index, " file=\"__FILE__\""); |
137 } |
|
138 line.replace(index, end-index + 1, markers[j][1]); |
|
139 } |
133 } |
140 } |
134 |
141 |
135 return out; |
142 return out; |
136 } |
143 } |
137 |
144 |
394 continue; |
401 continue; |
395 if (line.endsWith(" : failure location")) |
402 if (line.endsWith(" : failure location")) |
396 continue; |
403 continue; |
397 |
404 |
398 const QString output(QString::fromLatin1(line)); |
405 const QString output(QString::fromLatin1(line)); |
399 const QString expected(QString::fromLatin1(exp.at(i)).replace("<INSERT_QT_VERSION_HERE>", QT_VERSION_STR)); |
406 const QString expected(QString::fromLatin1(exp.at(i)).replace("@INSERT_QT_VERSION_HERE@", QT_VERSION_STR)); |
400 |
407 |
401 if (line.contains("ASSERT") && output != expected) { |
408 if (line.contains("ASSERT") && output != expected) { |
402 QEXPECT_FAIL("assert", "QTestLib prints out the absolute path.", Continue); |
409 QEXPECT_FAIL("assert", "QTestLib prints out the absolute path.", Continue); |
403 QEXPECT_FAIL("assert xml", "QTestLib prints out the absolute path.", Continue); |
410 QEXPECT_FAIL("assert xml", "QTestLib prints out the absolute path.", Continue); |
404 QEXPECT_FAIL("assert xml flush","QTestLib prints out the absolute path.", Continue); |
411 QEXPECT_FAIL("assert xml flush","QTestLib prints out the absolute path.", Continue); |
419 else { |
426 else { |
420 /* |
427 /* |
421 Are we expecting this line to be a benchmark result? |
428 Are we expecting this line to be a benchmark result? |
422 If so, don't do a literal comparison, since results have some natural variance. |
429 If so, don't do a literal comparison, since results have some natural variance. |
423 */ |
430 */ |
424 if (benchmark) { |
431 if (benchmark || line.startsWith("<BenchmarkResult")) { |
425 QString error; |
432 QString error; |
426 |
433 |
427 BenchmarkResult actualResult = BenchmarkResult::parse(output, &error); |
434 BenchmarkResult actualResult = BenchmarkResult::parse(output, &error); |
428 QVERIFY2(error.isEmpty(), qPrintable(QString("Actual line didn't parse as benchmark result: %1\nLine: %2").arg(error).arg(output))); |
435 QVERIFY2(error.isEmpty(), qPrintable(QString("Actual line didn't parse as benchmark result: %1\nLine: %2").arg(error).arg(output))); |
429 |
436 |
449 QFETCH(QStringList, arguments); |
456 QFETCH(QStringList, arguments); |
450 |
457 |
451 doRunSubTest(subdir, logger, arguments); |
458 doRunSubTest(subdir, logger, arguments); |
452 } |
459 } |
453 |
460 |
|
461 // attribute must contain =" |
|
462 QString extractXmlAttribute(const QString &line, const char *attribute) |
|
463 { |
|
464 int index = line.indexOf(attribute); |
|
465 if (index == -1) |
|
466 return QString(); |
|
467 int end = line.indexOf('"', index + strlen(attribute)); |
|
468 if (end == -1) |
|
469 return QString(); |
|
470 |
|
471 QString result = line.mid(index + strlen(attribute), end - index - strlen(attribute)); |
|
472 if (result.isEmpty()) |
|
473 return ""; // ensure empty but not null |
|
474 return result; |
|
475 } |
|
476 |
454 /* Parse line into the BenchmarkResult it represents. */ |
477 /* Parse line into the BenchmarkResult it represents. */ |
455 BenchmarkResult BenchmarkResult::parse(QString const& line, QString* error) |
478 BenchmarkResult BenchmarkResult::parse(QString const& line, QString* error) |
456 { |
479 { |
457 if (error) *error = QString(); |
480 if (error) *error = QString(); |
458 BenchmarkResult out; |
481 BenchmarkResult out; |
461 |
484 |
462 if (remaining.isEmpty()) { |
485 if (remaining.isEmpty()) { |
463 if (error) *error = "Line is empty"; |
486 if (error) *error = "Line is empty"; |
464 return out; |
487 return out; |
465 } |
488 } |
|
489 |
|
490 if (line.startsWith("<BenchmarkResult ")) { |
|
491 // XML result |
|
492 // format: |
|
493 // <BenchmarkResult metric="$unit" tag="$tag" value="$total" iterations="$iterations" /> |
|
494 if (!line.endsWith("/>")) { |
|
495 if (error) *error = "unterminated XML"; |
|
496 return out; |
|
497 } |
|
498 |
|
499 QString unit = extractXmlAttribute(line, " metric=\""); |
|
500 QString sTotal = extractXmlAttribute(line, " value=\""); |
|
501 QString sIterations = extractXmlAttribute(line, " iterations=\""); |
|
502 if (unit.isNull() || sTotal.isNull() || sIterations.isNull()) { |
|
503 if (error) *error = "XML snippet did not contain all required values"; |
|
504 return out; |
|
505 } |
|
506 |
|
507 bool ok; |
|
508 #if QT_VERSION >= 0x040700 |
|
509 // Qt 4.7 uses floating point |
|
510 double total = sTotal.toDouble(&ok); |
|
511 if (!ok) { |
|
512 if (error) *error = sTotal + " is not a valid number"; |
|
513 return out; |
|
514 } |
|
515 double iterations = sIterations.toDouble(&ok); |
|
516 if (!ok) { |
|
517 if (error) *error = sIterations + " is not a valid number"; |
|
518 return out; |
|
519 } |
|
520 #else |
|
521 qlonglong total = sTotal.toLongLong(&ok); |
|
522 if (!ok) { |
|
523 if (error) *error = sTotal + " is not a valid integer"; |
|
524 return out; |
|
525 } |
|
526 qlonglong iterations = sIterations.toLongLong(&ok); |
|
527 if (!ok) { |
|
528 if (error) *error = sIterations + " is not a valid integer"; |
|
529 return out; |
|
530 } |
|
531 #endif |
|
532 |
|
533 out.unit = unit; |
|
534 out.total = total; |
|
535 out.iterations = iterations; |
|
536 return out; |
|
537 } |
|
538 // Text result |
466 |
539 |
467 /* This code avoids using a QRegExp because QRegExp might be broken. */ |
540 /* This code avoids using a QRegExp because QRegExp might be broken. */ |
468 |
541 |
469 /* Sample format: 4,000 msec per iteration (total: 4000, iterations: 1) */ |
542 /* Sample format: 4,000 msec per iteration (total: 4000, iterations: 1) */ |
470 |
543 |