blob: c4e9d1ddc4c0e1f9f58897b92a0d2ad66f612aac [file] [log] [blame]
// Copyright 2019 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 CONTENT_PUBLIC_TEST_NO_RENDERER_CRASHES_ASSERTION_H_
#define CONTENT_PUBLIC_TEST_NO_RENDERER_CRASHES_ASSERTION_H_
#include <map>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test_utils.h"
namespace content {
class RenderProcessHost;
// Usually, a test should fail when BrowserTestBase detects a crash in a
// renderer process (see the NoRendererCrashesAssertion helper class below).
// The ScopedAllowRendererCrashes class can be used to temporarily suspend this
// behavior - this is useful in tests that explicitly expect renderer kills or
// crashes.
class ScopedAllowRendererCrashes {
public:
// Ignores *all* renderer crashes.
ScopedAllowRendererCrashes();
// Ignores crashes of |process|.
explicit ScopedAllowRendererCrashes(RenderProcessHost* process);
// Ignores crashes of the process associated with the given |frame|.
explicit ScopedAllowRendererCrashes(const ToRenderFrameHost& frame);
~ScopedAllowRendererCrashes();
private:
// The id of the process that is allowed to crash while this
// ScopedAllowRendererCrashes object is alive.
//
// The special |ChildProcessHost::kInvalidUniqueID| value means that crashes
// of *any* process are allowed.
int process_id_;
DISALLOW_COPY_AND_ASSIGN(ScopedAllowRendererCrashes);
};
// Helper that BrowserTestBase can use to start monitoring for renderer crashes
// (triggering a test failure when a renderer crash happens).
//
// TODO(lukasza): https://crbug.com/972220: Actually start using this class,
// by constructing it from BrowserTestBase::ProxyRunTestOnMainThreadLoop
// (before calling PreRunTestOnMainThread).
class NoRendererCrashesAssertion : public NotificationObserver {
public:
NoRendererCrashesAssertion();
~NoRendererCrashesAssertion() override;
private:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
NotificationRegistrar registrar_;
// Internal helper class for keeping track of suspensions that should cause
// us to ignore crashes in a specific renderer process.
class Suspensions {
public:
static Suspensions& GetInstance();
Suspensions();
~Suspensions();
// Methods for adding or removing a suspension.
//
// The special |ChildProcessHost::kInvalidUniqueID| value means that crashes
// of *any* process are allowed.
void AddSuspension(int process_id);
void RemoveSuspension(int process_id);
// Checks whether |process_id| has an active suspension.
bool IsSuspended(int process_id);
private:
friend class base::NoDestructor<Suspensions>;
std::map<int, int> process_id_to_suspension_count_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(Suspensions);
};
friend ScopedAllowRendererCrashes;
FRIEND_TEST_ALL_PREFIXES(NoRendererCrashesAssertionSuspensions,
SingleProcess);
FRIEND_TEST_ALL_PREFIXES(NoRendererCrashesAssertionSuspensions, AllProcesses);
FRIEND_TEST_ALL_PREFIXES(NoRendererCrashesAssertionSuspensions,
SingleProcessNesting);
FRIEND_TEST_ALL_PREFIXES(NoRendererCrashesAssertionSuspensions,
AllProcessesNesting);
DISALLOW_COPY_AND_ASSIGN(NoRendererCrashesAssertion);
};
} // namespace content
#endif // CONTENT_PUBLIC_TEST_NO_RENDERER_CRASHES_ASSERTION_H_