Commit 42816a8f authored by ckitagawa's avatar ckitagawa Committed by Commit Bot

[Paint Preview] Generate SKP for PaintPreviewPlayerTest

This CL restores the tests in PaintPreviewPlayerTest by generating an
SkPicture of specified dimensions with a proto.pb containing specified
metadata.

No new tests are added in this CL; however, the new generation
capability can be adapted/expanded to vastly improve integration test
coverage of the Player.

Bug: 1106035
Change-Id: I10a2e631a54badce6533ad25ce854eb8c714fb98
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2308137
Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org>
Reviewed-by: default avatarMehran Mahmoudi <mahmoudi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790500}
parent f94fd97a
...@@ -7,80 +7,136 @@ ...@@ -7,80 +7,136 @@
#include <memory> #include <memory>
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "components/paint_preview/browser/paint_preview_base_service.h" #include "components/paint_preview/browser/paint_preview_base_service.h"
#include "components/paint_preview/browser/test_paint_preview_policy.h" #include "components/paint_preview/browser/test_paint_preview_policy.h"
#include "components/paint_preview/common/file_stream.h"
#include "components/paint_preview/common/file_utils.h"
#include "components/paint_preview/common/proto/paint_preview.pb.h" #include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "components/paint_preview/player/android/javatests_jni_headers/PaintPreviewTestService_jni.h" #include "components/paint_preview/player/android/javatests_jni_headers/PaintPreviewTestService_jni.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
using base::android::JavaParamRef; using base::android::JavaParamRef;
namespace paint_preview { namespace paint_preview {
namespace {
const char kPaintPreviewDir[] = "paint_preview"; const char kPaintPreviewDir[] = "paint_preview";
const char kTestDirName[] = "PaintPreviewTestService"; const char kTestDirName[] = "PaintPreviewTestService";
void UpdateSkpPaths(const base::FilePath& test_data_dir,
const DirectoryKey& key,
PaintPreviewBaseService::OnReadProtoCallback callback,
std::unique_ptr<PaintPreviewProto> proto) {
if (proto == nullptr) {
std::move(callback).Run(std::move(proto));
return;
}
// Update the file path for the root SKP to match the isolated test
// environment.
std::string root_skp_file_name =
base::FilePath(proto->root_frame().file_path()).BaseName().AsUTF8Unsafe();
base::FilePath root_skp_file_path =
test_data_dir.AppendASCII(key.AsciiDirname())
.AppendASCII(root_skp_file_name);
proto->mutable_root_frame()->set_file_path(root_skp_file_path.AsUTF8Unsafe());
// Update the file path for the subframe SKPs to match the isolated test
// environment.
for (auto& subframe : *(proto->mutable_subframes())) {
std::string subframe_skp_file_name =
base::FilePath(subframe.file_path()).BaseName().AsUTF8Unsafe();
base::FilePath subframe_skp_file_path =
test_data_dir.AppendASCII(key.AsciiDirname())
.AppendASCII(subframe_skp_file_name);
subframe.set_file_path(subframe_skp_file_path.AsUTF8Unsafe());
}
std::move(callback).Run(std::move(proto));
}
} // namespace
jlong JNI_PaintPreviewTestService_GetInstance( jlong JNI_PaintPreviewTestService_GetInstance(
JNIEnv* env, JNIEnv* env,
const JavaParamRef<jstring>& j_test_data_dir) { const JavaParamRef<jstring>& j_path) {
base::FilePath file_path( base::FilePath file_path(base::android::ConvertJavaStringToUTF8(env, j_path));
base::android::ConvertJavaStringToUTF8(env, j_test_data_dir));
PaintPreviewTestService* service = new PaintPreviewTestService(file_path); PaintPreviewTestService* service = new PaintPreviewTestService(file_path);
return reinterpret_cast<intptr_t>(service); return reinterpret_cast<intptr_t>(service);
} }
PaintPreviewTestService::PaintPreviewTestService( PaintPreviewTestService::PaintPreviewTestService(const base::FilePath& path)
const base::FilePath& test_data_dir) : PaintPreviewBaseService(path,
: PaintPreviewBaseService(test_data_dir,
kTestDirName, kTestDirName,
std::make_unique<TestPaintPreviewPolicy>(), std::make_unique<TestPaintPreviewPolicy>(),
false), false),
test_data_dir_(test_data_dir.AppendASCII(kPaintPreviewDir) test_data_dir_(
.AppendASCII(kTestDirName)) {} path.AppendASCII(kPaintPreviewDir).AppendASCII(kTestDirName)) {}
PaintPreviewTestService::~PaintPreviewTestService() = default; PaintPreviewTestService::~PaintPreviewTestService() = default;
void PaintPreviewTestService::GetCapturedPaintPreviewProto( jboolean PaintPreviewTestService::CreateSingleSkpForKey(
const DirectoryKey& key, JNIEnv* env,
OnReadProtoCallback on_read_proto_callback) { const JavaParamRef<jstring>& j_key,
PaintPreviewBaseService::GetCapturedPaintPreviewProto( const JavaParamRef<jstring>& j_url,
key, base::BindOnce(&UpdateSkpPaths, test_data_dir_, key, jint j_width,
std::move(on_read_proto_callback))); jint j_height,
const JavaParamRef<jintArray>& j_link_rects,
const JavaParamRef<jobjectArray>& j_link_urls) {
base::ScopedAllowBlockingForTesting allow_blocking;
if (!base::PathExists(test_data_dir_)) {
base::File::Error error;
if (!base::CreateDirectoryAndGetError(test_data_dir_, &error)) {
LOG(ERROR) << "Failed to create dir: "
<< base::File::ErrorToString(error);
return false;
}
}
base::FilePath path = test_data_dir_.AppendASCII(
base::android::ConvertJavaStringToUTF8(env, j_key));
if (!base::CreateDirectory(path)) {
LOG(ERROR) << "Failed to create directory.";
return false;
}
uint32_t width = static_cast<uint32_t>(j_width);
uint32_t height = static_cast<uint32_t>(j_height);
SkPictureRecorder recorder;
auto* canvas = recorder.beginRecording(SkRect::MakeWH(width, height));
SkPaint paint;
paint.setColor(SK_ColorWHITE);
canvas->drawRect(SkRect::MakeWH(width, height), paint);
paint.setColor(SK_ColorGRAY);
const int kSquareSideLen = 50;
for (uint32_t j = 0; j * kSquareSideLen < height; ++j) {
for (uint32_t i = (j % 2); i * kSquareSideLen < width; i += 2) {
canvas->drawRect(SkRect::MakeXYWH(i * kSquareSideLen, j * kSquareSideLen,
kSquareSideLen, kSquareSideLen),
paint);
}
}
auto skp = recorder.finishRecordingAsPicture();
auto skp_path = path.AppendASCII("test_file.skp");
FileWStream wstream(base::File(
skp_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE));
skp->serialize(&wstream);
wstream.Close();
if (wstream.DidWriteFail()) {
LOG(ERROR) << "SKP Write failed";
return false;
}
LOG(INFO) << "Wrote SKP " << wstream.ActualBytesWritten() << " bytes";
PaintPreviewProto paint_preview;
auto* metadata = paint_preview.mutable_metadata();
metadata->set_url(base::android::ConvertJavaStringToUTF8(env, j_url));
auto* root_frame = paint_preview.mutable_root_frame();
auto token = base::UnguessableToken::Create();
root_frame->set_file_path(skp_path.AsUTF8Unsafe());
root_frame->set_embedding_token_low(token.GetLowForSerialization());
root_frame->set_embedding_token_high(token.GetHighForSerialization());
root_frame->set_is_main_frame(true);
// No initial offset.
root_frame->set_scroll_offset_x(0);
root_frame->set_scroll_offset_y(0);
std::vector<std::string> link_urls;
base::android::AppendJavaStringArrayToStringVector(env, j_link_urls,
&link_urls);
std::vector<int> link_rects;
base::android::JavaIntArrayToIntVector(env, j_link_rects, &link_rects);
for (size_t i = 0; i < link_urls.size(); ++i) {
auto* link_proto = root_frame->add_links();
link_proto->set_url(link_urls[i]);
auto* rect = link_proto->mutable_rect();
rect->set_x(link_rects[i * 4]);
rect->set_y(link_rects[i * 4 + 1]);
rect->set_width(link_rects[i * 4 + 2]);
rect->set_height(link_rects[i * 4 + 3]);
}
if (!WriteProtoToFile(path.AppendASCII("proto.pb"), paint_preview)) {
LOG(ERROR) << "Failed to write proto to file.";
return false;
}
return true;
} }
} // namespace paint_preview } // namespace paint_preview
...@@ -14,15 +14,20 @@ namespace paint_preview { ...@@ -14,15 +14,20 @@ namespace paint_preview {
// A simple implementation of PaintPreviewBaseService used in tests. // A simple implementation of PaintPreviewBaseService used in tests.
class PaintPreviewTestService : public PaintPreviewBaseService { class PaintPreviewTestService : public PaintPreviewBaseService {
public: public:
PaintPreviewTestService(const base::FilePath& test_data_dir); PaintPreviewTestService(const base::FilePath& path);
~PaintPreviewTestService() override; ~PaintPreviewTestService() override;
PaintPreviewTestService(const PaintPreviewTestService&) = delete; PaintPreviewTestService(const PaintPreviewTestService&) = delete;
PaintPreviewTestService& operator=(const PaintPreviewTestService&) = delete; PaintPreviewTestService& operator=(const PaintPreviewTestService&) = delete;
void GetCapturedPaintPreviewProto( jboolean CreateSingleSkpForKey(
const DirectoryKey& key, JNIEnv* env,
OnReadProtoCallback on_read_proto_callback) override; const base::android::JavaParamRef<jstring>& j_key,
const base::android::JavaParamRef<jstring>& j_url,
jint j_width,
jint j_height,
const base::android::JavaParamRef<jintArray>& j_link_rects,
const base::android::JavaParamRef<jobjectArray>& j_link_urls);
private: private:
base::FilePath test_data_dir_; base::FilePath test_data_dir_;
......
...@@ -16,14 +16,13 @@ import org.hamcrest.Matchers; ...@@ -16,14 +16,13 @@ import org.hamcrest.Matchers;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.task.PostTask; import org.chromium.base.task.PostTask;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.ScalableTimeout; import org.chromium.base.test.util.ScalableTimeout;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper;
...@@ -37,15 +36,12 @@ import org.chromium.url.GURL; ...@@ -37,15 +36,12 @@ import org.chromium.url.GURL;
public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
private static final long TIMEOUT_MS = ScalableTimeout.scaleTimeout(5000); private static final long TIMEOUT_MS = ScalableTimeout.scaleTimeout(5000);
private static final String TEST_DATA_DIR = "components/test/data/"; private static final String TEST_DIRECTORY_KEY = "test_dir";
private static final String TEST_DIRECTORY_KEY = "wikipedia"; private static final String TEST_URL = "https://www.chromium.org";
private static final String TEST_URL = "https://en.m.wikipedia.org/wiki/Main_Page"; private static final String TEST_IN_VIEWPORT_LINK_URL = "http://www.google.com/";
private static final String TEST_MAIN_PICTURE_LINK_URL = private static final String TEST_OUT_OF_VIEWPORT_LINK_URL = "http://example.com/";
"https://en.m.wikipedia.org/wiki/File:Volc%C3%A1n_Ubinas,_Arequipa,_Per%C3%BA,_2015-08-02,_DD_50.JPG"; private final Rect mInViewportLinkRect = new Rect(700, 650, 900, 700);
private static final String TEST_IN_VIEWPORT_LINK_URL = private final Rect mOutOfViewportLinkRect = new Rect(300, 4900, 450, 5000);
"https://en.m.wikipedia.org/wiki/Arequipa";
private static final String TEST_OUT_OF_VIEWPORT_LINK_URL =
"https://foundation.wikimedia.org/wiki/Privacy_policy";
private static final int TEST_PAGE_WIDTH = 1082; private static final int TEST_PAGE_WIDTH = 1082;
private static final int TEST_PAGE_HEIGHT = 5019; private static final int TEST_PAGE_HEIGHT = 5019;
...@@ -53,6 +49,9 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { ...@@ -53,6 +49,9 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
@Rule @Rule
public PaintPreviewTestRule mPaintPreviewTestRule = new PaintPreviewTestRule(); public PaintPreviewTestRule mPaintPreviewTestRule = new PaintPreviewTestRule();
@Rule
public TemporaryFolder mTempFolder = new TemporaryFolder();
private PlayerManager mPlayerManager; private PlayerManager mPlayerManager;
private TestLinkClickHandler mLinkClickHandler; private TestLinkClickHandler mLinkClickHandler;
private CallbackHelper mRefreshedCallback; private CallbackHelper mRefreshedCallback;
...@@ -85,7 +84,6 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { ...@@ -85,7 +84,6 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
*/ */
@Test @Test
@MediumTest @MediumTest
@DisabledTest(message = "crbug.com/1106035")
public void singleFrameDisplayTest() { public void singleFrameDisplayTest() {
initPlayerManager(); initPlayerManager();
final View playerHostView = mPlayerManager.getView(); final View playerHostView = mPlayerManager.getView();
...@@ -107,32 +105,24 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { ...@@ -107,32 +105,24 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
*/ */
@Test @Test
@MediumTest @MediumTest
@DisabledTest(message = "crbug.com/1106035")
public void linkClickTest() { public void linkClickTest() {
initPlayerManager(); initPlayerManager();
final View playerHostView = mPlayerManager.getView(); final View playerHostView = mPlayerManager.getView();
// Click on the top left picture and assert it directs to the correct link.
assertLinkUrl(playerHostView, 92, 424, TEST_MAIN_PICTURE_LINK_URL);
assertLinkUrl(playerHostView, 67, 527, TEST_MAIN_PICTURE_LINK_URL);
assertLinkUrl(playerHostView, 466, 668, TEST_MAIN_PICTURE_LINK_URL);
assertLinkUrl(playerHostView, 412, 432, TEST_MAIN_PICTURE_LINK_URL);
// Click on a link that is visible in the default viewport. // Click on a link that is visible in the default viewport.
assertLinkUrl(playerHostView, 732, 698, TEST_IN_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 720, 670, TEST_IN_VIEWPORT_LINK_URL);
assertLinkUrl(playerHostView, 876, 716, TEST_IN_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 880, 675, TEST_IN_VIEWPORT_LINK_URL);
assertLinkUrl(playerHostView, 798, 711, TEST_IN_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 800, 680, TEST_IN_VIEWPORT_LINK_URL);
// Scroll to the bottom, and click on a link. // Scroll to the bottom, and click on a link.
scrollToBottom(); scrollToBottom();
assertLinkUrl(playerHostView, 322, 4946, TEST_OUT_OF_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 320, 4920, TEST_OUT_OF_VIEWPORT_LINK_URL);
assertLinkUrl(playerHostView, 376, 4954, TEST_OUT_OF_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 375, 4950, TEST_OUT_OF_VIEWPORT_LINK_URL);
assertLinkUrl(playerHostView, 422, 4965, TEST_OUT_OF_VIEWPORT_LINK_URL); assertLinkUrl(playerHostView, 430, 4980, TEST_OUT_OF_VIEWPORT_LINK_URL);
} }
@Test @Test
@MediumTest @MediumTest
@DisabledTest(message = "crbug.com/1106035")
public void overscrollRefreshTest() throws Exception { public void overscrollRefreshTest() throws Exception {
initPlayerManager(); initPlayerManager();
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
...@@ -157,7 +147,7 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { ...@@ -157,7 +147,7 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
mLinkClickHandler = new TestLinkClickHandler(); mLinkClickHandler = new TestLinkClickHandler();
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
PaintPreviewTestService service = PaintPreviewTestService service =
new PaintPreviewTestService(UrlUtils.getIsolatedTestFilePath(TEST_DATA_DIR)); new PaintPreviewTestService(mTempFolder.getRoot().getPath());
// Use the wrong URL to simulate a failure. // Use the wrong URL to simulate a failure.
mPlayerManager = new PlayerManager(new GURL("about:blank"), getActivity(), service, mPlayerManager = new PlayerManager(new GURL("about:blank"), getActivity(), service,
TEST_DIRECTORY_KEY, mLinkClickHandler, TEST_DIRECTORY_KEY, mLinkClickHandler,
...@@ -217,7 +207,11 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase { ...@@ -217,7 +207,11 @@ public class PaintPreviewPlayerTest extends DummyUiActivityTestCase {
CallbackHelper viewReady = new CallbackHelper(); CallbackHelper viewReady = new CallbackHelper();
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
PaintPreviewTestService service = PaintPreviewTestService service =
new PaintPreviewTestService(UrlUtils.getIsolatedTestFilePath(TEST_DATA_DIR)); new PaintPreviewTestService(mTempFolder.getRoot().getPath());
Assert.assertTrue(service.createSingleSkpForKey(TEST_DIRECTORY_KEY, TEST_URL,
TEST_PAGE_WIDTH, TEST_PAGE_HEIGHT,
new Rect[] {mInViewportLinkRect, mOutOfViewportLinkRect},
new String[] {TEST_IN_VIEWPORT_LINK_URL, TEST_OUT_OF_VIEWPORT_LINK_URL}));
mPlayerManager = new PlayerManager(new GURL(TEST_URL), getActivity(), service, mPlayerManager = new PlayerManager(new GURL(TEST_URL), getActivity(), service,
TEST_DIRECTORY_KEY, mLinkClickHandler, TEST_DIRECTORY_KEY, mLinkClickHandler,
() -> { mRefreshedCallback.notifyCalled(); }, () -> { mRefreshedCallback.notifyCalled(); },
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
package org.chromium.components.paintpreview.player; package org.chromium.components.paintpreview.player;
import android.graphics.Rect;
import org.chromium.base.Log;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.NativeMethods; import org.chromium.base.annotations.NativeMethods;
import org.chromium.components.paintpreview.browser.NativePaintPreviewServiceProvider; import org.chromium.components.paintpreview.browser.NativePaintPreviewServiceProvider;
...@@ -13,10 +16,11 @@ import org.chromium.components.paintpreview.browser.NativePaintPreviewServicePro ...@@ -13,10 +16,11 @@ import org.chromium.components.paintpreview.browser.NativePaintPreviewServicePro
*/ */
@JNINamespace("paint_preview") @JNINamespace("paint_preview")
public class PaintPreviewTestService implements NativePaintPreviewServiceProvider { public class PaintPreviewTestService implements NativePaintPreviewServiceProvider {
private static final String TAG = "PPTestService";
private long mNativePaintPreviewTestService; private long mNativePaintPreviewTestService;
public PaintPreviewTestService(String testDataDir) { public PaintPreviewTestService(String path) {
mNativePaintPreviewTestService = PaintPreviewTestServiceJni.get().getInstance(testDataDir); mNativePaintPreviewTestService = PaintPreviewTestServiceJni.get().getInstance(path);
} }
@Override @Override
...@@ -24,8 +28,35 @@ public class PaintPreviewTestService implements NativePaintPreviewServiceProvide ...@@ -24,8 +28,35 @@ public class PaintPreviewTestService implements NativePaintPreviewServiceProvide
return mNativePaintPreviewTestService; return mNativePaintPreviewTestService;
} }
public boolean createSingleSkpForKey(
String key, String url, int width, int height, Rect[] linkRects, String[] links) {
if (mNativePaintPreviewTestService == 0) {
Log.e(TAG, "No native service.");
return false;
}
assert linkRects.length == links.length;
int flattenedRects[] = new int[linkRects.length * 4];
for (int i = 0; i < linkRects.length; i++) {
flattenedRects[i * 4] = linkRects[i].left;
flattenedRects[i * 4 + 1] = linkRects[i].top;
flattenedRects[i * 4 + 2] = linkRects[i].width();
flattenedRects[i * 4 + 3] = linkRects[i].height();
}
boolean ret = PaintPreviewTestServiceJni.get().createSingleSkpForKey(
mNativePaintPreviewTestService, key, url, width, height, flattenedRects, links);
if (!ret) {
Log.e(TAG, "Native failed to setup files for testing.");
}
return ret;
}
@NativeMethods @NativeMethods
interface Natives { interface Natives {
long getInstance(String testDataDir); long getInstance(String path);
boolean createSingleSkpForKey(long nativePaintPreviewTestService, String key, String url,
int width, int height, int[] flattenedRects, String[] links);
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment