Make fpdf_annot_unittest.cc and fpdf_editimg_unittest.cc be embeddertests.

These tests are all calling FPDF_CreateNewDocument(), which requires
that the entire PDFium environment be initialized, rather than just
the per-test subsystem initialization that we can get away with in
unittests. Although this happens to work at present, we may get into
trouble down the road when more sophisticated intialization is required
for new features.

Change-Id: I94f144c58924f048fd37ddd6a5d3b56ce3bd12da
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70551
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/BUILD.gn b/fpdfsdk/BUILD.gn
index e0a9983..081152e 100644
--- a/fpdfsdk/BUILD.gn
+++ b/fpdfsdk/BUILD.gn
@@ -109,11 +109,9 @@
 pdfium_unittest_source_set("unittests") {
   sources = [
     "cpdfsdk_helpers_unittest.cpp",
-    "fpdf_annot_unittest.cpp",
     "fpdf_catalog_unittest.cpp",
     "fpdf_doc_unittest.cpp",
     "fpdf_edit_unittest.cpp",
-    "fpdf_editimg_unittest.cpp",
     "fpdf_view_unittest.cpp",
   ]
   deps = [
@@ -137,6 +135,7 @@
     "fpdf_dataavail_embeddertest.cpp",
     "fpdf_doc_embeddertest.cpp",
     "fpdf_edit_embeddertest.cpp",
+    "fpdf_editimg_embeddertest.cpp",
     "fpdf_editpage_embeddertest.cpp",
     "fpdf_editpath_embeddertest.cpp",
     "fpdf_ext_embeddertest.cpp",
diff --git a/fpdfsdk/fpdf_annot_embeddertest.cpp b/fpdfsdk/fpdf_annot_embeddertest.cpp
index 52d130d..b0e23a4 100644
--- a/fpdfsdk/fpdf_annot_embeddertest.cpp
+++ b/fpdfsdk/fpdf_annot_embeddertest.cpp
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "public/fpdf_annot.h"
+
+#include <limits.h>
+
 #include <algorithm>
 #include <cwchar>
 #include <memory>
@@ -10,9 +14,13 @@
 
 #include "build/build_config.h"
 #include "constants/annotation_common.h"
+#include "core/fpdfapi/page/cpdf_annotcontext.h"
+#include "core/fpdfapi/page/cpdf_pagemodule.h"
+#include "core/fpdfapi/parser/cpdf_array.h"
+#include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fxcrt/fx_system.h"
+#include "fpdfsdk/cpdfsdk_helpers.h"
 #include "public/cpp/fpdf_scopers.h"
-#include "public/fpdf_annot.h"
 #include "public/fpdf_edit.h"
 #include "public/fpdf_formfill.h"
 #include "public/fpdfview.h"
@@ -27,6 +35,13 @@
 
 namespace {
 
+const wchar_t kStreamData[] =
+    L"/GS gs 0.0 0.0 0.0 RG 4 w 211.8 747.6 m 211.8 744.8 "
+    L"212.6 743.0 214.2 740.8 "
+    L"c 215.4 739.0 216.8 737.1 218.9 736.1 c 220.8 735.1 221.4 733.0 "
+    L"223.7 732.4 c 232.6 729.9 242.0 730.8 251.2 730.8 c 257.5 730.8 "
+    L"263.0 732.9 269.0 734.4 c S";
+
 #if defined(_SKIA_SUPPORT_) || defined(_SKIA_SUPPORT_PATHS_)
 #if defined(OS_LINUX)
 const char kAnnotationStampWithApChecksum[] =
@@ -96,6 +111,235 @@
 
 class FPDFAnnotEmbedderTest : public EmbedderTest {};
 
+TEST_F(FPDFAnnotEmbedderTest, SetAP) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ASSERT_TRUE(doc);
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
+  ASSERT_TRUE(page);
+  ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
+  ASSERT_TRUE(ap_stream);
+
+  ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
+  ASSERT_TRUE(annot);
+
+  // Negative case: FPDFAnnot_SetAP() should fail if bounding rect is not yet
+  // set on the annotation.
+  EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+                               ap_stream.get()));
+
+  const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
+  EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
+
+  ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
+                                 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/255));
+
+  EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+                              ap_stream.get()));
+
+  // Verify that appearance stream is created as form XObject
+  CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
+  ASSERT_TRUE(context);
+  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
+  ASSERT_TRUE(annot_dict);
+  CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
+  ASSERT_TRUE(ap_dict);
+  CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
+  ASSERT_TRUE(stream_dict);
+  // Check for non-existence of resources dictionary in case of opaque color
+  CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
+  ASSERT_FALSE(resources_dict);
+  ByteString type = stream_dict->GetStringFor(pdfium::annotation::kType);
+  EXPECT_EQ("XObject", type);
+  ByteString sub_type = stream_dict->GetStringFor(pdfium::annotation::kSubtype);
+  EXPECT_EQ("Form", sub_type);
+
+  // Check that the appearance stream is same as we just set.
+  const uint32_t kStreamDataSize =
+      pdfium::size(kStreamData) * sizeof(FPDF_WCHAR);
+  unsigned long normal_length_bytes = FPDFAnnot_GetAP(
+      annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
+  ASSERT_EQ(kStreamDataSize, normal_length_bytes);
+  std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
+  EXPECT_EQ(kStreamDataSize,
+            FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+                            buf.data(), normal_length_bytes));
+  EXPECT_EQ(kStreamData, GetPlatformWString(buf.data()));
+}
+
+TEST_F(FPDFAnnotEmbedderTest, SetAPWithOpacity) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ASSERT_TRUE(doc);
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
+  ASSERT_TRUE(page);
+  ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
+  ASSERT_TRUE(ap_stream);
+
+  ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
+  ASSERT_TRUE(annot);
+
+  ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
+                                 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/102));
+
+  const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
+  EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
+
+  EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
+                              ap_stream.get()));
+
+  CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
+  ASSERT_TRUE(context);
+  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
+  ASSERT_TRUE(annot_dict);
+  CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
+  ASSERT_TRUE(ap_dict);
+  CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
+  ASSERT_TRUE(stream_dict);
+  CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
+  ASSERT_TRUE(stream_dict);
+  CPDF_Dictionary* extGState_dict = resources_dict->GetDictFor("ExtGState");
+  ASSERT_TRUE(extGState_dict);
+  CPDF_Dictionary* gs_dict = extGState_dict->GetDictFor("GS");
+  ASSERT_TRUE(gs_dict);
+  ByteString type = gs_dict->GetStringFor(pdfium::annotation::kType);
+  EXPECT_EQ("ExtGState", type);
+  float opacity = gs_dict->GetNumberFor("CA");
+  // Opacity value of 102 is represented as 0.4f (=104/255) in /CA entry.
+  EXPECT_FLOAT_EQ(0.4f, opacity);
+  ByteString blend_mode = gs_dict->GetStringFor("BM");
+  EXPECT_EQ("Normal", blend_mode);
+  bool alpha_source_flag = gs_dict->GetBooleanFor("AIS", true);
+  EXPECT_FALSE(alpha_source_flag);
+}
+
+TEST_F(FPDFAnnotEmbedderTest, InkListAPIValidations) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ASSERT_TRUE(doc);
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
+  ASSERT_TRUE(page);
+
+  // Create a new ink annotation.
+  ScopedFPDFAnnotation ink_annot(
+      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
+  ASSERT_TRUE(ink_annot);
+  CPDF_AnnotContext* context =
+      CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
+  ASSERT_TRUE(context);
+  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
+  ASSERT_TRUE(annot_dict);
+
+  static constexpr FS_POINTF kFirstInkStroke[] = {
+      {80.0f, 90.0f}, {81.0f, 91.0f}, {82.0f, 92.0f},
+      {83.0f, 93.0f}, {84.0f, 94.0f}, {85.0f, 95.0f}};
+  static constexpr size_t kFirstStrokePointCount =
+      pdfium::size(kFirstInkStroke);
+
+  static constexpr FS_POINTF kSecondInkStroke[] = {
+      {70.0f, 90.0f}, {71.0f, 91.0f}, {72.0f, 92.0f}};
+  static constexpr size_t kSecondStrokePointCount =
+      pdfium::size(kSecondInkStroke);
+
+  static constexpr FS_POINTF kThirdInkStroke[] = {{60.0f, 90.0f},
+                                                  {61.0f, 91.0f},
+                                                  {62.0f, 92.0f},
+                                                  {63.0f, 93.0f},
+                                                  {64.0f, 94.0f}};
+  static constexpr size_t kThirdStrokePointCount =
+      pdfium::size(kThirdInkStroke);
+
+  // Negative test: |annot| is passed as nullptr.
+  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(nullptr, kFirstInkStroke,
+                                       kFirstStrokePointCount));
+
+  // Negative test: |annot| is not ink annotation.
+  // Create a new highlight annotation.
+  ScopedFPDFAnnotation highlight_annot(
+      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
+  ASSERT_TRUE(highlight_annot);
+  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(highlight_annot.get(), kFirstInkStroke,
+                                       kFirstStrokePointCount));
+
+  // Negative test: passing |point_count| as  0.
+  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke, 0));
+
+  // Negative test: passing |points| array as nullptr.
+  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), nullptr,
+                                       kFirstStrokePointCount));
+
+  // Negative test: passing |point_count| more than ULONG_MAX/2.
+  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
+                                       ULONG_MAX / 2 + 1));
+
+  // InkStroke should get added to ink annotation. Also inklist should get
+  // created.
+  EXPECT_EQ(0, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke,
+                                      kFirstStrokePointCount));
+
+  CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
+  ASSERT_TRUE(inklist);
+  EXPECT_EQ(1u, inklist->size());
+  EXPECT_EQ(kFirstStrokePointCount * 2, inklist->GetArrayAt(0)->size());
+
+  // Adding another inkStroke to ink annotation with all valid paremeters.
+  // InkList already exists in ink_annot.
+  EXPECT_EQ(1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
+                                      kSecondStrokePointCount));
+  EXPECT_EQ(2u, inklist->size());
+  EXPECT_EQ(kSecondStrokePointCount * 2, inklist->GetArrayAt(1)->size());
+
+  // Adding one more InkStroke to the ink annotation. |point_count| passed is
+  // less than the data available in |buffer|.
+  EXPECT_EQ(2, FPDFAnnot_AddInkStroke(ink_annot.get(), kThirdInkStroke,
+                                      kThirdStrokePointCount - 1));
+  EXPECT_EQ(3u, inklist->size());
+  EXPECT_EQ((kThirdStrokePointCount - 1) * 2, inklist->GetArrayAt(2)->size());
+}
+
+TEST_F(FPDFAnnotEmbedderTest, RemoveInkList) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ASSERT_TRUE(doc);
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
+  ASSERT_TRUE(page);
+
+  // Negative test: |annot| is passed as nullptr.
+  EXPECT_FALSE(FPDFAnnot_RemoveInkList(nullptr));
+
+  // Negative test: |annot| is not ink annotation.
+  // Create a new highlight annotation.
+  ScopedFPDFAnnotation highlight_annot(
+      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
+  ASSERT_TRUE(highlight_annot);
+  EXPECT_FALSE(FPDFAnnot_RemoveInkList(highlight_annot.get()));
+
+  // Create a new ink annotation.
+  ScopedFPDFAnnotation ink_annot(
+      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
+  ASSERT_TRUE(ink_annot);
+  CPDF_AnnotContext* context =
+      CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
+  ASSERT_TRUE(context);
+  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
+  ASSERT_TRUE(annot_dict);
+
+  static constexpr FS_POINTF kInkStroke[] = {{80.0f, 90.0f}, {81.0f, 91.0f},
+                                             {82.0f, 92.0f}, {83.0f, 93.0f},
+                                             {84.0f, 94.0f}, {85.0f, 95.0f}};
+  static constexpr size_t kPointCount = pdfium::size(kInkStroke);
+
+  // InkStroke should get added to ink annotation. Also inklist should get
+  // created.
+  EXPECT_EQ(0,
+            FPDFAnnot_AddInkStroke(ink_annot.get(), kInkStroke, kPointCount));
+
+  CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
+  ASSERT_TRUE(inklist);
+  ASSERT_EQ(1u, inklist->size());
+  EXPECT_EQ(kPointCount * 2, inklist->GetArrayAt(0)->size());
+
+  // Remove inklist.
+  EXPECT_TRUE(FPDFAnnot_RemoveInkList(ink_annot.get()));
+  EXPECT_FALSE(annot_dict->KeyExist("InkList"));
+}
+
 TEST_F(FPDFAnnotEmbedderTest, BadParams) {
   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
   FPDF_PAGE page = LoadPage(0);
diff --git a/fpdfsdk/fpdf_annot_unittest.cpp b/fpdfsdk/fpdf_annot_unittest.cpp
deleted file mode 100644
index b9044fa..0000000
--- a/fpdfsdk/fpdf_annot_unittest.cpp
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2019 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "public/fpdf_annot.h"
-
-#include <limits.h>
-
-#include <vector>
-
-#include "constants/annotation_common.h"
-#include "core/fpdfapi/page/cpdf_annotcontext.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
-#include "core/fpdfapi/parser/cpdf_array.h"
-#include "core/fpdfapi/parser/cpdf_dictionary.h"
-#include "fpdfsdk/cpdfsdk_helpers.h"
-#include "public/cpp/fpdf_scopers.h"
-#include "public/fpdf_edit.h"
-#include "testing/fx_string_testhelpers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/base/stl_util.h"
-
-namespace {
-
-const wchar_t kStreamData[] =
-    L"/GS gs 0.0 0.0 0.0 RG 4 w 211.8 747.6 m 211.8 744.8 "
-    L"212.6 743.0 214.2 740.8 "
-    L"c 215.4 739.0 216.8 737.1 218.9 736.1 c 220.8 735.1 221.4 733.0 "
-    L"223.7 732.4 c 232.6 729.9 242.0 730.8 251.2 730.8 c 257.5 730.8 "
-    L"263.0 732.9 269.0 734.4 c S";
-
-}  // namespace
-
-class PDFAnnotTest : public testing::Test {
- protected:
-  PDFAnnotTest() = default;
-  ~PDFAnnotTest() override = default;
-
-  void SetUp() override { CPDF_PageModule::Create(); }
-  void TearDown() override { CPDF_PageModule::Destroy(); }
-};
-
-TEST_F(PDFAnnotTest, SetAP) {
-  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
-  ASSERT_TRUE(doc);
-  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
-  ASSERT_TRUE(page);
-  ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
-  ASSERT_TRUE(ap_stream);
-
-  ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
-  ASSERT_TRUE(annot);
-
-  // Negative case: FPDFAnnot_SetAP() should fail if bounding rect is not yet
-  // set on the annotation.
-  EXPECT_FALSE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
-                               ap_stream.get()));
-
-  const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
-  EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
-
-  ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
-                                 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/255));
-
-  EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
-                              ap_stream.get()));
-
-  // Verify that appearance stream is created as form XObject
-  CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
-  ASSERT_TRUE(context);
-  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
-  ASSERT_TRUE(annot_dict);
-  CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
-  ASSERT_TRUE(ap_dict);
-  CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
-  ASSERT_TRUE(stream_dict);
-  // Check for non-existence of resources dictionary in case of opaque color
-  CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
-  ASSERT_FALSE(resources_dict);
-  ByteString type = stream_dict->GetStringFor(pdfium::annotation::kType);
-  EXPECT_EQ("XObject", type);
-  ByteString sub_type = stream_dict->GetStringFor(pdfium::annotation::kSubtype);
-  EXPECT_EQ("Form", sub_type);
-
-  // Check that the appearance stream is same as we just set.
-  const uint32_t kStreamDataSize =
-      pdfium::size(kStreamData) * sizeof(FPDF_WCHAR);
-  unsigned long normal_length_bytes = FPDFAnnot_GetAP(
-      annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL, nullptr, 0);
-  ASSERT_EQ(kStreamDataSize, normal_length_bytes);
-  std::vector<FPDF_WCHAR> buf = GetFPDFWideStringBuffer(normal_length_bytes);
-  EXPECT_EQ(kStreamDataSize,
-            FPDFAnnot_GetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
-                            buf.data(), normal_length_bytes));
-  EXPECT_EQ(kStreamData, GetPlatformWString(buf.data()));
-}
-
-TEST_F(PDFAnnotTest, SetAPWithOpacity) {
-  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
-  ASSERT_TRUE(doc);
-  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
-  ASSERT_TRUE(page);
-  ScopedFPDFWideString ap_stream = GetFPDFWideString(kStreamData);
-  ASSERT_TRUE(ap_stream);
-
-  ScopedFPDFAnnotation annot(FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
-  ASSERT_TRUE(annot);
-
-  ASSERT_TRUE(FPDFAnnot_SetColor(annot.get(), FPDFANNOT_COLORTYPE_Color,
-                                 /*R=*/255, /*G=*/0, /*B=*/0, /*A=*/102));
-
-  const FS_RECTF bounding_rect{206.0f, 753.0f, 339.0f, 709.0f};
-  EXPECT_TRUE(FPDFAnnot_SetRect(annot.get(), &bounding_rect));
-
-  EXPECT_TRUE(FPDFAnnot_SetAP(annot.get(), FPDF_ANNOT_APPEARANCEMODE_NORMAL,
-                              ap_stream.get()));
-
-  CPDF_AnnotContext* context = CPDFAnnotContextFromFPDFAnnotation(annot.get());
-  ASSERT_TRUE(context);
-  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
-  ASSERT_TRUE(annot_dict);
-  CPDF_Dictionary* ap_dict = annot_dict->GetDictFor(pdfium::annotation::kAP);
-  ASSERT_TRUE(ap_dict);
-  CPDF_Dictionary* stream_dict = ap_dict->GetDictFor("N");
-  ASSERT_TRUE(stream_dict);
-  CPDF_Dictionary* resources_dict = stream_dict->GetDictFor("Resources");
-  ASSERT_TRUE(stream_dict);
-  CPDF_Dictionary* extGState_dict = resources_dict->GetDictFor("ExtGState");
-  ASSERT_TRUE(extGState_dict);
-  CPDF_Dictionary* gs_dict = extGState_dict->GetDictFor("GS");
-  ASSERT_TRUE(gs_dict);
-  ByteString type = gs_dict->GetStringFor(pdfium::annotation::kType);
-  EXPECT_EQ("ExtGState", type);
-  float opacity = gs_dict->GetNumberFor("CA");
-  // Opacity value of 102 is represented as 0.4f (=104/255) in /CA entry.
-  EXPECT_FLOAT_EQ(0.4f, opacity);
-  ByteString blend_mode = gs_dict->GetStringFor("BM");
-  EXPECT_EQ("Normal", blend_mode);
-  bool alpha_source_flag = gs_dict->GetBooleanFor("AIS", true);
-  EXPECT_FALSE(alpha_source_flag);
-}
-
-TEST_F(PDFAnnotTest, InkListAPIValidations) {
-  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
-  ASSERT_TRUE(doc);
-  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
-  ASSERT_TRUE(page);
-
-  // Create a new ink annotation.
-  ScopedFPDFAnnotation ink_annot(
-      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
-  ASSERT_TRUE(ink_annot);
-  CPDF_AnnotContext* context =
-      CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
-  ASSERT_TRUE(context);
-  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
-  ASSERT_TRUE(annot_dict);
-
-  static constexpr FS_POINTF kFirstInkStroke[] = {
-      {80.0f, 90.0f}, {81.0f, 91.0f}, {82.0f, 92.0f},
-      {83.0f, 93.0f}, {84.0f, 94.0f}, {85.0f, 95.0f}};
-  static constexpr size_t kFirstStrokePointCount =
-      pdfium::size(kFirstInkStroke);
-
-  static constexpr FS_POINTF kSecondInkStroke[] = {
-      {70.0f, 90.0f}, {71.0f, 91.0f}, {72.0f, 92.0f}};
-  static constexpr size_t kSecondStrokePointCount =
-      pdfium::size(kSecondInkStroke);
-
-  static constexpr FS_POINTF kThirdInkStroke[] = {{60.0f, 90.0f},
-                                                  {61.0f, 91.0f},
-                                                  {62.0f, 92.0f},
-                                                  {63.0f, 93.0f},
-                                                  {64.0f, 94.0f}};
-  static constexpr size_t kThirdStrokePointCount =
-      pdfium::size(kThirdInkStroke);
-
-  // Negative test: |annot| is passed as nullptr.
-  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(nullptr, kFirstInkStroke,
-                                       kFirstStrokePointCount));
-
-  // Negative test: |annot| is not ink annotation.
-  // Create a new highlight annotation.
-  ScopedFPDFAnnotation highlight_annot(
-      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
-  ASSERT_TRUE(highlight_annot);
-  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(highlight_annot.get(), kFirstInkStroke,
-                                       kFirstStrokePointCount));
-
-  // Negative test: passing |point_count| as  0.
-  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke, 0));
-
-  // Negative test: passing |points| array as nullptr.
-  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), nullptr,
-                                       kFirstStrokePointCount));
-
-  // Negative test: passing |point_count| more than ULONG_MAX/2.
-  EXPECT_EQ(-1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
-                                       ULONG_MAX / 2 + 1));
-
-  // InkStroke should get added to ink annotation. Also inklist should get
-  // created.
-  EXPECT_EQ(0, FPDFAnnot_AddInkStroke(ink_annot.get(), kFirstInkStroke,
-                                      kFirstStrokePointCount));
-
-  CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
-  ASSERT_TRUE(inklist);
-  EXPECT_EQ(1u, inklist->size());
-  EXPECT_EQ(kFirstStrokePointCount * 2, inklist->GetArrayAt(0)->size());
-
-  // Adding another inkStroke to ink annotation with all valid paremeters.
-  // InkList already exists in ink_annot.
-  EXPECT_EQ(1, FPDFAnnot_AddInkStroke(ink_annot.get(), kSecondInkStroke,
-                                      kSecondStrokePointCount));
-  EXPECT_EQ(2u, inklist->size());
-  EXPECT_EQ(kSecondStrokePointCount * 2, inklist->GetArrayAt(1)->size());
-
-  // Adding one more InkStroke to the ink annotation. |point_count| passed is
-  // less than the data available in |buffer|.
-  EXPECT_EQ(2, FPDFAnnot_AddInkStroke(ink_annot.get(), kThirdInkStroke,
-                                      kThirdStrokePointCount - 1));
-  EXPECT_EQ(3u, inklist->size());
-  EXPECT_EQ((kThirdStrokePointCount - 1) * 2, inklist->GetArrayAt(2)->size());
-}
-
-TEST_F(PDFAnnotTest, RemoveInkList) {
-  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
-  ASSERT_TRUE(doc);
-  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
-  ASSERT_TRUE(page);
-
-  // Negative test: |annot| is passed as nullptr.
-  EXPECT_FALSE(FPDFAnnot_RemoveInkList(nullptr));
-
-  // Negative test: |annot| is not ink annotation.
-  // Create a new highlight annotation.
-  ScopedFPDFAnnotation highlight_annot(
-      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_HIGHLIGHT));
-  ASSERT_TRUE(highlight_annot);
-  EXPECT_FALSE(FPDFAnnot_RemoveInkList(highlight_annot.get()));
-
-  // Create a new ink annotation.
-  ScopedFPDFAnnotation ink_annot(
-      FPDFPage_CreateAnnot(page.get(), FPDF_ANNOT_INK));
-  ASSERT_TRUE(ink_annot);
-  CPDF_AnnotContext* context =
-      CPDFAnnotContextFromFPDFAnnotation(ink_annot.get());
-  ASSERT_TRUE(context);
-  CPDF_Dictionary* annot_dict = context->GetAnnotDict();
-  ASSERT_TRUE(annot_dict);
-
-  static constexpr FS_POINTF kInkStroke[] = {{80.0f, 90.0f}, {81.0f, 91.0f},
-                                             {82.0f, 92.0f}, {83.0f, 93.0f},
-                                             {84.0f, 94.0f}, {85.0f, 95.0f}};
-  static constexpr size_t kPointCount = pdfium::size(kInkStroke);
-
-  // InkStroke should get added to ink annotation. Also inklist should get
-  // created.
-  EXPECT_EQ(0,
-            FPDFAnnot_AddInkStroke(ink_annot.get(), kInkStroke, kPointCount));
-
-  CPDF_Array* inklist = annot_dict->GetArrayFor("InkList");
-  ASSERT_TRUE(inklist);
-  ASSERT_EQ(1u, inklist->size());
-  EXPECT_EQ(kPointCount * 2, inklist->GetArrayAt(0)->size());
-
-  // Remove inklist.
-  EXPECT_TRUE(FPDFAnnot_RemoveInkList(ink_annot.get()));
-  EXPECT_FALSE(annot_dict->KeyExist("InkList"));
-}
diff --git a/fpdfsdk/fpdf_editimg_unittest.cpp b/fpdfsdk/fpdf_editimg_embeddertest.cpp
similarity index 96%
rename from fpdfsdk/fpdf_editimg_unittest.cpp
rename to fpdfsdk/fpdf_editimg_embeddertest.cpp
index 09ec71e..60f6ed1 100644
--- a/fpdfsdk/fpdf_editimg_unittest.cpp
+++ b/fpdfsdk/fpdf_editimg_embeddertest.cpp
@@ -4,15 +4,11 @@
 
 #include "public/fpdf_edit.h"
 
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "public/cpp/fpdf_scopers.h"
-#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/embedder_test.h"
 #include "testing/utils/file_util.h"
 
-class PDFEditImgTest : public testing::Test {
-  void SetUp() override { CPDF_PageModule::Create(); }
-  void TearDown() override { CPDF_PageModule::Destroy(); }
-};
+class PDFEditImgTest : public EmbedderTest {};
 
 TEST_F(PDFEditImgTest, InsertObjectWithInvalidPage) {
   FPDF_DOCUMENT doc = FPDF_CreateNewDocument();