Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5436)

Unified Diff: chrome/browser/image_decoder_browsertest.cc

Issue 1129653002: Wait for pending requests to finish in ImageDecoder. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix kill test. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/image_decoder.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/image_decoder_browsertest.cc
diff --git a/chrome/browser/image_decoder_browsertest.cc b/chrome/browser/image_decoder_browsertest.cc
index f5c81eeb1bbae5eeabdd4a4138ab50d9d5e3a173..1cde39f1767fba9ea8a8f5d40c85c98d69146e8b 100644
--- a/chrome/browser/image_decoder_browsertest.cc
+++ b/chrome/browser/image_decoder_browsertest.cc
@@ -9,20 +9,35 @@
#include <signal.h>
#endif
+#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/browser_child_process_observer.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/test/test_utils.h"
+#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
namespace {
+std::string GetValidPngString() {
+ // 1x1 PNG. Does not get much smaller than this.
+ static const char kPngData[] =
+ "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52"
+ "\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53"
+ "\xde\x00\x00\x00\x0c\x49\x44\x41\x54\x08\xd7\x63\xf8\xff\xff\x3f"
+ "\x00\x05\xfe\x02\xfe\xdc\xcc\x59\xe7\x00\x00\x00\x00\x49\x45\x4e"
+ "\x44\xae\x42\x60\x82";
+ // Need to specify the buffer size because it contains NULs.
+ return std::string(kPngData, sizeof(kPngData) - 1);
+}
+
class TestImageRequest : public ImageDecoder::ImageRequest {
public:
explicit TestImageRequest(const base::Closure& quit_closure)
- : quit_closure_(quit_closure),
+ : decode_succeeded_(false),
+ quit_closure_(quit_closure),
quit_called_(false) {
}
@@ -32,8 +47,11 @@ class TestImageRequest : public ImageDecoder::ImageRequest {
}
}
+ const bool decode_succeeded() const { return decode_succeeded_; }
+
private:
void OnImageDecoded(const SkBitmap& decoded_image) override {
+ decode_succeeded_ = true;
Quit();
}
@@ -47,6 +65,8 @@ class TestImageRequest : public ImageDecoder::ImageRequest {
quit_closure_.Run();
}
+ bool decode_succeeded_;
+
base::Closure quit_closure_;
bool quit_called_;
@@ -55,7 +75,10 @@ class TestImageRequest : public ImageDecoder::ImageRequest {
class KillProcessObserver : public content::BrowserChildProcessObserver {
public:
- KillProcessObserver() {
+ KillProcessObserver()
+ : did_kill_(false),
+ utility_process_name_(
+ l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_IMAGE_DECODER_NAME)) {
Add(this);
}
@@ -63,13 +86,19 @@ class KillProcessObserver : public content::BrowserChildProcessObserver {
Remove(this);
}
+ bool did_kill() const { return did_kill_; }
+
private:
void BrowserChildProcessHostConnected(
const content::ChildProcessData& data) override {
- base::ProcessHandle handle = data.handle;
-
- if (handle == base::kNullProcessHandle)
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (data.handle == base::kNullProcessHandle ||
+ data.name != utility_process_name_) {
return;
+ }
+
+ ASSERT_FALSE(did_kill_);
+ base::ProcessHandle handle = data.handle;
#if defined(OS_WIN)
// On windows, duplicate the process handle since base::Process closes it on
@@ -77,19 +106,30 @@ class KillProcessObserver : public content::BrowserChildProcessObserver {
base::ProcessHandle out_handle;
if (!::DuplicateHandle(GetCurrentProcess(), handle,
GetCurrentProcess(), &out_handle,
- 0, FALSE, DUPLICATE_SAME_ACCESS))
+ 0, FALSE, DUPLICATE_SAME_ACCESS)) {
return;
+ }
handle = out_handle;
#endif
- EXPECT_TRUE(base::Process(handle).Terminate(0, true));
Lei Zhang 2015/05/07 00:24:13 0 is "exit normally" on Windows -> OnProcessCrashe
+ // Use a non-zero exit code so it counts as a crash.
+ EXPECT_TRUE(base::Process(handle).Terminate(1, true));
+ did_kill_ = true;
}
+
+ bool did_kill_;
+ const base::string16 utility_process_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(KillProcessObserver);
};
#if defined(OS_POSIX)
class FreezeProcessObserver : public content::BrowserChildProcessObserver {
public:
- FreezeProcessObserver() {
+ FreezeProcessObserver()
+ : did_freeze_(false),
+ utility_process_name_(
+ l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_IMAGE_DECODER_NAME)) {
Add(this);
}
@@ -97,12 +137,36 @@ class FreezeProcessObserver : public content::BrowserChildProcessObserver {
Remove(this);
}
+ bool did_freeze() const { return did_freeze_; }
+
private:
+ static void ResumeFrozenProcess(const base::ProcessHandle& handle) {
+ DCHECK_NE(handle, base::kNullProcessHandle);
+ EXPECT_EQ(0, kill(handle, SIGCONT));
Anand Mistry (off Chromium) 2015/05/07 05:35:22 I'm not 100% sure, but I suspect there's a race he
Lei Zhang 2015/05/07 22:31:05 How do you feel if I just removed this test? It no
Anand Mistry (off Chromium) 2015/05/08 00:02:10 That sounds fine.
+ }
+
void BrowserChildProcessHostConnected(
const content::ChildProcessData& data) override {
- if (data.handle != base::kNullProcessHandle)
- EXPECT_EQ(0, kill(data.handle, SIGSTOP));
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (data.handle == base::kNullProcessHandle ||
+ data.name != utility_process_name_) {
+ return;
+ }
+
+ ASSERT_FALSE(did_freeze_);
+ did_freeze_ = true;
+ EXPECT_EQ(0, kill(data.handle, SIGSTOP));
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&FreezeProcessObserver::ResumeFrozenProcess, data.handle),
+ base::TimeDelta::FromSeconds(7));
}
+
+ bool did_freeze_;
+ const base::string16 utility_process_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(FreezeProcessObserver);
};
#endif // defined(OS_POSIX)
@@ -117,6 +181,16 @@ IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, Basic) {
TestImageRequest test_request(runner->QuitClosure());
ImageDecoder::Start(&test_request, std::string());
runner->Run();
+ EXPECT_FALSE(test_request.decode_succeeded());
+}
+
+IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, BasicDecode) {
+ scoped_refptr<content::MessageLoopRunner> runner =
+ new content::MessageLoopRunner;
+ TestImageRequest test_request(runner->QuitClosure());
+ ImageDecoder::Start(&test_request, GetValidPngString());
+ runner->Run();
+ EXPECT_TRUE(test_request.decode_succeeded());
}
IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndDestroy) {
@@ -129,24 +203,36 @@ IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndDestroy) {
runner->Run();
}
+// Killing the utility process counts as a crash. Thus the request fails.
+// This test is inherently racy because KillProcessObserver lives on the UI
+// thread but ImageDecoder does its work mainly on the IO thread. So the test
+// checks for both possible valid outcomes.
Anand Mistry (off Chromium) 2015/05/07 05:35:22 I should have commented this when I wrote this tes
Lei Zhang 2015/05/07 22:36:22 Done.
IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndKillProcess) {
KillProcessObserver observer;
scoped_refptr<content::MessageLoopRunner> runner =
new content::MessageLoopRunner;
- scoped_ptr<TestImageRequest> test_request(
- new TestImageRequest(runner->QuitClosure()));
- ImageDecoder::Start(test_request.get(), std::string());
+ TestImageRequest test_request(runner->QuitClosure());
+ ImageDecoder::Start(&test_request, GetValidPngString());
runner->Run();
+ if (!test_request.decode_succeeded()) {
+ // The UI thread won the race. Make sure the utility process did get killed.
+ EXPECT_TRUE(observer.did_kill());
+ }
+ // Else the IO thread won the race and the image got decoded. Oh well.
}
#if defined(OS_POSIX)
+// Freezing the utility process just long enough that it would try to end batch
+// mode. However, the outstanding request prevents that. The request should
+// eventually finish.
IN_PROC_BROWSER_TEST_F(ImageDecoderBrowserTest, StartAndFreezeProcess) {
FreezeProcessObserver observer;
scoped_refptr<content::MessageLoopRunner> runner =
new content::MessageLoopRunner;
- scoped_ptr<TestImageRequest> test_request(
- new TestImageRequest(runner->QuitClosure()));
- ImageDecoder::Start(test_request.get(), std::string());
+ TestImageRequest test_request(runner->QuitClosure());
+ ImageDecoder::Start(&test_request, GetValidPngString());
runner->Run();
+ EXPECT_TRUE(observer.did_freeze());
+ EXPECT_TRUE(test_request.decode_succeeded());
}
#endif // defined(OS_POSIX)
« no previous file with comments | « chrome/browser/image_decoder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698