harden and speed up path op unit tests

PathOps tests internal routines direcctly. Check to make sure that
test points, lines, quads, curves, triangles, and bounds read from
arrays are valid (i.e., don't contain NaN) before calling the
test function.

Repurpose the test flags.
- make 'v' verbose test region output against path output
- make 'z' single threaded (before it made it multithreaded)

The latter change speeds up tests run by the buildbot by 2x to 3x.

BUG=

Review URL: https://codereview.chromium.org/19374003

git-svn-id: http://skia.googlecode.com/svn/trunk@10107 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/PathOpsAngleTest.cpp b/tests/PathOpsAngleTest.cpp
index 34a77b1..4c362b6 100644
--- a/tests/PathOpsAngleTest.cpp
+++ b/tests/PathOpsAngleTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkOpSegment.h"
 #include "SkTArray.h"
 #include "Test.h"
@@ -248,9 +249,11 @@
     }
     switch(set[idx].ptCount) {
         case 2: {
+            SkASSERT(ValidPoints(data, 2));
             seg->addLine(data, false, false);
             SkDLine dLine;
             dLine.set(set[idx].ptData);
+            SkASSERT(ValidLine(dLine));
             if (useIntersectPt) {
                 break;
             }
@@ -258,9 +261,11 @@
             end = dLine.xyAtT(set[idx].tEnd).asSkPoint();
             } break;
         case 3: {
+            SkASSERT(ValidPoints(data, 3));
             seg->addQuad(data, false, false);
             SkDQuad dQuad;
             dQuad.set(set[idx].ptData);
+            SkASSERT(ValidQuad(dQuad));
              if (useIntersectPt) {
                 break;
             }
@@ -268,9 +273,11 @@
             end = dQuad.xyAtT(set[idx].tEnd).asSkPoint();
             } break;
         case 4: {
+            SkASSERT(ValidPoints(data, 4));
             seg->addCubic(data, false, false);
             SkDCubic dCubic;
             dCubic.set(set[idx].ptData);
+            SkASSERT(ValidCubic(dCubic));
             if (useIntersectPt) {
                 break;
             }
diff --git a/tests/PathOpsBoundsTest.cpp b/tests/PathOpsBoundsTest.cpp
index 9d686a5..3d6091c 100644
--- a/tests/PathOpsBoundsTest.cpp
+++ b/tests/PathOpsBoundsTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsBounds.h"
 #include "Test.h"
 
@@ -48,13 +49,17 @@
 static void PathOpsBoundsTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < sectTestsCount; ++index) {
         const SkPathOpsBounds& bounds1 = static_cast<const SkPathOpsBounds&>(sectTests[index][0]);
+        SkASSERT(ValidBounds(bounds1));
         const SkPathOpsBounds& bounds2 = static_cast<const SkPathOpsBounds&>(sectTests[index][1]);
+        SkASSERT(ValidBounds(bounds2));
         bool touches = SkPathOpsBounds::Intersects(bounds1, bounds2);
         REPORTER_ASSERT(reporter, touches);
     }
     for (size_t index = 0; index < noSectTestsCount; ++index) {
         const SkPathOpsBounds& bounds1 = static_cast<const SkPathOpsBounds&>(noSectTests[index][0]);
+        SkASSERT(ValidBounds(bounds1));
         const SkPathOpsBounds& bounds2 = static_cast<const SkPathOpsBounds&>(noSectTests[index][1]);
+        SkASSERT(ValidBounds(bounds2));
         bool touches = SkPathOpsBounds::Intersects(bounds1, bounds2);
         REPORTER_ASSERT(reporter, !touches);
     }
@@ -76,11 +81,13 @@
     REPORTER_ASSERT(reporter, bounds == expected);
     for (size_t index = 0; index < emptyTestsCount; ++index) {
         const SkPathOpsBounds& bounds = static_cast<const SkPathOpsBounds&>(reallyEmpty[index]);
+        // SkASSERT(ValidBounds(bounds));  // don't check because test may contain nan
         bool empty = bounds.isReallyEmpty();
         REPORTER_ASSERT(reporter, empty);
     }
     for (size_t index = 0; index < notEmptyTestsCount; ++index) {
         const SkPathOpsBounds& bounds = static_cast<const SkPathOpsBounds&>(notReallyEmpty[index]);
+        SkASSERT(ValidBounds(bounds));
         bool empty = bounds.isReallyEmpty();
         REPORTER_ASSERT(reporter, !empty);
     }
diff --git a/tests/PathOpsCubicIntersectionTest.cpp b/tests/PathOpsCubicIntersectionTest.cpp
index 4cac2d0..c4915e9 100644
--- a/tests/PathOpsCubicIntersectionTest.cpp
+++ b/tests/PathOpsCubicIntersectionTest.cpp
@@ -268,6 +268,8 @@
 const size_t newTestSetCount = SK_ARRAY_COUNT(newTestSet);
 
 static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const SkDCubic& cubic2) {
+    SkASSERT(ValidCubic(cubic1));
+    SkASSERT(ValidCubic(cubic2));
 #if ONE_OFF_DEBUG
     SkDebugf("computed quadratics given\n");
     SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
diff --git a/tests/PathOpsCubicLineIntersectionTest.cpp b/tests/PathOpsCubicLineIntersectionTest.cpp
index 245f8a6..2f52b3b 100644
--- a/tests/PathOpsCubicLineIntersectionTest.cpp
+++ b/tests/PathOpsCubicLineIntersectionTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsCubic.h"
 #include "SkPathOpsLine.h"
@@ -32,7 +33,9 @@
 
 static void testOne(skiatest::Reporter* reporter, int iIndex) {
     const SkDCubic& cubic = lineCubicTests[iIndex].cubic;
+    SkASSERT(ValidCubic(cubic));
     const SkDLine& line = lineCubicTests[iIndex].line;
+    SkASSERT(ValidLine(line));
     SkReduceOrder reduce1;
     SkReduceOrder reduce2;
     int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics,
diff --git a/tests/PathOpsCubicQuadIntersectionTest.cpp b/tests/PathOpsCubicQuadIntersectionTest.cpp
index 8a31814..42a5d33 100644
--- a/tests/PathOpsCubicQuadIntersectionTest.cpp
+++ b/tests/PathOpsCubicQuadIntersectionTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsCubic.h"
 #include "SkPathOpsQuad.h"
@@ -30,7 +31,9 @@
     for (size_t index = 0; index < quadCubicTests_count; ++index) {
         int iIndex = static_cast<int>(index);
         const SkDCubic& cubic = quadCubicTests[index].cubic;
+        SkASSERT(ValidCubic(cubic));
         const SkDQuad& quad = quadCubicTests[index].quad;
+        SkASSERT(ValidQuad(quad));
         SkReduceOrder reduce1;
         SkReduceOrder reduce2;
         int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics,
diff --git a/tests/PathOpsCubicReduceOrderTest.cpp b/tests/PathOpsCubicReduceOrderTest.cpp
index d7518ab..7b89bbe 100644
--- a/tests/PathOpsCubicReduceOrderTest.cpp
+++ b/tests/PathOpsCubicReduceOrderTest.cpp
@@ -6,6 +6,7 @@
  */
 #include "PathOpsCubicIntersectionTestData.h"
 #include "PathOpsQuadIntersectionTestData.h"
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsRect.h"
 #include "SkReduceOrder.h"
@@ -102,6 +103,7 @@
 
     for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
         const SkDCubic& cubic = pointDegenerates[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 1) {
             SkDebugf("[%d] pointDegenerates order=%d\n", static_cast<int>(index), order);
@@ -110,6 +112,7 @@
     }
     for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
         const SkDCubic& cubic = notPointDegenerates[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order == 1) {
             SkDebugf("[%d] notPointDegenerates order=%d\n", static_cast<int>(index), order);
@@ -118,6 +121,7 @@
     }
     for (index = firstLinesTest; index < lines_count; ++index) {
         const SkDCubic& cubic = lines[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 2) {
             SkDebugf("[%d] lines order=%d\n", static_cast<int>(index), order);
@@ -126,6 +130,7 @@
     }
     for (index = firstNotLinesTest; index < notLines_count; ++index) {
         const SkDCubic& cubic = notLines[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order == 2) {
             SkDebugf("[%d] notLines order=%d\n", static_cast<int>(index), order);
@@ -134,6 +139,7 @@
     }
     for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
         const SkDCubic& cubic = modEpsilonLines[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order == 2) {
             SkDebugf("[%d] line mod by epsilon order=%d\n", static_cast<int>(index), order);
@@ -142,6 +148,7 @@
     }
     for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
         const SkDCubic& cubic = lessEpsilonLines[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 2) {
             SkDebugf("[%d] line less by epsilon/2 order=%d\n", static_cast<int>(index), order);
@@ -150,6 +157,7 @@
     }
     for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
         const SkDCubic& cubic = negEpsilonLines[index];
+        SkASSERT(ValidCubic(cubic));
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 2) {
             SkDebugf("[%d] line neg by epsilon/2 order=%d\n", static_cast<int>(index), order);
@@ -158,6 +166,7 @@
     }
     for (index = firstQuadraticPointTest; index < quadraticPoints_count; ++index) {
         const SkDQuad& quad = quadraticPoints[index];
+        SkASSERT(ValidQuad(quad));
         SkDCubic cubic = quad.toCubic();
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 1) {
@@ -167,6 +176,7 @@
     }
     for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
         const SkDQuad& quad = quadraticLines[index];
+        SkASSERT(ValidQuad(quad));
         SkDCubic cubic = quad.toCubic();
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 2) {
@@ -176,6 +186,7 @@
     }
     for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
         const SkDQuad& quad = quadraticModEpsilonLines[index];
+        SkASSERT(ValidQuad(quad));
         SkDCubic cubic = quad.toCubic();
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics, SkReduceOrder::kFill_Style);
         if (order != 3) {
@@ -187,6 +198,7 @@
     // test if computed line end points are valid
     for (index = firstComputedLinesTest; index < lines_count; ++index) {
         const SkDCubic& cubic = lines[index];
+        SkASSERT(ValidCubic(cubic));
         bool controlsInside = controls_inside(cubic);
         order = reducer.reduce(cubic, SkReduceOrder::kAllow_Quadratics,
                 SkReduceOrder::kStroke_Style);
diff --git a/tests/PathOpsCubicToQuadsTest.cpp b/tests/PathOpsCubicToQuadsTest.cpp
index 774fbae..60def6d 100644
--- a/tests/PathOpsCubicToQuadsTest.cpp
+++ b/tests/PathOpsCubicToQuadsTest.cpp
@@ -17,6 +17,7 @@
                  int firstTest, size_t testCount) {
     for (size_t index = firstTest; index < testCount; ++index) {
         const SkDCubic& cubic = cubics[index];
+        SkASSERT(ValidCubic(cubic));
         double precision = cubic.calcPrecision();
         SkTArray<SkDQuad, true> quads;
         CubicToQuads(cubic, precision, quads);
@@ -32,6 +33,7 @@
                  int firstTest, size_t testCount) {
     for (size_t index = firstTest; index < testCount; ++index) {
         const SkDQuad& quad = quadTests[index];
+        SkASSERT(ValidQuad(quad));
         SkDCubic cubic = quad.toCubic();
         double precision = cubic.calcPrecision();
         SkTArray<SkDQuad, true> quads;
@@ -49,6 +51,7 @@
     // test if computed line end points are valid
     for (size_t index = firstTest; index < testCount; ++index) {
         const SkDCubic& cubic = cubics[index];
+        SkASSERT(ValidCubic(cubic));
         double precision = cubic.calcPrecision();
         SkTArray<SkDQuad, true> quads;
         CubicToQuads(cubic, precision, quads);
@@ -71,6 +74,7 @@
     for (size_t index = firstTest; index < testCount; ++index) {
         for (int idx2 = 0; idx2 < 2; ++idx2) {
             const SkDCubic& cubic = cubics[index][idx2];
+            SkASSERT(ValidCubic(cubic));
             double precision = cubic.calcPrecision();
             SkTArray<SkDQuad, true> quads;
             CubicToQuads(cubic, precision, quads);
@@ -168,6 +172,7 @@
 
 static void oneOff(skiatest::Reporter* reporter, size_t x) {
     const SkDCubic& cubic = locals[x];
+    SkASSERT(ValidCubic(cubic));
     const SkPoint skcubic[4] = {
             {static_cast<float>(cubic[0].fX), static_cast<float>(cubic[0].fY)},
             {static_cast<float>(cubic[1].fX), static_cast<float>(cubic[1].fY)},
diff --git a/tests/PathOpsDCubicTest.cpp b/tests/PathOpsDCubicTest.cpp
index 04850de..d9e40f9 100644
--- a/tests/PathOpsDCubicTest.cpp
+++ b/tests/PathOpsDCubicTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsCubic.h"
 #include "Test.h"
 
@@ -18,6 +19,7 @@
 static void PathOpsDCubicTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count; ++index) {
         const SkDCubic& cubic = tests[index];
+        SkASSERT(ValidCubic(cubic));
         bool result = cubic.clockwise();
         if (!result) {
             SkDebugf("%s [%d] expected clockwise\n", __FUNCTION__, index);
diff --git a/tests/PathOpsDLineTest.cpp b/tests/PathOpsDLineTest.cpp
index c237494..feab21d 100644
--- a/tests/PathOpsDLineTest.cpp
+++ b/tests/PathOpsDLineTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsLine.h"
 #include "Test.h"
 
@@ -30,11 +31,13 @@
 static void PathOpsLineUtilitiesTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count; ++index) {
         const SkDLine& line = tests[index];
+        SkASSERT(ValidLine(line));
         SkDLine line2;
         SkPoint pts[2] = {line[0].asSkPoint(), line[1].asSkPoint()};
         line2.set(pts);
         REPORTER_ASSERT(reporter, line[0] == line2[0] && line[1] == line2[1]);
         const SkDPoint& pt = left[index];
+        SkASSERT(ValidPoint(pt));
         double result = line.isLeft(pt);
         if ((result <= 0 && index >= 1) || (result < 0 && index == 0)) {
             SkDebugf("%s [%d] expected left\n", __FUNCTION__, index);
diff --git a/tests/PathOpsDPointTest.cpp b/tests/PathOpsDPointTest.cpp
index 688d01b..8621e66 100644
--- a/tests/PathOpsDPointTest.cpp
+++ b/tests/PathOpsDPointTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsPoint.h"
 #include "Test.h"
 
@@ -22,6 +23,7 @@
 static void PathOpsDPointTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count; ++index) {
         const SkDPoint& pt = tests[index];
+        SkASSERT(ValidPoint(pt));
         SkDPoint p = pt;
         REPORTER_ASSERT(reporter, p == pt);
         REPORTER_ASSERT(reporter, !(pt != pt));
diff --git a/tests/PathOpsDQuadTest.cpp b/tests/PathOpsDQuadTest.cpp
index 89da659..5921b69 100644
--- a/tests/PathOpsDQuadTest.cpp
+++ b/tests/PathOpsDQuadTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsQuad.h"
 #include "Test.h"
 
@@ -36,6 +37,7 @@
 static void PathOpsDQuadTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count; ++index) {
         const SkDQuad& quad = tests[index];
+        SkASSERT(ValidQuad(quad));
         bool result = quad.pointInHull(inPoint[index]);
         if (!result) {
             SkDebugf("%s [%d] expected in hull\n", __FUNCTION__, index);
diff --git a/tests/PathOpsDRectTest.cpp b/tests/PathOpsDRectTest.cpp
index 6eb1955..7cadf63 100644
--- a/tests/PathOpsDRectTest.cpp
+++ b/tests/PathOpsDRectTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsCubic.h"
 #include "SkPathOpsLine.h"
 #include "SkPathOpsQuad.h"
@@ -42,6 +43,7 @@
     SkDRect rect, rect2;
     for (index = 0; index < lineTests_count; ++index) {
         const SkDLine& line = lineTests[index];
+        SkASSERT(ValidLine(line));
         rect.setBounds(line);
         REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(line[0].fX, line[1].fX));
         REPORTER_ASSERT(reporter, rect.fTop == SkTMin(line[0].fY, line[1].fY));
@@ -58,6 +60,7 @@
     }
     for (index = 0; index < quadTests_count; ++index) {
         const SkDQuad& quad = quadTests[index];
+        SkASSERT(ValidQuad(quad));
         rect.setRawBounds(quad);
         REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(quad[0].fX,
                 SkTMin(quad[1].fX, quad[2].fX)));
@@ -77,6 +80,7 @@
     }
     for (index = 0; index < cubicTests_count; ++index) {
         const SkDCubic& cubic = cubicTests[index];
+        SkASSERT(ValidCubic(cubic));
         rect.setRawBounds(cubic);
         REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(cubic[0].fX,
                 SkTMin(cubic[1].fX, SkTMin(cubic[2].fX, cubic[3].fX))));
diff --git a/tests/PathOpsDTriangleTest.cpp b/tests/PathOpsDTriangleTest.cpp
index d64197d..35bfe06 100644
--- a/tests/PathOpsDTriangleTest.cpp
+++ b/tests/PathOpsDTriangleTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsTriangle.h"
 #include "Test.h"
 
@@ -30,6 +31,7 @@
 static void PathOpsTriangleUtilitiesTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count; ++index) {
         const SkDTriangle& triangle = tests[index];
+        SkASSERT(ValidTriangle(triangle));
         bool result = triangle.contains(inPoint[index]);
         if (!result) {
             SkDebugf("%s [%d] expected point in triangle\n", __FUNCTION__, index);
diff --git a/tests/PathOpsDVectorTest.cpp b/tests/PathOpsDVectorTest.cpp
index 6d752c5..23ca2a8 100644
--- a/tests/PathOpsDVectorTest.cpp
+++ b/tests/PathOpsDVectorTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkPathOpsPoint.h"
 #include "Test.h"
 
@@ -22,7 +23,9 @@
 static void PathOpsDVectorTest(skiatest::Reporter* reporter) {
     for (size_t index = 0; index < tests_count - 1; ++index) {
         SkDVector v1 = tests[index + 1] - tests[index];
+        SkASSERT(ValidVector(v1));
         SkDVector v2 = tests[index] - tests[index + 1];
+        SkASSERT(ValidVector(v2));
         v1 += v2;
         REPORTER_ASSERT(reporter, v1.fX == 0 && v1.fY == 0);
         SkDPoint p = tests[index + 1] + v2;
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index 93280d7..b85644d 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -41,7 +41,6 @@
 };
 
 static bool gShowPath = false;
-static bool gComparePaths = true;
 static bool gComparePathsAssert = true;
 static bool gPathStrAssert = true;
 
@@ -512,7 +511,7 @@
         REPORTER_ASSERT(state.fReporter, 0);
         return false;
     }
-    if (!gComparePaths) {
+    if (!state.fReporter->verbose()) {
         return true;
     }
     int result = comparePaths(state.fReporter, path, out, *state.fBitmap);
@@ -563,8 +562,8 @@
 }
 #endif
 
-bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
-                 const SkPathOp shapeOp, const char* testName) {
+static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+                 const SkPathOp shapeOp, const char* testName, bool threaded) {
 #if DEBUG_SHOW_TEST_NAME
     if (testName == NULL) {
         SkDebugf("\n");
@@ -581,6 +580,9 @@
         REPORTER_ASSERT(reporter, 0);
         return false;
     }
+    if (threaded && !reporter->verbose()) {
+        return true;
+    }
     SkPath pathOut, scaledPathOut;
     SkRegion rgnA, rgnB, openClip, rgnOut;
     openClip.setRect(-16000, -16000, 16000, 16000);
@@ -614,6 +616,16 @@
     return result == 0;
 }
 
+bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+                 const SkPathOp shapeOp, const char* testName) {
+    return innerPathOp(reporter, a, b, shapeOp, testName, false);
+}
+
+bool testThreadedPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+                 const SkPathOp shapeOp, const char* testName) {
+    return innerPathOp(reporter, a, b, shapeOp, testName, true);
+}
+
 int initializeTests(skiatest::Reporter* reporter, const char* test) {
 #ifdef SK_DEBUG
     gDebugMaxWindSum = 4;
diff --git a/tests/PathOpsExtendedTest.h b/tests/PathOpsExtendedTest.h
index 723135a..303d10c 100644
--- a/tests/PathOpsExtendedTest.h
+++ b/tests/PathOpsExtendedTest.h
@@ -28,6 +28,8 @@
 extern void showOp(const SkPathOp op);
 extern bool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
                         const SkPathOp , const char* testName = NULL);
+extern bool testThreadedPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
+                        const SkPathOp , const char* testName = NULL);
 extern bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
                          const char* pathStr);
 extern bool testSimplify(skiatest::Reporter* reporter, const SkPath& path);
diff --git a/tests/PathOpsLineIntersectionTest.cpp b/tests/PathOpsLineIntersectionTest.cpp
index be40ae4..f2bef91 100644
--- a/tests/PathOpsLineIntersectionTest.cpp
+++ b/tests/PathOpsLineIntersectionTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsLine.h"
 #include "Test.h"
@@ -61,6 +62,8 @@
 }
 
 static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2) {
+    SkASSERT(ValidLine(line1));
+    SkASSERT(ValidLine(line2));
     SkIntersections i;
     int pts = i.intersect(line1, line2);
     REPORTER_ASSERT(reporter, pts);
@@ -101,6 +104,8 @@
 
 static void testOneCoincident(skiatest::Reporter* reporter, const SkDLine& line1,
                               const SkDLine& line2) {
+    SkASSERT(ValidLine(line1));
+    SkASSERT(ValidLine(line2));
     SkIntersections ts2;
     int pts2 = ts2.intersect(line1, line2);
     REPORTER_ASSERT(reporter, pts2 == 2);
diff --git a/tests/PathOpsLineParametetersTest.cpp b/tests/PathOpsLineParametetersTest.cpp
index c8f8be7..5226382 100644
--- a/tests/PathOpsLineParametetersTest.cpp
+++ b/tests/PathOpsLineParametetersTest.cpp
@@ -4,6 +4,7 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+#include "PathOpsTestCommon.h"
 #include "SkLineParameters.h"
 #include "Test.h"
 
@@ -40,6 +41,7 @@
     for (size_t index = 0; index < tests_count; ++index) {
         SkLineParameters lineParameters;
         const SkDCubic& cubic = tests[index];
+        SkASSERT(ValidCubic(cubic));
         lineParameters.cubicEndPoints(cubic, 0, 3);
         double denormalizedDistance[2];
         denormalizedDistance[0] = lineParameters.controlPtDistance(cubic, 1);
diff --git a/tests/PathOpsOpCubicThreadedTest.cpp b/tests/PathOpsOpCubicThreadedTest.cpp
index 0ccb89d..99e68da 100644
--- a/tests/PathOpsOpCubicThreadedTest.cpp
+++ b/tests/PathOpsOpCubicThreadedTest.cpp
@@ -15,7 +15,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];  // gdb: set print elements 400
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     for (int a = 0 ; a < 6; ++a) {
         for (int b = a + 1 ; b < 7; ++b) {
             for (int c = 0 ; c < 6; ++c) {
@@ -23,34 +26,38 @@
                     for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
     for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) {
         SkPath pathA, pathB;
-        char* str = pathStr;
+        if (progress) {
+            char* str = pathStr;
+            str += sprintf(str, "    path.setFillType(SkPath::k%s_FillType);\n",
+                    e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            str += sprintf(str, "    path.moveTo(%d,%d);\n", state.fA, state.fB);
+            str += sprintf(str, "    path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.fC, state.fD,
+                    b, a, d, c);
+            str += sprintf(str, "    path.close();\n");
+            str += sprintf(str, "    pathB.setFillType(SkPath::k%s_FillType);\n",
+                    f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            str += sprintf(str, "    pathB.moveTo(%d,%d);\n", a, b);
+            str += sprintf(str, "    pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
+                    state.fB, state.fA, state.fD, state.fC);
+            str += sprintf(str, "    pathB.close();\n");
+        }
         pathA.setFillType((SkPath::FillType) e);
-        str += sprintf(str, "    path.setFillType(SkPath::k%s_FillType);\n",
-                e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
-                ? "EvenOdd" : "?UNDEFINED");
         pathA.moveTo(SkIntToScalar(state.fA), SkIntToScalar(state.fB));
-        str += sprintf(str, "    path.moveTo(%d,%d);\n", state.fA, state.fB);
         pathA.cubicTo(SkIntToScalar(state.fC), SkIntToScalar(state.fD), SkIntToScalar(b),
                 SkIntToScalar(a), SkIntToScalar(d), SkIntToScalar(c));
-        str += sprintf(str, "    path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.fC, state.fD,
-                b, a, d, c);
         pathA.close();
-        str += sprintf(str, "    path.close();\n");
         pathB.setFillType((SkPath::FillType) f);
-        str += sprintf(str, "    pathB.setFillType(SkPath::k%s_FillType);\n",
-                f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
-                ? "EvenOdd" : "?UNDEFINED");
         pathB.moveTo(SkIntToScalar(a), SkIntToScalar(b));
-        str += sprintf(str, "    pathB.moveTo(%d,%d);\n", a, b);
         pathB.cubicTo(SkIntToScalar(c), SkIntToScalar(d), SkIntToScalar(state.fB),
                 SkIntToScalar(state.fA), SkIntToScalar(state.fD), SkIntToScalar(state.fC));
-        str += sprintf(str, "    pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
-                state.fB, state.fA, state.fD, state.fC);
         pathB.close();
-        str += sprintf(str, "    pathB.close();\n");
         for (int op = 0 ; op <= kXOR_PathOp; ++op)    {
-            outputProgress(state.fPathStr, pathStr, (SkPathOp) op);
-            testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op);
+            if (progress) {
+                outputProgress(state.fPathStr, pathStr, (SkPathOp) op);
+            }
+            testThreadedPathOp(state.fReporter, pathA, pathB, (SkPathOp) op);
         }
     }
                     }
diff --git a/tests/PathOpsOpRectThreadedTest.cpp b/tests/PathOpsOpRectThreadedTest.cpp
index 58e4707..59a0d54 100644
--- a/tests/PathOpsOpRectThreadedTest.cpp
+++ b/tests/PathOpsOpRectThreadedTest.cpp
@@ -19,44 +19,51 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];  // gdb: set print elements 400
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     for (int a = 0 ; a < 6; ++a) {
         for (int b = a + 1 ; b < 7; ++b) {
             for (int c = 0 ; c < 6; ++c) {
                 for (int d = c + 1 ; d < 7; ++d) {
                     for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
     for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f)   {
+        if (progress) {
+            char* str = pathStr;
+            str += sprintf(str, "    path.setFillType(SkPath::k%s_FillType);\n",
+                    e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                    " SkPath::kCW_Direction);\n", state.fA, state.fA, state.fB, state.fB);
+            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                    " SkPath::kCW_Direction);\n", state.fC, state.fC, state.fD, state.fD);
+            str += sprintf(str, "    pathB.setFillType(SkPath::k%s_FillType);\n",
+                    f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
+                    ? "EvenOdd" : "?UNDEFINED");
+            str += sprintf(str, "    pathB.addRect(%d, %d, %d, %d,"
+                    " SkPath::kCW_Direction);\n", a, a, b, b);
+            str += sprintf(str, "    pathB.addRect(%d, %d, %d, %d,"
+                    " SkPath::kCW_Direction);\n", c, c, d, d);
+        }
         SkPath pathA, pathB;
-        char* str = pathStr;
         pathA.setFillType((SkPath::FillType) e);
-        str += sprintf(str, "    path.setFillType(SkPath::k%s_FillType);\n",
-                e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
-                ? "EvenOdd" : "?UNDEFINED");
         pathA.addRect(SkIntToScalar(state.fA), SkIntToScalar(state.fA), SkIntToScalar(state.fB),
                 SkIntToScalar(state.fB), SkPath::kCW_Direction);
-        str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                " SkPath::kCW_Direction);\n", state.fA, state.fA, state.fB, state.fB);
         pathA.addRect(SkIntToScalar(state.fC), SkIntToScalar(state.fC), SkIntToScalar(state.fD),
                 SkIntToScalar(state.fD), SkPath::kCW_Direction);
-        str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                " SkPath::kCW_Direction);\n", state.fC, state.fC, state.fD, state.fD);
         pathA.close();
         pathB.setFillType((SkPath::FillType) f);
-        str += sprintf(str, "    pathB.setFillType(SkPath::k%s_FillType);\n",
-                f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
-                ? "EvenOdd" : "?UNDEFINED");
         pathB.addRect(SkIntToScalar(a), SkIntToScalar(a), SkIntToScalar(b),
                 SkIntToScalar(b), SkPath::kCW_Direction);
-        str += sprintf(str, "    pathB.addRect(%d, %d, %d, %d,"
-                " SkPath::kCW_Direction);\n", a, a, b, b);
         pathB.addRect(SkIntToScalar(c), SkIntToScalar(c), SkIntToScalar(d),
                 SkIntToScalar(d), SkPath::kCW_Direction);
-        str += sprintf(str, "    pathB.addRect(%d, %d, %d, %d,"
-                " SkPath::kCW_Direction);\n", c, c, d, d);
         pathB.close();
         for (int op = 0 ; op <= kXOR_PathOp; ++op)    {
-            outputProgress(state.fPathStr, pathStr, (SkPathOp) op);
-            testPathOp(state.fReporter, pathA, pathB, (SkPathOp) op);
+            if (progress) {
+                outputProgress(state.fPathStr, pathStr, (SkPathOp) op);
+            }
+            testThreadedPathOp(state.fReporter, pathA, pathB, (SkPathOp) op);
         }
     }
                     }
diff --git a/tests/PathOpsQuadIntersectionTest.cpp b/tests/PathOpsQuadIntersectionTest.cpp
index a060c8c..ee2e8de 100644
--- a/tests/PathOpsQuadIntersectionTest.cpp
+++ b/tests/PathOpsQuadIntersectionTest.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 #include "PathOpsQuadIntersectionTestData.h"
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsRect.h"
 #include "SkReduceOrder.h"
@@ -14,7 +15,9 @@
     bool showSkipped = false;
     for (size_t index = 0; index < quadraticTests_count; ++index) {
         const SkDQuad& quad1 = quadraticTests[index][0];
+        SkASSERT(ValidQuad(quad1));
         const SkDQuad& quad2 = quadraticTests[index][1];
+        SkASSERT(ValidQuad(quad2));
         SkReduceOrder reduce1, reduce2;
         int order1 = reduce1.reduce(quad1, SkReduceOrder::kFill_Style);
         int order2 = reduce2.reduce(quad2, SkReduceOrder::kFill_Style);
@@ -246,7 +249,9 @@
 
 static void oneOffTest1(skiatest::Reporter* reporter, size_t outer, size_t inner) {
     const SkDQuad& quad1 = testSet[outer];
+    SkASSERT(ValidQuad(quad1));
     const SkDQuad& quad2 = testSet[inner];
+    SkASSERT(ValidQuad(quad2));
     SkIntersections intersections2;
     intersections2.intersect(quad1, quad2);
     for (int pt = 0; pt < intersections2.used(); ++pt) {
@@ -291,7 +296,9 @@
 static void coincidentTest(skiatest::Reporter* reporter) {
     for (size_t testIndex = 0; testIndex < coincidentTestSetCount - 1; testIndex += 2) {
         const SkDQuad& quad1 = coincidentTestSet[testIndex];
+        SkASSERT(ValidQuad(quad1));
         const SkDQuad& quad2 = coincidentTestSet[testIndex + 1];
+        SkASSERT(ValidQuad(quad2));
         SkIntersections intersections2;
         intersections2.intersect(quad1, quad2);
         REPORTER_ASSERT(reporter, intersections2.coincidentUsed() == 2);
diff --git a/tests/PathOpsQuadLineIntersectionTest.cpp b/tests/PathOpsQuadLineIntersectionTest.cpp
index 4227ee5..02c925c 100644
--- a/tests/PathOpsQuadLineIntersectionTest.cpp
+++ b/tests/PathOpsQuadLineIntersectionTest.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 #include "PathOpsExtendedTest.h"
+#include "PathOpsTestCommon.h"
 #include "SkIntersections.h"
 #include "SkPathOpsLine.h"
 #include "SkPathOpsQuad.h"
@@ -72,7 +73,9 @@
     bool flipped = false;
     for (size_t index = 0; index < oneOffs_count; ++index) {
         const SkDQuad& quad = oneOffs[index].quad;
+        SkASSERT(ValidQuad(quad));
         const SkDLine& line = oneOffs[index].line;
+        SkASSERT(ValidLine(line));
         SkIntersections intersections;
         int result = doIntersect(intersections, quad, line, flipped);
         for (int inner = 0; inner < result; ++inner) {
@@ -93,7 +96,9 @@
     for (size_t index = 0; index < lineQuadTests_count; ++index) {
         int iIndex = static_cast<int>(index);
         const SkDQuad& quad = lineQuadTests[index].quad;
+        SkASSERT(ValidQuad(quad));
         const SkDLine& line = lineQuadTests[index].line;
+        SkASSERT(ValidLine(line));
         SkReduceOrder reducer1, reducer2;
         int order1 = reducer1.reduce(quad, SkReduceOrder::kFill_Style);
         int order2 = reducer2.reduce(line);
diff --git a/tests/PathOpsSimplifyDegenerateThreadedTest.cpp b/tests/PathOpsSimplifyDegenerateThreadedTest.cpp
index 22997e7..9ed1f3a 100755
--- a/tests/PathOpsSimplifyDegenerateThreadedTest.cpp
+++ b/tests/PathOpsSimplifyDegenerateThreadedTest.cpp
@@ -11,7 +11,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     int ax = state.fA & 0x03;
     int ay = state.fA >> 2;
     int bx = state.fB & 0x03;
@@ -41,19 +44,23 @@
                 path.lineTo(SkIntToScalar(ex), SkIntToScalar(ey));
                 path.lineTo(SkIntToScalar(fx), SkIntToScalar(fy));
                 path.close();
-                char* str = pathStr;
-                str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                str += sprintf(str, "    path.close();\n");
-                str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                str += sprintf(str, "    path.close();\n");
-                outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                if (progress) {
+                    char* str = pathStr;
+                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
+                    str += sprintf(str, "    path.close();\n");
+                    str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                    str += sprintf(str, "    path.close();\n");
+                    outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                }
                 testSimplify(path, false, out, state, pathStr);
                 path.setFillType(SkPath::kEvenOdd_FillType);
-                outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                if (progress) {
+                    outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                }
                 testSimplify(path, true, out, state, pathStr);
             }
         }
diff --git a/tests/PathOpsSimplifyQuadThreadedTest.cpp b/tests/PathOpsSimplifyQuadThreadedTest.cpp
index 8dea049..d1e0dac 100644
--- a/tests/PathOpsSimplifyQuadThreadedTest.cpp
+++ b/tests/PathOpsSimplifyQuadThreadedTest.cpp
@@ -12,7 +12,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     int ax = state.fA & 0x03;
     int ay = state.fA >> 2;
     int bx = state.fB & 0x03;
@@ -45,20 +48,24 @@
                     path.quadTo(SkIntToScalar(gx), SkIntToScalar(gy),
                             SkIntToScalar(hx), SkIntToScalar(hy));
                     path.close();
-                    // gdb: set print elements 400
-                    char* str = pathStr;
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                    str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", bx, by, cx, cy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
-                    str += sprintf(str, "    path.close();\n");
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                    str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", gx, gy, hx, hy);
-                    str += sprintf(str, "    path.close();\n");
-                    outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                    if (progress) {
+                        // gdb: set print elements 400
+                        char* str = pathStr;
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                        str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", bx, by, cx, cy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
+                        str += sprintf(str, "    path.close();\n");
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                        str += sprintf(str, "    path.quadTo(%d, %d, %d, %d);\n", gx, gy, hx, hy);
+                        str += sprintf(str, "    path.close();\n");
+                        outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                    }
                     testSimplify(path, false, out, state, pathStr);
                     path.setFillType(SkPath::kEvenOdd_FillType);
-                    outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                    if (progress) {
+                        outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                    }
                     testSimplify(path, true, out, state, pathStr);
                 }
             }
diff --git a/tests/PathOpsSimplifyQuadralateralsThreadedTest.cpp b/tests/PathOpsSimplifyQuadralateralsThreadedTest.cpp
index 5afadbe..96960b5 100755
--- a/tests/PathOpsSimplifyQuadralateralsThreadedTest.cpp
+++ b/tests/PathOpsSimplifyQuadralateralsThreadedTest.cpp
@@ -12,7 +12,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     int ax = state.fA & 0x03;
     int ay = state.fA >> 2;
     int bx = state.fB & 0x03;
@@ -45,22 +48,26 @@
                     path.lineTo(SkIntToScalar(gx), SkIntToScalar(gy));
                     path.lineTo(SkIntToScalar(hx), SkIntToScalar(hy));
                     path.close();
-                   // gdb: set print elements 400
-                    char* str = pathStr;
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
-                    str += sprintf(str, "    path.close();\n");
-                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", gx, gy);
-                    str += sprintf(str, "    path.lineTo(%d, %d);\n", hx, hy);
-                    str += sprintf(str, "    path.close();\n");
-                    outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                    if (progress) {
+                       // gdb: set print elements 400
+                        char* str = pathStr;
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", dx, dy);
+                        str += sprintf(str, "    path.close();\n");
+                        str += sprintf(str, "    path.moveTo(%d, %d);\n", ex, ey);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", gx, gy);
+                        str += sprintf(str, "    path.lineTo(%d, %d);\n", hx, hy);
+                        str += sprintf(str, "    path.close();\n");
+                        outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                    }
                     testSimplify(path, false, out, state, pathStr);
                     path.setFillType(SkPath::kEvenOdd_FillType);
-                    outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                    if (progress) {
+                        outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                    }
                     testSimplify(path, true, out, state, pathStr);
                 }
             }
diff --git a/tests/PathOpsSimplifyRectThreadedTest.cpp b/tests/PathOpsSimplifyRectThreadedTest.cpp
index 66b70d3..6ed6a7b 100644
--- a/tests/PathOpsSimplifyRectThreadedTest.cpp
+++ b/tests/PathOpsSimplifyRectThreadedTest.cpp
@@ -19,7 +19,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];  // gdb: set print elements 400
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     int aShape = state.fA & 0x03;
     SkPath::Direction aCW = state.fA >> 2 ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
     int bShape = state.fB & 0x03;
@@ -63,8 +66,10 @@
             }
             path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b),
                     aCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " SkPath::kC%sW_Direction);\n", l, t, r, b, aCW ? "C" : "");
+            if (progress) {
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " SkPath::kC%sW_Direction);\n", l, t, r, b, aCW ? "C" : "");
+            }
         } else {
             aXAlign = 5;
             aYAlign = 5;
@@ -92,8 +97,10 @@
             }
             path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b),
                     bCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " SkPath::kC%sW_Direction);\n", l, t, r, b, bCW ? "C" : "");
+            if (progress) {
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " SkPath::kC%sW_Direction);\n", l, t, r, b, bCW ? "C" : "");
+            }
         } else {
             bXAlign = 5;
             bYAlign = 5;
@@ -121,8 +128,10 @@
             }
             path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b),
                     cCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " SkPath::kC%sW_Direction);\n", l, t, r, b, cCW ? "C" : "");
+            if (progress) {
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " SkPath::kC%sW_Direction);\n", l, t, r, b, cCW ? "C" : "");
+            }
         } else {
             cXAlign = 5;
             cYAlign = 5;
@@ -150,16 +159,22 @@
             }
             path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b),
                     dCW);
-            str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
-                    " SkPath::kC%sW_Direction);\n", l, t, r, b, dCW ? "C" : "");
+            if (progress) {
+                str += sprintf(str, "    path.addRect(%d, %d, %d, %d,"
+                        " SkPath::kC%sW_Direction);\n", l, t, r, b, dCW ? "C" : "");
+            }
         } else {
             dXAlign = 5;
             dYAlign = 5;
         }
         path.close();
-        outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+        if (progress) {
+            outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+        }
         testSimplify(path, false, out, state, pathStr);
-        outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+        if (progress) {
+            outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+        }
         testSimplify(path, true, out, state, pathStr);
     }
                             }
diff --git a/tests/PathOpsSimplifyTrianglesThreadedTest.cpp b/tests/PathOpsSimplifyTrianglesThreadedTest.cpp
index 8d1e8db..0b821d6 100755
--- a/tests/PathOpsSimplifyTrianglesThreadedTest.cpp
+++ b/tests/PathOpsSimplifyTrianglesThreadedTest.cpp
@@ -11,7 +11,10 @@
     SkASSERT(data);
     PathOpsThreadState& state = *data;
     char pathStr[1024];
-    sk_bzero(pathStr, sizeof(pathStr));
+    bool progress = state.fReporter->verbose(); // FIXME: break out into its own parameter?
+    if (progress) {
+        sk_bzero(pathStr, sizeof(pathStr));
+    }
     state.fKey = "?";
     int ax = state.fA & 0x03;
     int ay = state.fA >> 2;
@@ -44,20 +47,24 @@
                 path.lineTo(SkIntToScalar(ex), SkIntToScalar(ey));
                 path.lineTo(SkIntToScalar(fx), SkIntToScalar(fy));
                 path.close();
-                char* str = pathStr;
-                str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
-                str += sprintf(str, "    path.close();\n");
-                str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
-                str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
-                str += sprintf(str, "    path.close();\n");
-                outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                if (progress) {
+                    char* str = pathStr;
+                    str += sprintf(str, "    path.moveTo(%d, %d);\n", ax, ay);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", bx, by);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", cx, cy);
+                    str += sprintf(str, "    path.close();\n");
+                    str += sprintf(str, "    path.moveTo(%d, %d);\n", dx, dy);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", ex, ey);
+                    str += sprintf(str, "    path.lineTo(%d, %d);\n", fx, fy);
+                    str += sprintf(str, "    path.close();\n");
+                    outputProgress(state.fPathStr, pathStr, SkPath::kWinding_FillType);
+                }
                 ShowTestName(&state, d, e, f, 0);
                 testSimplify(path, false, out, state, pathStr);
                 path.setFillType(SkPath::kEvenOdd_FillType);
-                outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                if (progress) {
+                    outputProgress(state.fPathStr, pathStr, SkPath::kEvenOdd_FillType);
+                }
                 ShowTestName(&state, d, e, f, 1);
                 testSimplify(path, true, out, state, pathStr);
             }
diff --git a/tests/PathOpsTestCommon.cpp b/tests/PathOpsTestCommon.cpp
index 4356b42..dd9b347 100644
--- a/tests/PathOpsTestCommon.cpp
+++ b/tests/PathOpsTestCommon.cpp
@@ -5,7 +5,11 @@
  * found in the LICENSE file.
  */
 #include "PathOpsTestCommon.h"
+#include "SkPathOpsBounds.h"
 #include "SkPathOpsCubic.h"
+#include "SkPathOpsLine.h"
+#include "SkPathOpsQuad.h"
+#include "SkPathOpsTriangle.h"
 
 void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads) {
     SkTArray<double, true> ts;
@@ -24,3 +28,82 @@
         tStart = tEnd;
     }
 }
+
+static bool SkDoubleIsNaN(double x) {
+    return x != x;
+}
+
+bool ValidBounds(const SkPathOpsBounds& bounds) {
+    if (SkScalarIsNaN(bounds.fLeft)) {
+        return false;
+    }
+    if (SkScalarIsNaN(bounds.fTop)) {
+        return false;
+    }
+    if (SkScalarIsNaN(bounds.fRight)) {
+        return false;
+    }
+    return !SkScalarIsNaN(bounds.fBottom);
+}
+
+bool ValidCubic(const SkDCubic& cubic) {
+    for (int index = 0; index < 4; ++index) {
+        if (!ValidPoint(cubic[index])) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidLine(const SkDLine& line) {
+    for (int index = 0; index < 2; ++index) {
+        if (!ValidPoint(line[index])) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidPoint(const SkDPoint& pt) {
+    if (SkDoubleIsNaN(pt.fX)) {
+        return false;
+    }
+    return !SkDoubleIsNaN(pt.fY);  
+}
+
+bool ValidPoints(const SkPoint* pts, int count) {
+    for (int index = 0; index < count; ++index) {
+        if (SkScalarIsNaN(pts[index].fX)) {
+            return false;
+        }
+        if (SkScalarIsNaN(pts[index].fY)) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidQuad(const SkDQuad& quad) {
+    for (int index = 0; index < 3; ++index) {
+        if (!ValidPoint(quad[index])) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidTriangle(const SkDTriangle& triangle) {
+    for (int index = 0; index < 3; ++index) {
+        if (!ValidPoint(triangle.fPts[index])) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool ValidVector(const SkDVector& v) {
+    if (SkDoubleIsNaN(v.fX)) {
+        return false;
+    }
+    return !SkDoubleIsNaN(v.fY);  
+}
diff --git a/tests/PathOpsTestCommon.h b/tests/PathOpsTestCommon.h
index 5072ad6..78f2e90 100644
--- a/tests/PathOpsTestCommon.h
+++ b/tests/PathOpsTestCommon.h
@@ -10,6 +10,16 @@
 #include "SkPathOpsQuad.h"
 #include "SkTArray.h"
 
+struct SkPathOpsBounds;
+
 void CubicToQuads(const SkDCubic& cubic, double precision, SkTArray<SkDQuad, true>& quads);
+bool ValidBounds(const SkPathOpsBounds&);
+bool ValidCubic(const SkDCubic& cubic);
+bool ValidLine(const SkDLine& line);
+bool ValidPoint(const SkDPoint& pt);
+bool ValidPoints(const SkPoint* pts, int count);
+bool ValidQuad(const SkDQuad& quad);
+bool ValidTriangle(const SkDTriangle& triangle);
+bool ValidVector(const SkDVector& v);
 
 #endif
diff --git a/tests/Test.cpp b/tests/Test.cpp
index 32c293e..61e1653 100644
--- a/tests/Test.cpp
+++ b/tests/Test.cpp
@@ -84,6 +84,10 @@
             fReporter->bumpTestCount();
         }
 
+        virtual bool verbose() const SK_OVERRIDE {
+            return fReporter->verbose();
+        }
+
     private:
         Reporter* fReporter;  // Unowned.
         SkTArray<SkString> fFailures;
diff --git a/tests/skia_test.cpp b/tests/skia_test.cpp
index dc1015d..da63d42 100644
--- a/tests/skia_test.cpp
+++ b/tests/skia_test.cpp
@@ -125,7 +125,7 @@
 DEFINE_string2(tmpDir, t, NULL, "tmp directory for tests to use.");
 DEFINE_string2(resourcePath, i, NULL, "directory for test resources.");
 DEFINE_bool2(extendedTest, x, false, "run extended tests for pathOps.");
-DEFINE_bool2(threaded, z, false, "allow tests to use multiple threads internally.");
+DEFINE_bool2(single, z, false, "run tests on a single thread internally.");
 DEFINE_bool2(verbose, v, false, "enable verbose output.");
 DEFINE_int32(threads, SkThreadPool::kThreadPerCore,
              "Run threadsafe tests on a threadpool with this many threads.");
@@ -237,7 +237,7 @@
         SkDebugf("%s\n", header.c_str());
     }
 
-    DebugfReporter reporter(FLAGS_extendedTest, FLAGS_threaded, FLAGS_verbose);
+    DebugfReporter reporter(FLAGS_extendedTest, !FLAGS_single, FLAGS_verbose);
     Iter iter(&reporter);
 
     // Count tests first.