Add unit test for FPDFImageObj_LoadJpegFile{Inline}() APIs

- Take mona_lisa.jpg from chromium tree.
- Move fopen-based FileAccess to testing/utils to provide easy access
  to actual jpeg files.

Bug: pdfium:1226
Change-Id: Ie78034f5794ad7789874932b2ecf834601dc23a1
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/62910
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
index b60b663..9d849c1 100644
--- a/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
+++ b/core/fpdfapi/edit/cpdf_creator_embeddertest.cpp
@@ -17,44 +17,6 @@
 #include "testing/gmock/include/gmock/gmock-matchers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/utils/file_util.h"
-#include "testing/utils/path_service.h"
-
-namespace {
-
-class FileAccess final : public FPDF_FILEACCESS {
- public:
-  explicit FileAccess(const std::string& file_name) {
-    std::string file_path;
-    if (!PathService::GetTestFilePath(file_name, &file_path))
-      return;
-
-    file_contents_ = GetFileContents(file_path.c_str(), &file_length_);
-    if (!file_contents_)
-      return;
-
-    m_FileLen = static_cast<unsigned long>(file_length_);
-    m_GetBlock = SGetBlock;
-    m_Param = this;
-  }
-
- private:
-  int GetBlockImpl(unsigned long pos, unsigned char* pBuf, unsigned long size) {
-    memcpy(pBuf, file_contents_.get() + pos, size);
-    return size;
-  }
-
-  static int SGetBlock(void* param,
-                       unsigned long pos,
-                       unsigned char* pBuf,
-                       unsigned long size) {
-    return static_cast<FileAccess*>(param)->GetBlockImpl(pos, pBuf, size);
-  }
-
-  size_t file_length_;
-  std::unique_ptr<char, pdfium::FreeDeleter> file_contents_;
-};
-
-}  // namespace
 
 class CPDF_CreatorEmbedderTest : public EmbedderTest {};
 
@@ -104,7 +66,7 @@
 }
 
 TEST_F(CPDF_CreatorEmbedderTest, SaveLinearizedInfo) {
-  FileAccess file_acc("linearized.pdf");
+  FileAccessForTesting file_acc("linearized.pdf");
   FakeFileAccess fake_acc(&file_acc);
 
   avail_ = FPDFAvail_Create(fake_acc.GetFileAvail(), fake_acc.GetFileAccess());
diff --git a/fpdfsdk/fpdf_editimg_unittest.cpp b/fpdfsdk/fpdf_editimg_unittest.cpp
index 89fb9c5..09ec71e 100644
--- a/fpdfsdk/fpdf_editimg_unittest.cpp
+++ b/fpdfsdk/fpdf_editimg_unittest.cpp
@@ -7,6 +7,7 @@
 #include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "public/cpp/fpdf_scopers.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "testing/utils/file_util.h"
 
 class PDFEditImgTest : public testing::Test {
   void SetUp() override { CPDF_PageModule::Create(); }
@@ -70,6 +71,44 @@
   FPDF_CloseDocument(doc);
 }
 
+TEST_F(PDFEditImgTest, NewImageObjLoadJpeg) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 200, 200));
+  ASSERT_TRUE(page);
+
+  ScopedFPDFPageObject image(FPDFPageObj_NewImageObj(doc.get()));
+  ASSERT_TRUE(image);
+
+  FileAccessForTesting file_access("mona_lisa.jpg");
+  FPDF_PAGE temp_page = page.get();
+  EXPECT_TRUE(
+      FPDFImageObj_LoadJpegFile(&temp_page, 1, image.get(), &file_access));
+
+  ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(image.get()));
+  EXPECT_TRUE(bitmap);
+  EXPECT_EQ(120, FPDFBitmap_GetWidth(bitmap.get()));
+  EXPECT_EQ(120, FPDFBitmap_GetHeight(bitmap.get()));
+}
+
+TEST_F(PDFEditImgTest, NewImageObjLoadJpegInline) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+  ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 200, 200));
+  ASSERT_TRUE(page);
+
+  ScopedFPDFPageObject image(FPDFPageObj_NewImageObj(doc.get()));
+  ASSERT_TRUE(image);
+
+  FileAccessForTesting file_access("mona_lisa.jpg");
+  FPDF_PAGE temp_page = page.get();
+  EXPECT_TRUE(FPDFImageObj_LoadJpegFileInline(&temp_page, 1, image.get(),
+                                              &file_access));
+
+  ScopedFPDFBitmap bitmap(FPDFImageObj_GetBitmap(image.get()));
+  EXPECT_TRUE(bitmap);
+  EXPECT_EQ(120, FPDFBitmap_GetWidth(bitmap.get()));
+  EXPECT_EQ(120, FPDFBitmap_GetHeight(bitmap.get()));
+}
+
 TEST_F(PDFEditImgTest, SetBitmap) {
   ScopedFPDFDocument doc(FPDF_CreateNewDocument());
   ScopedFPDFPage page(FPDFPage_New(doc.get(), 0, 100, 100));
diff --git a/testing/resources/mona_lisa.jpg b/testing/resources/mona_lisa.jpg
new file mode 100644
index 0000000..df28704
--- /dev/null
+++ b/testing/resources/mona_lisa.jpg
Binary files differ
diff --git a/testing/utils/file_util.cpp b/testing/utils/file_util.cpp
index b239e20..ffd387b 100644
--- a/testing/utils/file_util.cpp
+++ b/testing/utils/file_util.cpp
@@ -6,6 +6,8 @@
 
 #include <stdio.h>
 
+#include "testing/utils/path_service.h"
+
 std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename,
                                                            size_t* retlen) {
   FILE* file = fopen(filename, "rb");
@@ -33,3 +35,33 @@
   *retlen = bytes_read;
   return buffer;
 }
+
+FileAccessForTesting::FileAccessForTesting(const std::string& file_name) {
+  std::string file_path;
+  if (!PathService::GetTestFilePath(file_name, &file_path))
+    return;
+
+  file_contents_ = GetFileContents(file_path.c_str(), &file_length_);
+  if (!file_contents_)
+    return;
+
+  m_FileLen = static_cast<unsigned long>(file_length_);
+  m_GetBlock = SGetBlock;
+  m_Param = this;
+}
+
+int FileAccessForTesting::GetBlockImpl(unsigned long pos,
+                                       unsigned char* pBuf,
+                                       unsigned long size) {
+  memcpy(pBuf, file_contents_.get() + pos, size);
+  return size;
+}
+
+// static
+int FileAccessForTesting::SGetBlock(void* param,
+                                    unsigned long pos,
+                                    unsigned char* pBuf,
+                                    unsigned long size) {
+  auto* file_access = static_cast<FileAccessForTesting*>(param);
+  return file_access->GetBlockImpl(pos, pBuf, size);
+}
diff --git a/testing/utils/file_util.h b/testing/utils/file_util.h
index 21b911a..352b882 100644
--- a/testing/utils/file_util.h
+++ b/testing/utils/file_util.h
@@ -8,11 +8,30 @@
 #include <stdlib.h>
 
 #include <memory>
+#include <string>
 
+#include "public/fpdfview.h"
 #include "testing/free_deleter.h"
 
 // Reads the entire contents of a file into a newly alloc'd buffer.
 std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename,
                                                            size_t* retlen);
 
+// Use an ordinary file anywhere a FPDF_FILEACCESS is required.
+class FileAccessForTesting final : public FPDF_FILEACCESS {
+ public:
+  explicit FileAccessForTesting(const std::string& file_name);
+
+ private:
+  static int SGetBlock(void* param,
+                       unsigned long pos,
+                       unsigned char* pBuf,
+                       unsigned long size);
+
+  int GetBlockImpl(unsigned long pos, unsigned char* pBuf, unsigned long size);
+
+  size_t file_length_;
+  std::unique_ptr<char, pdfium::FreeDeleter> file_contents_;
+};
+
 #endif  // TESTING_UTILS_FILE_UTIL_H_