SkPDF/Tests: imporve test coverage.

Also: make sure that all SkPDF unit tests are named SkPDF_* to
make testing changes to SkPDF easier.  Other cleanup.

Add test: SkPDF_pdfa_document to verify that flag in public API
works.

SkPDF_JpegIdentification test: test slightly malformed JPEGs to
verify that all code paths work.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2322133003

Review-Url: https://codereview.chromium.org/2322133003
diff --git a/tests/PDFDeflateWStreamTest.cpp b/tests/PDFDeflateWStreamTest.cpp
index 2627508..eedcaaf 100644
--- a/tests/PDFDeflateWStreamTest.cpp
+++ b/tests/PDFDeflateWStreamTest.cpp
@@ -101,7 +101,7 @@
 }
 }  // namespace
 
-DEF_TEST(SkDeflateWStream, r) {
+DEF_TEST(SkPDF_DeflateWStream, r) {
     SkRandom random(123456);
     for (int i = 0; i < 50; ++i) {
         uint32_t size = random.nextULessThan(10000);
@@ -123,6 +123,7 @@
                 }
                 j += writeSize;
             }
+            REPORTER_ASSERT(r, deflateWStream.bytesWritten() == size);
         }
         SkAutoTDelete<SkStreamAsset> compressed(
                 dynamicMemoryWStream.detachAsStream());
@@ -159,4 +160,6 @@
             }
         }
     }
+    SkDeflateWStream emptyDeflateWStream(nullptr);
+    REPORTER_ASSERT(r, !emptyDeflateWStream.writeText("FOO"));
 }
diff --git a/tests/PDFDocumentTest.cpp b/tests/PDFDocumentTest.cpp
index b763742..c871375 100644
--- a/tests/PDFDocumentTest.cpp
+++ b/tests/PDFDocumentTest.cpp
@@ -105,7 +105,7 @@
     REPORTER_ASSERT(reporter, stream.bytesWritten() != 0);
 }
 
-DEF_TEST(document_tests, reporter) {
+DEF_TEST(SkPDF_document_tests, reporter) {
     REQUIRE_PDF_DOCUMENT(document_tests, reporter);
     test_empty(reporter);
     test_abort(reporter);
@@ -147,8 +147,8 @@
     return stream.bytesWritten();
 }
 
-DEF_TEST(document_dct_encoder, r) {
-    REQUIRE_PDF_DOCUMENT(document_dct_encoder, r);
+DEF_TEST(SkPDF_document_dct_encoder, r) {
+    REQUIRE_PDF_DOCUMENT(SkPDF_document_dct_encoder, r);
     SkBitmap bm;
     if (GetResourceAsBitmap("mandrill_64.png", &bm)) {
         // Lossy encoding works better on photographs.
@@ -156,8 +156,8 @@
     }
 }
 
-DEF_TEST(document_skbug_4734, r) {
-    REQUIRE_PDF_DOCUMENT(document_skbug_4734, r);
+DEF_TEST(SkPDF_document_skbug_4734, r) {
+    REQUIRE_PDF_DOCUMENT(SkPDF_document_skbug_4734, r);
     SkDynamicMemoryWStream stream;
     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
     SkCanvas* canvas = doc->beginPage(64, 64);
@@ -167,3 +167,63 @@
     const char text[] = "HELLO";
     canvas->drawText(text, strlen(text), 0, 0, SkPaint());
 }
+
+static bool contains(const uint8_t* result, size_t size, const char expectation[]) {
+    size_t len = strlen(expectation);
+    size_t N = 1 + size - len;
+    for (size_t i = 0; i < N; ++i) {
+        if (0 == memcmp(result + i, expectation, len)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// verify that the PDFA flag does something.
+DEF_TEST(SkPDF_pdfa_document, r) {
+    REQUIRE_PDF_DOCUMENT(SkPDF_pdfa_document, r);
+
+    SkDocument::PDFMetadata pdfMetadata;
+    pdfMetadata.fTitle = "test document";
+    pdfMetadata.fCreation.fEnabled = true;
+    pdfMetadata.fCreation.fDateTime = {0, 1999, 12, 5, 31, 23, 59, 59};
+
+    SkDynamicMemoryWStream buffer;
+    auto doc = SkDocument::MakePDF(&buffer, SK_ScalarDefaultRasterDPI,
+                                   pdfMetadata, nullptr, /* pdfa = */ true);
+    doc->beginPage(64, 64)->drawColor(SK_ColorRED);
+    doc->close();
+    sk_sp<SkData> data(buffer.copyToData());
+    buffer.reset();
+    static const char* expectations[] = {
+        "sRGB IEC61966-2.1",
+        "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">test document",
+        "<xmp:CreateDate>1999-12-31T23:59:59+00:00</xmp:CreateDate>",
+        "/Subtype /XML",
+        "/CreationDate (D:19991231235959+00'00')>>",
+    };
+    for (const char* expectation : expectations) {
+        if (!contains(data->bytes(), data->size(), expectation)) {
+            ERRORF(r, "PDFA expectation missing: '%s'.", expectation);
+        }
+    }
+    pdfMetadata.fProducer = "phoney library";
+    doc = SkDocument::MakePDF(&buffer, SK_ScalarDefaultRasterDPI,
+                              pdfMetadata, nullptr, /* pdfa = */ true);
+    doc->beginPage(64, 64)->drawColor(SK_ColorRED);
+    doc->close();
+    data.reset(buffer.copyToData());
+    buffer.reset();
+
+    static const char* moreExpectations[] = {
+        "/Producer (phoney library)",
+        "/ProductionLibrary (Skia/PDF m",
+        "<!-- <skia:ProductionLibrary>Skia/PDF m",
+        "<pdf:Producer>phoney library</pdf:Producer>",
+    };
+    for (const char* expectation : moreExpectations) {
+        if (!contains(data->bytes(), data->size(), expectation)) {
+            ERRORF(r, "PDFA expectation missing: '%s'.", expectation);
+        }
+    }
+}
diff --git a/tests/PDFGlyphsToUnicodeTest.cpp b/tests/PDFGlyphsToUnicodeTest.cpp
index 3ba8870..f65ee3e 100644
--- a/tests/PDFGlyphsToUnicodeTest.cpp
+++ b/tests/PDFGlyphsToUnicodeTest.cpp
@@ -25,7 +25,7 @@
     return memcmp(data->bytes() + offset, buffer, len) == 0;
 }
 
-DEF_TEST(ToUnicode, reporter) {
+DEF_TEST(SkPDF_ToUnicode, reporter) {
     SkTDArray<SkUnichar> glyphToUnicode;
     SkTDArray<uint16_t> glyphsInSubset;
     SkBitSet subset(kMaximumGlyphCount);
diff --git a/tests/PDFInvalidBitmapTest.cpp b/tests/PDFInvalidBitmapTest.cpp
index c9685f7..10292bd 100644
--- a/tests/PDFInvalidBitmapTest.cpp
+++ b/tests/PDFInvalidBitmapTest.cpp
@@ -43,9 +43,12 @@
 
 }  // namespace
 
-DEF_TEST(PDFInvalidBitmap, reporter) {
+DEF_TEST(SkPDF_InvalidBitmap, reporter) {
     SkDynamicMemoryWStream stream;
     sk_sp<SkDocument> document(SkDocument::MakePDF(&stream));
+    if (!document) {
+        return;
+    }
     SkCanvas* canvas = document->beginPage(100, 100);
 
     canvas->drawBitmap(SkBitmap(), 0, 0);
diff --git a/tests/PDFJpegEmbedTest.cpp b/tests/PDFJpegEmbedTest.cpp
index b199c80..93c2044 100644
--- a/tests/PDFJpegEmbedTest.cpp
+++ b/tests/PDFJpegEmbedTest.cpp
@@ -5,10 +5,11 @@
  * found in the LICENSE file.
  */
 
-#include "SkDocument.h"
 #include "SkCanvas.h"
-#include "SkImageGenerator.h"
 #include "SkData.h"
+#include "SkDocument.h"
+#include "SkImageGenerator.h"
+#include "SkJpegInfo.h"
 #include "SkStream.h"
 
 #include "Resources.h"
@@ -54,8 +55,9 @@
  *  directly embedded into the PDF (without re-encoding) when that
  *  makes sense.
  */
-DEF_TEST(PDFJpegEmbedTest, r) {
-    const char test[] = "PDFJpegEmbedTest";
+DEF_TEST(SkPDF_JpegEmbedTest, r) {
+    REQUIRE_PDF_DOCUMENT(SkPDF_JpegEmbedTest, r);
+    const char test[] = "SkPDF_JpegEmbedTest";
     sk_sp<SkData> mandrillData(load_resource(r, test, "mandrill_512_q075.jpg"));
     sk_sp<SkData> cmykData(load_resource(r, test, "CMYK.jpg"));
     if (!mandrillData || !cmykData) {
@@ -111,9 +113,7 @@
     REPORTER_ASSERT(r, !is_subset_of(cmykData.get(), pdfData.get()));
 }
 
-#include "SkJpegInfo.h"
-
-DEF_TEST(JpegIdentification, r) {
+DEF_TEST(SkPDF_JpegIdentification, r) {
     static struct {
         const char* path;
         bool isJfif;
@@ -144,4 +144,100 @@
         INFOF(r, "\nJpegIdentification: %s [%d x %d]\n", kTests[i].path,
               info.fSize.width(), info.fSize.height());
     }
+
+    // Test several malformed jpegs.
+    SkJFIFInfo info;
+    {
+        static const char goodJpeg[] =
+            "\377\330\377\340\0\20JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\21\10\2\0\2\0\3\1\"\0\2\21\1\3\21\001";
+        size_t goodJpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(goodJpeg, goodJpegLength);
+        REPORTER_ASSERT(r, SkIsJFIF(data.get(), &info));
+        REPORTER_ASSERT(r, info.fSize == SkISize::Make(512, 512));
+        REPORTER_ASSERT(r, info.fType == SkJFIFInfo::kYCbCr);
+
+        // Not long enough to read first (SOI) segment marker.
+        data = SkData::MakeWithoutCopy(goodJpeg, 1);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+
+        // Not long enough to read second segment (APP0) marker.
+        data = SkData::MakeWithoutCopy(goodJpeg, 3);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+
+        // Not long enough to read second segment's length.
+        data = SkData::MakeWithoutCopy(goodJpeg, 5);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+
+        // APP0 segment is truncated.
+        data = SkData::MakeWithoutCopy(goodJpeg, 7);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+
+        // Missing SOF segment.
+        data = SkData::MakeWithoutCopy(goodJpeg, 89);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
+    {
+        // JFIF tag missing.
+        static const char jpeg[] =
+            "\377\330\377\340\0\20JFIX\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\21\10\2\0\2\0\3\1\"\0\2\21\1\3\21\001";
+        size_t jpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(jpeg, jpegLength);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
+    {
+        // APP0 segment short (byte 6 changed).
+        static const char jpeg[] =
+            "\377\330\377\340\0\5JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\21\10\2\0\2\0\3\1\"\0\2\21\1\3\21\001";
+        size_t jpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(jpeg, jpegLength);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
+    {
+        // SOF segment short. ('\21' replaced with '\5')
+        static const char jpeg[] =
+            "\377\330\377\340\0\20JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\5\10\2\0\2\0\3\1\"\0\2\21\1\3\21\001";
+        size_t jpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(jpeg, jpegLength);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
+    {
+        // Unsupported 12-bit components. ('\10' replaced with '\14')
+        static const char jpeg[] =
+            "\377\330\377\340\0\20JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\21\14\2\0\2\0\3\1\"\0\2\21\1\3\21\001";
+        size_t jpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(jpeg, jpegLength);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
+    {
+        // Two color channels.  ('\3' replaced with '\2')
+        static const char jpeg[] =
+            "\377\330\377\340\0\20JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\10\6\6\7"
+            "\6\5\10\7\7\7\t\t\10\n\14\24\r\14\13\13\14\31\22\23\17\24\35\32\37"
+            "\36\35\32\34\34 $.' \",#\34\34(7),01444\37'9=82<.342\377\333\0C\1\t"
+            "\t\t\14\13\14\30\r\r\0302!\34!222222222222222222222222222222222222"
+            "22222222222222\377\300\0\21\10\2\0\2\0\2\1\"\0\2\21\1\3\21\001";
+        size_t jpegLength = 177;
+        auto data = SkData::MakeWithoutCopy(jpeg, jpegLength);
+        REPORTER_ASSERT(r, !SkIsJFIF(data.get(), &info));
+    }
 }
diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp
index 1001b99..c719f48 100644
--- a/tests/PDFPrimitivesTest.cpp
+++ b/tests/PDFPrimitivesTest.cpp
@@ -334,7 +334,7 @@
     assert_eq(reporter, result, "<</Type /DType\n/n1 1 0 R>>");
 }
 
-DEF_TEST(PDFPrimitives, reporter) {
+DEF_TEST(SkPDF_Primitives, reporter) {
     TestPDFUnion(reporter);
     TestPDFArray(reporter);
     TestPDFDict(reporter);
@@ -389,7 +389,8 @@
 
 // Check that PDF rendering of image filters successfully falls back to
 // CPU rasterization.
-DEF_TEST(PDFImageFilter, reporter) {
+DEF_TEST(SkPDF_ImageFilter, reporter) {
+    REQUIRE_PDF_DOCUMENT(SkPDF_ImageFilter, reporter);
     SkDynamicMemoryWStream stream;
     sk_sp<SkDocument> doc(SkDocument::MakePDF(&stream));
     SkCanvas* canvas = doc->beginPage(100.0f, 100.0f);
@@ -409,7 +410,7 @@
 
 // Check that PDF rendering of image filters successfully falls back to
 // CPU rasterization.
-DEF_TEST(PDFFontCanEmbedTypeface, reporter) {
+DEF_TEST(SkPDF_FontCanEmbedTypeface, reporter) {
     SkPDFCanon canon;
 
     const char resource[] = "fonts/Roboto2-Regular_NoEmbed.ttf";
@@ -453,7 +454,7 @@
 }
 
 // Test SkPDFUtils::AppendScalar for accuracy.
-DEF_TEST(PDFPrimitives_Scalar, reporter) {
+DEF_TEST(SkPDF_Primitives_Scalar, reporter) {
     SkRandom random(0x5EED);
     int iterationCount = 512;
     while (iterationCount-- > 0) {
@@ -474,7 +475,7 @@
 }
 
 // Test SkPDFUtils:: for accuracy.
-DEF_TEST(PDFPrimitives_Color, reporter) {
+DEF_TEST(SkPDF_Primitives_Color, reporter) {
     char buffer[5];
     for (int i = 0; i < 256; ++i) {
         size_t len = SkPDFUtils::ColorToDecimal(i, buffer);