add json dump to pathops unittest

./out/skia/pathops_unittest -J dump.json
will write all Op tests to a JSON file. Since this
will run single threaded, this can take a while,
and generates a 500M file.
A reasonable subset is
./out/skia/pathops_unittest -J dump.json -m PathOpsOp$
around 275K.

This is in service of pathkit.

R=kjlubick@google.com

Bug: skia:
Change-Id: I7e0771639e29755c00036f335a531403044d9d30
Reviewed-on: https://skia-review.googlesource.com/145737
Commit-Queue: Cary Clark <caryclark@skia.org>
Auto-Submit: Cary Clark <caryclark@skia.org>
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/tests/PathOpsExtendedTest.cpp b/tests/PathOpsExtendedTest.cpp
index 232918f..2fecf36 100644
--- a/tests/PathOpsExtendedTest.cpp
+++ b/tests/PathOpsExtendedTest.cpp
@@ -5,6 +5,7 @@
  * found in the LICENSE file.
  */
 
+#include "PathOpsDebug.h"
 #include "PathOpsExtendedTest.h"
 #include "PathOpsThreadedCommon.h"
 #include "SkBitmap.h"
@@ -12,6 +13,7 @@
 #include "SkMatrix.h"
 #include "SkMutex.h"
 #include "SkPaint.h"
+#include "SkParsePath.h"
 #include "SkRegion.h"
 #include "SkStream.h"
 
@@ -534,12 +536,50 @@
 }
 #endif
 
+static void json_status(ExpectSuccess expectSuccess, ExpectMatch expectMatch, bool opSucceeded) {
+    fprintf(PathOpsDebug::gOut, "  \"expectSuccess\": \"%s\",\n",
+            ExpectSuccess::kNo == expectSuccess ? "no" :
+            ExpectSuccess::kYes == expectSuccess ? "yes" : "flaky");
+    fprintf(PathOpsDebug::gOut, "  \"expectMatch\": \"%s\",\n",
+            ExpectMatch::kNo == expectMatch ? "no" :
+            ExpectMatch::kYes == expectMatch ? "yes" : "flaky");
+    fprintf(PathOpsDebug::gOut, "  \"succeeded\": %s,\n", opSucceeded ? "true" : "false");
+}
+
+static void json_path_out(const SkPath& path, const char* pathName, const char* fillTypeName,
+        bool lastField) {
+    char const * const gFillTypeStrs[] = {
+        "Winding",
+        "EvenOdd",
+        "InverseWinding",
+        "InverseEvenOdd",
+    };
+    SkString svg;
+    SkParsePath::ToSVGString(path, &svg);
+    fprintf(PathOpsDebug::gOut, "  \"%s\": \"%s\",\n", pathName, svg.c_str());
+    fprintf(PathOpsDebug::gOut, "  \"fillType%s\": \"k%s_FillType\"%s", fillTypeName,
+            gFillTypeStrs[(int) path.getFillType()], lastField ? "\n}" : ",\n");
+}
+
 static bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b,
         const SkPathOp shapeOp, const char* testName, ExpectSuccess expectSuccess,
         SkipAssert skipAssert, ExpectMatch expectMatch) {
 #if 0 && DEBUG_SHOW_TEST_NAME
     showName(a, b, shapeOp);
 #endif
+    if (PathOpsDebug::gJson) {
+        SkString aStr, bStr;
+        SkParsePath::ToSVGString(a, &aStr);
+        SkParsePath::ToSVGString(b, &bStr);
+        if (!PathOpsDebug::gOutFirst) {
+            fprintf(PathOpsDebug::gOut, ",\n");
+        }
+        PathOpsDebug::gOutFirst = false;
+        fprintf(PathOpsDebug::gOut, "\"%s\": {\n", testName);
+        json_path_out(a, "p1", "1", false);
+        json_path_out(b, "p2", "2", false);
+        fprintf(PathOpsDebug::gOut, "  \"op\": \"%s\",\n", opStrs[shapeOp]);
+    }
     SkPath out;
     if (!OpDebug(a, b, shapeOp, &out  SkDEBUGPARAMS(SkipAssert::kYes == skipAssert)
             SkDEBUGPARAMS(testName))) {
@@ -547,12 +587,20 @@
             SkDebugf("%s %s did not expect failure\n", __FUNCTION__, testName);
             REPORTER_ASSERT(reporter, 0);
         }
+        if (PathOpsDebug::gJson) {
+            json_status(expectSuccess, expectMatch, false);
+            fprintf(PathOpsDebug::gOut, "  \"out\": \"\"\n}");
+        }
         return false;
     } else {
         if (ExpectSuccess::kNo == expectSuccess) {
                 SkDebugf("%s %s unexpected success\n", __FUNCTION__, testName);
                 REPORTER_ASSERT(reporter, 0);
         }
+        if (PathOpsDebug::gJson) {
+            json_status(expectSuccess, expectMatch, true);
+            json_path_out(out, "out", "Out", true);
+        }
     }
     if (!reporter->verbose()) {
         return true;