summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorboliu <boliu@chromium.org>2014-12-10 16:54:41 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-11 00:55:03 +0000
commitec5d6de3135398882a0975c95de98d5111aa6c2e (patch)
treefb4ef88deca5e11943a3ae1ea54a9bb77dee7ba8
parent9015c8b4419268a35a5c1a0f2afb7a2a2aaff699 (diff)
downloadchromium_src-ec5d6de3135398882a0975c95de98d5111aa6c2e.zip
chromium_src-ec5d6de3135398882a0975c95de98d5111aa6c2e.tar.gz
chromium_src-ec5d6de3135398882a0975c95de98d5111aa6c2e.tar.bz2
aw: Rendering test harness and end-to-end smoke test
The test harness is heavily modelled after LayerTreeTests in cc. Add implementation for simulating invalidation and functor behavior. Add in enough hooks to allow a end-to-end smoke test from invalidation to draw to functor draw. BUG=418346 Review URL: https://codereview.chromium.org/786533002 Cr-Commit-Position: refs/heads/master@{#307812}
-rw-r--r--android_webview/android_webview_tests.gypi3
-rw-r--r--android_webview/browser/browser_view_renderer_unittest.cc20
-rw-r--r--android_webview/browser/test/fake_window.cc235
-rw-r--r--android_webview/browser/test/fake_window.h94
-rw-r--r--android_webview/browser/test/rendering_test.cc51
-rw-r--r--android_webview/browser/test/rendering_test.h39
-rw-r--r--android_webview/lib/DEPS1
-rw-r--r--android_webview/lib/main/webview_tests.cc5
8 files changed, 415 insertions, 33 deletions
diff --git a/android_webview/android_webview_tests.gypi b/android_webview/android_webview_tests.gypi
index 2dc3c7b..2e1ba0e 100644
--- a/android_webview/android_webview_tests.gypi
+++ b/android_webview/android_webview_tests.gypi
@@ -113,6 +113,7 @@
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
'../ui/base/ui_base.gyp:ui_base_jni_headers',
+ '../ui/gl/gl.gyp:gl',
'android_webview_common',
'android_webview_unittests_jni',
],
@@ -127,6 +128,8 @@
'browser/browser_view_renderer_unittest.cc',
'browser/net/android_stream_reader_url_request_job_unittest.cc',
'browser/net/input_stream_reader_unittest.cc',
+ 'browser/test/fake_window.cc',
+ 'browser/test/fake_window.h',
'browser/test/rendering_test.cc',
'browser/test/rendering_test.h',
'lib/main/webview_tests.cc',
diff --git a/android_webview/browser/browser_view_renderer_unittest.cc b/android_webview/browser/browser_view_renderer_unittest.cc
index 6ecf99a..0c2786b 100644
--- a/android_webview/browser/browser_view_renderer_unittest.cc
+++ b/android_webview/browser/browser_view_renderer_unittest.cc
@@ -2,13 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "android_webview/browser/browser_view_renderer.h"
#include "android_webview/browser/test/rendering_test.h"
namespace android_webview {
-TEST_F(RenderingTest, SmokeTest) {
- SetUpTestHarness();
- RunTest();
-}
+class SmokeTest : public RenderingTest {
+ void StartTest() override {
+ browser_view_renderer_->SetContinuousInvalidate(true);
+ }
+
+ void WillOnDraw() override {
+ browser_view_renderer_->SetContinuousInvalidate(false);
+ }
+
+ void DidDrawOnRT(SharedRendererState* functor) override {
+ EndTest();
+ }
+};
+
+RENDERING_TEST_F(SmokeTest);
} // namespace android_webview
diff --git a/android_webview/browser/test/fake_window.cc b/android_webview/browser/test/fake_window.cc
new file mode 100644
index 0000000..c709f62e
--- /dev/null
+++ b/android_webview/browser/test/fake_window.cc
@@ -0,0 +1,235 @@
+// Copyright 2014 The Chromium 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 "android_webview/browser/test/fake_window.h"
+
+#include "android_webview/browser/browser_view_renderer.h"
+#include "android_webview/public/browser/draw_gl.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace android_webview {
+
+class FakeWindow::ScopedMakeCurrent {
+ public:
+ ScopedMakeCurrent(FakeWindow* view_root) : view_root_(view_root) {
+ DCHECK(!view_root_->context_current_);
+ view_root_->context_current_ = true;
+ bool result = view_root_->context_->MakeCurrent(view_root_->surface_.get());
+ DCHECK(result);
+ };
+
+ ~ScopedMakeCurrent() {
+ DCHECK(view_root_->context_current_);
+ view_root_->context_current_ = false;
+
+ // Release the underlying EGLContext. This is required because the real
+ // GLContextEGL may no longer be current here and to satisfy DCHECK in
+ // GLContextEGL::IsCurrent.
+ eglMakeCurrent(view_root_->surface_->GetDisplay(), EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ view_root_->context_->ReleaseCurrent(view_root_->surface_.get());
+ }
+
+ private:
+ FakeWindow* view_root_;
+};
+
+FakeWindow::FakeWindow(BrowserViewRenderer* view,
+ WindowHooks* hooks,
+ gfx::Rect location)
+ : view_(view),
+ hooks_(hooks),
+ surface_size_(100, 100),
+ location_(location),
+ on_draw_hardware_pending_(false),
+ functor_(nullptr),
+ context_current_(false),
+ weak_ptr_factory_(this) {
+ CheckCurrentlyOnUIThread();
+ DCHECK(view_);
+ view_->OnAttachedToWindow(location_.width(), location_.height());
+}
+
+FakeWindow::~FakeWindow() {
+ CheckCurrentlyOnUIThread();
+}
+
+void FakeWindow::Detach() {
+ CheckCurrentlyOnUIThread();
+ view_->OnDetachedFromWindow();
+
+ if (render_thread_loop_) {
+ base::WaitableEvent completion(true, false);
+ render_thread_loop_->PostTask(
+ FROM_HERE, base::Bind(&FakeWindow::DestroyOnRT, base::Unretained(this),
+ &completion));
+ completion.Wait();
+ }
+
+ render_thread_.reset();
+ functor_ = nullptr;
+}
+
+void FakeWindow::RequestDrawGL(bool wait_for_completion) {
+ CheckCurrentlyOnUIThread();
+ base::WaitableEvent completion(true, false);
+ render_thread_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&FakeWindow::ProcessFunctorOnRT, base::Unretained(this),
+ wait_for_completion ? &completion : nullptr));
+ if (wait_for_completion)
+ completion.Wait();
+}
+
+void FakeWindow::ProcessFunctorOnRT(base::WaitableEvent* sync) {
+ CheckCurrentlyOnRT();
+ AwDrawGLInfo process_info;
+ process_info.version = kAwDrawGLInfoVersion;
+ process_info.mode = AwDrawGLInfo::kModeProcess;
+
+ hooks_->WillProcessOnRT(functor_);
+ {
+ ScopedMakeCurrent make_current(this);
+ functor_->DrawGL(&process_info);
+ }
+ hooks_->DidProcessOnRT(functor_);
+
+ if (sync)
+ sync->Signal();
+}
+
+void FakeWindow::PostInvalidate() {
+ CheckCurrentlyOnUIThread();
+ if (on_draw_hardware_pending_)
+ return;
+ on_draw_hardware_pending_ = true;
+ base::MessageLoopProxy::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&FakeWindow::OnDrawHardware, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void FakeWindow::OnDrawHardware() {
+ CheckCurrentlyOnUIThread();
+ DCHECK(on_draw_hardware_pending_);
+ on_draw_hardware_pending_ = false;
+
+ bool success = view_->OnDrawHardware();
+ if (success) {
+ CreateRenderThreadIfNeeded();
+
+ base::WaitableEvent completion(true, false);
+ render_thread_loop_->PostTask(
+ FROM_HERE, base::Bind(&FakeWindow::DrawFunctorOnRT,
+ base::Unretained(this), &completion));
+ completion.Wait();
+ }
+}
+
+void FakeWindow::DrawFunctorOnRT(base::WaitableEvent* sync) {
+ CheckCurrentlyOnRT();
+ // Ok to access UI functions until sync is signalled.
+ gfx::Rect location = location_;
+ {
+ AwDrawGLInfo process_info;
+ process_info.version = kAwDrawGLInfoVersion;
+ process_info.mode = AwDrawGLInfo::kModeSync;
+
+ hooks_->WillSyncOnRT(functor_);
+ functor_->DrawGL(&process_info);
+ hooks_->DidSyncOnRT(functor_);
+ }
+ sync->Signal();
+
+ AwDrawGLInfo draw_info;
+ draw_info.version = kAwDrawGLInfoVersion;
+ draw_info.mode = AwDrawGLInfo::kModeDraw;
+ draw_info.clip_left = location.x();
+ draw_info.clip_top = location.y();
+ draw_info.clip_right = location.x() + location.width();
+ draw_info.clip_bottom = location.y() + location.height();
+ draw_info.width = surface_size_.width();
+ draw_info.height = surface_size_.height();
+ draw_info.is_layer = false;
+
+ draw_info.transform[0] = 1.0;
+ draw_info.transform[1] = 0.0;
+ draw_info.transform[2] = 0.0;
+ draw_info.transform[3] = 0.0;
+
+ draw_info.transform[4] = 0.0;
+ draw_info.transform[5] = 1.0;
+ draw_info.transform[6] = 0.0;
+ draw_info.transform[7] = 0.0;
+
+ draw_info.transform[8] = 0.0;
+ draw_info.transform[9] = 0.0;
+ draw_info.transform[10] = 1.0;
+ draw_info.transform[11] = 0.0;
+
+ draw_info.transform[12] = 0.0;
+ draw_info.transform[13] = 0.0;
+ draw_info.transform[14] = 0.0;
+ draw_info.transform[15] = 1.0;
+
+ hooks_->WillDrawOnRT(functor_);
+ {
+ ScopedMakeCurrent make_current(this);
+ functor_->DrawGL(&draw_info);
+ }
+ hooks_->DidDrawOnRT(functor_);
+}
+
+void FakeWindow::CheckCurrentlyOnUIThread() {
+ DCHECK(ui_checker_.CalledOnValidSequencedThread());
+}
+
+void FakeWindow::CreateRenderThreadIfNeeded() {
+ CheckCurrentlyOnUIThread();
+ if (functor_) {
+ DCHECK(render_thread_.get());
+ DCHECK(render_thread_loop_.get());
+ return;
+ }
+ functor_ = view_->GetAwDrawGLViewContext();
+ render_thread_.reset(new base::Thread("TestRenderThread"));
+ render_thread_->Start();
+ render_thread_loop_ = render_thread_->task_runner();
+ rt_checker_.DetachFromSequence();
+
+ base::WaitableEvent completion(true, false);
+ render_thread_loop_->PostTask(
+ FROM_HERE, base::Bind(&FakeWindow::InitializeOnRT, base::Unretained(this),
+ &completion));
+ completion.Wait();
+}
+
+void FakeWindow::InitializeOnRT(base::WaitableEvent* sync) {
+ CheckCurrentlyOnRT();
+ surface_ = gfx::GLSurface::CreateOffscreenGLSurface(surface_size_);
+ DCHECK(surface_.get());
+ DCHECK(surface_->GetHandle());
+ context_ = gfx::GLContext::CreateGLContext(nullptr, surface_.get(),
+ gfx::PreferDiscreteGpu);
+ DCHECK(context_.get());
+ sync->Signal();
+}
+
+void FakeWindow::DestroyOnRT(base::WaitableEvent* sync) {
+ CheckCurrentlyOnRT();
+ if (context_) {
+ DCHECK(!context_->IsCurrent(surface_.get()));
+ context_ = nullptr;
+ surface_ = nullptr;
+ }
+ sync->Signal();
+}
+
+void FakeWindow::CheckCurrentlyOnRT() {
+ DCHECK(rt_checker_.CalledOnValidSequencedThread());
+}
+
+} // namespace android_webview
diff --git a/android_webview/browser/test/fake_window.h b/android_webview/browser/test/fake_window.h
new file mode 100644
index 0000000..abe9ec0
--- /dev/null
+++ b/android_webview/browser/test/fake_window.h
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_TEST_FAKE_WINDOW_H_
+#define ANDROID_WEBVIEW_BROWSER_TEST_FAKE_WINDOW_H_
+
+#include <map>
+
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/single_thread_task_runner.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+namespace base {
+class Thread;
+class WaitableEvent;
+}
+
+namespace android_webview {
+
+class BrowserViewRenderer;
+class SharedRendererState;
+
+class WindowHooks {
+ public:
+ virtual ~WindowHooks() {}
+
+ virtual void WillOnDraw() = 0;
+ virtual void DidOnDraw() = 0;
+
+ virtual void WillSyncOnRT(SharedRendererState* functor) = 0;
+ virtual void DidSyncOnRT(SharedRendererState* functor) = 0;
+ virtual void WillProcessOnRT(SharedRendererState* functor) = 0;
+ virtual void DidProcessOnRT(SharedRendererState* functor) = 0;
+ virtual void WillDrawOnRT(SharedRendererState* functor) = 0;
+ virtual void DidDrawOnRT(SharedRendererState* functor) = 0;
+};
+
+class FakeWindow {
+ public:
+ FakeWindow(BrowserViewRenderer* view,
+ WindowHooks* hooks,
+ gfx::Rect location);
+ ~FakeWindow();
+
+ void Detach();
+
+ // BrowserViewRendererClient methods.
+ void RequestDrawGL(bool wait_for_completion);
+ void PostInvalidate();
+
+ private:
+ class ScopedMakeCurrent;
+
+ void OnDrawHardware();
+ void CheckCurrentlyOnUIThread();
+ void CreateRenderThreadIfNeeded();
+
+ void InitializeOnRT(base::WaitableEvent* sync);
+ void DestroyOnRT(base::WaitableEvent* sync);
+ void ProcessFunctorOnRT(base::WaitableEvent* sync);
+ void DrawFunctorOnRT(base::WaitableEvent* sync);
+ void CheckCurrentlyOnRT();
+
+ // const so can be used on both threads.
+ BrowserViewRenderer* const view_;
+ WindowHooks* const hooks_;
+ const gfx::Size surface_size_;
+
+ // UI thread members.
+ gfx::Rect location_;
+ bool on_draw_hardware_pending_;
+ base::SequenceChecker ui_checker_;
+
+ // Render thread members.
+ scoped_ptr<base::Thread> render_thread_;
+ base::SequenceChecker rt_checker_;
+ SharedRendererState* functor_;
+ scoped_refptr<base::SingleThreadTaskRunner> render_thread_loop_;
+ scoped_refptr<gfx::GLSurface> surface_;
+ scoped_refptr<gfx::GLContext> context_;
+ bool context_current_;
+
+ base::WeakPtrFactory<FakeWindow> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeWindow);
+};
+
+} // namespace android_webview
+
+#endif // ANDROID_WEBVIEW_BROWSER_TEST_FAKE_WINDOW_H_
diff --git a/android_webview/browser/test/rendering_test.cc b/android_webview/browser/test/rendering_test.cc
index bea0de1..995b602 100644
--- a/android_webview/browser/test/rendering_test.cc
+++ b/android_webview/browser/test/rendering_test.cc
@@ -6,36 +6,27 @@
#include "android_webview/browser/browser_view_renderer.h"
#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "content/public/test/test_synchronous_compositor_android.h"
namespace android_webview {
RenderingTest::RenderingTest() : message_loop_(new base::MessageLoop) {
+ ui_proxy_ = base::MessageLoopProxy::current();
}
RenderingTest::~RenderingTest() {
+ if (window_.get())
+ window_->Detach();
}
void RenderingTest::SetUpTestHarness() {
DCHECK(!browser_view_renderer_.get());
browser_view_renderer_.reset(
new BrowserViewRenderer(this, base::MessageLoopProxy::current()));
+ InitializeCompositor();
+ Attach();
}
-class RenderingTest::ScopedInitializeCompositor {
- public:
- explicit ScopedInitializeCompositor(RenderingTest* test) : test_(test) {
- test_->InitializeCompositor();
- }
-
- ~ScopedInitializeCompositor() { test_->TeardownCompositor(); }
-
- private:
- RenderingTest* test_;
- DISALLOW_COPY_AND_ASSIGN(ScopedInitializeCompositor);
-};
-
void RenderingTest::InitializeCompositor() {
DCHECK(!compositor_.get());
DCHECK(browser_view_renderer_.get());
@@ -43,25 +34,43 @@ void RenderingTest::InitializeCompositor() {
compositor_->SetClient(browser_view_renderer_.get());
}
-void RenderingTest::TeardownCompositor() {
- DCHECK(compositor_.get());
- DCHECK(browser_view_renderer_.get());
- compositor_.reset();
+void RenderingTest::Attach() {
+ window_.reset(
+ new FakeWindow(browser_view_renderer_.get(), this, gfx::Rect(100, 100)));
}
void RenderingTest::RunTest() {
- ScopedInitializeCompositor initialize_compositor(this);
- StartTest();
+ SetUpTestHarness();
+
+ ui_proxy_->PostTask(
+ FROM_HERE, base::Bind(&RenderingTest::StartTest, base::Unretained(this)));
+ message_loop_->Run();
+}
+
+void RenderingTest::StartTest() {
+ EndTest();
+}
+
+void RenderingTest::EndTest() {
+ ui_proxy_->PostTask(FROM_HERE, base::Bind(&RenderingTest::QuitMessageLoop,
+ base::Unretained(this)));
+}
+
+void RenderingTest::QuitMessageLoop() {
+ DCHECK_EQ(base::MessageLoop::current(), message_loop_.get());
+ message_loop_->QuitWhenIdle();
}
bool RenderingTest::RequestDrawGL(bool wait_for_completion) {
- return false;
+ window_->RequestDrawGL(wait_for_completion);
+ return true;
}
void RenderingTest::OnNewPicture() {
}
void RenderingTest::PostInvalidate() {
+ window_->PostInvalidate();
}
void RenderingTest::InvalidateOnFunctorDestroy() {
diff --git a/android_webview/browser/test/rendering_test.h b/android_webview/browser/test/rendering_test.h
index 31347ec..e5c64ed 100644
--- a/android_webview/browser/test/rendering_test.h
+++ b/android_webview/browser/test/rendering_test.h
@@ -6,7 +6,9 @@
#define ANDROID_WEBVIEW_BROWSER_TEST_RENDERING_TEST_H_
#include "android_webview/browser/browser_view_renderer_client.h"
+#include "android_webview/browser/test/fake_window.h"
#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -20,8 +22,11 @@ class TestSynchronousCompositor;
namespace android_webview {
class BrowserViewRenderer;
+class FakeWindow;
-class RenderingTest : public testing::Test, public BrowserViewRendererClient {
+class RenderingTest : public testing::Test,
+ public BrowserViewRendererClient,
+ public WindowHooks {
public:
// BrowserViewRendererClient overrides.
bool RequestDrawGL(bool wait_for_completion) override;
@@ -38,27 +43,45 @@ class RenderingTest : public testing::Test, public BrowserViewRendererClient {
float max_page_scale_factor) override {}
void DidOverscroll(gfx::Vector2d overscroll_delta) override {}
+ // WindowHooks overrides.
+ void WillOnDraw() override {}
+ void DidOnDraw() override {}
+ void WillSyncOnRT(SharedRendererState* functor) override {}
+ void DidSyncOnRT(SharedRendererState* functor) override {}
+ void WillProcessOnRT(SharedRendererState* functor) override {}
+ void DidProcessOnRT(SharedRendererState* functor) override {}
+ void WillDrawOnRT(SharedRendererState* functor) override {}
+ void DidDrawOnRT(SharedRendererState* functor) override {}
+
protected:
RenderingTest();
~RenderingTest() override;
- void SetUpTestHarness();
+ virtual void SetUpTestHarness();
+ virtual void StartTest();
+
void RunTest();
+ void InitializeCompositor();
+ void Attach();
+ void EndTest();
- virtual void StartTest() {}
+ scoped_refptr<base::MessageLoopProxy> ui_proxy_;
+ scoped_ptr<BrowserViewRenderer> browser_view_renderer_;
+ scoped_ptr<content::TestSynchronousCompositor> compositor_;
+ scoped_ptr<FakeWindow> window_;
private:
- class ScopedInitializeCompositor;
- void InitializeCompositor();
- void TeardownCompositor();
+ void QuitMessageLoop();
const scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<content::TestSynchronousCompositor> compositor_;
- scoped_ptr<BrowserViewRenderer> browser_view_renderer_;
DISALLOW_COPY_AND_ASSIGN(RenderingTest);
};
+#define RENDERING_TEST_F(TEST_FIXTURE_NAME) \
+ TEST_F(TEST_FIXTURE_NAME, RunTest) { RunTest(); } \
+ class NeedsSemicolon##TEST_FIXTURE_NAME {}
+
} // namespace android_webview
#endif // ANDROID_WEBVIEW_BROWSER_TEST_RENDERING_TEST_H_
diff --git a/android_webview/lib/DEPS b/android_webview/lib/DEPS
index 4442017..ab83088 100644
--- a/android_webview/lib/DEPS
+++ b/android_webview/lib/DEPS
@@ -3,4 +3,5 @@ include_rules = [
"+components", # For jni registers.
"+content/public",
"+media/base/media_switches.h", # For media command line switches.
+ "+ui/gl",
]
diff --git a/android_webview/lib/main/webview_tests.cc b/android_webview/lib/main/webview_tests.cc
index 08109fe..0fe4b6b 100644
--- a/android_webview/lib/main/webview_tests.cc
+++ b/android_webview/lib/main/webview_tests.cc
@@ -4,9 +4,14 @@
#include "android_webview/native/android_webview_jni_registrar.h"
#include "base/android/jni_android.h"
+#include "base/command_line.h"
#include "base/test/test_suite.h"
+#include "content/public/common/content_switches.h"
+#include "ui/gl/gl_surface.h"
int main(int argc, char** argv) {
android_webview::RegisterJni(base::android::AttachCurrentThread());
+ CommandLine::ForCurrentProcess()->AppendSwitch(switches::kSingleProcess);
+ gfx::GLSurface::InitializeOneOffForTests();
return base::TestSuite(argc, argv).Run();
}