#include "content/browser/renderer_host/commit_deferring_condition_runner.h"
#include "content/public/browser/commit_deferring_condition.h"
#include "content/public/test/mock_navigation_handle.h"
#include "content/public/test/test_renderer_host.h"
#include "content/test/mock_commit_deferring_condition.h"
namespace content {
class CommitDeferringConditionRunnerTest
: public RenderViewHostTestHarness,
public CommitDeferringConditionRunner::Delegate {
public:
CommitDeferringConditionRunnerTest() = default;
void SetUp() override {
RenderViewHostTestHarness::SetUp();
runner_ = base::WrapUnique(new CommitDeferringConditionRunner(
*this, CommitDeferringCondition::NavigationType::kOther,
std::nullopt));
}
bool was_delegate_notified() const { return was_delegate_notified_; }
bool is_deferring() { return runner_->is_deferred_; }
CommitDeferringConditionRunner* runner() { return runner_.get(); }
private:
void OnCommitDeferringConditionChecksComplete(
CommitDeferringCondition::NavigationType navigation_type,
std::optional<FrameTreeNodeId> candidate_prerender_frame_tree_node_id)
override {
EXPECT_EQ(navigation_type,
CommitDeferringCondition::NavigationType::kOther);
EXPECT_FALSE(candidate_prerender_frame_tree_node_id.has_value());
was_delegate_notified_ = true;
}
std::unique_ptr<CommitDeferringConditionRunner> runner_;
bool was_delegate_notified_ = false;
};
class MockHandleConditionWrapper : public MockNavigationHandle,
public MockCommitDeferringConditionWrapper {
public:
explicit MockHandleConditionWrapper(CommitDeferringCondition::Result result)
: MockCommitDeferringConditionWrapper(*this, result) {}
};
TEST_F(CommitDeferringConditionRunnerTest, NoRegisteredConditions) {
EXPECT_FALSE(was_delegate_notified());
runner()->ProcessChecks();
EXPECT_TRUE(was_delegate_notified());
}
TEST_F(CommitDeferringConditionRunnerTest, BasicAsync) {
MockHandleConditionWrapper condition(
CommitDeferringCondition::Result::kDefer);
runner()->AddConditionForTesting(condition.PassToDelegate());
runner()->ProcessChecks();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition.WasInvoked());
EXPECT_TRUE(is_deferring());
condition.CallResumeClosure();
EXPECT_TRUE(was_delegate_notified());
}
TEST_F(CommitDeferringConditionRunnerTest, BasicSync) {
MockHandleConditionWrapper condition(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition.PassToDelegate());
runner()->ProcessChecks();
EXPECT_TRUE(was_delegate_notified());
EXPECT_TRUE(condition.WasInvoked());
}
TEST_F(CommitDeferringConditionRunnerTest, BasicCancelled) {
MockHandleConditionWrapper condition(
CommitDeferringCondition::Result::kCancelled);
runner()->AddConditionForTesting(condition.PassToDelegate());
runner()->ProcessChecks();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition.WasInvoked());
}
TEST_F(CommitDeferringConditionRunnerTest, MultipleConditionsLastAsync) {
MockHandleConditionWrapper condition1(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition1.PassToDelegate());
MockHandleConditionWrapper condition2(
CommitDeferringCondition::Result::kDefer);
runner()->AddConditionForTesting(condition2.PassToDelegate());
MockHandleConditionWrapper condition3(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition3.PassToDelegate());
MockHandleConditionWrapper condition4(
CommitDeferringCondition::Result::kDefer);
runner()->AddConditionForTesting(condition4.PassToDelegate());
runner()->ProcessChecks();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition1.WasInvoked());
EXPECT_TRUE(condition2.WasInvoked());
EXPECT_FALSE(condition3.WasInvoked());
EXPECT_FALSE(condition4.WasInvoked());
EXPECT_TRUE(is_deferring());
condition2.CallResumeClosure();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition3.WasInvoked());
EXPECT_TRUE(condition4.WasInvoked());
EXPECT_TRUE(is_deferring());
condition4.CallResumeClosure();
EXPECT_TRUE(was_delegate_notified());
EXPECT_FALSE(is_deferring());
}
TEST_F(CommitDeferringConditionRunnerTest, MultipleConditionsLastSync) {
MockHandleConditionWrapper condition1(
CommitDeferringCondition::Result::kDefer);
runner()->AddConditionForTesting(condition1.PassToDelegate());
MockHandleConditionWrapper condition2(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition2.PassToDelegate());
MockHandleConditionWrapper condition3(
CommitDeferringCondition::Result::kDefer);
runner()->AddConditionForTesting(condition3.PassToDelegate());
MockHandleConditionWrapper condition4(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition4.PassToDelegate());
runner()->ProcessChecks();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition1.WasInvoked());
EXPECT_FALSE(condition2.WasInvoked());
EXPECT_TRUE(is_deferring());
condition1.CallResumeClosure();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition2.WasInvoked());
EXPECT_TRUE(condition3.WasInvoked());
EXPECT_FALSE(condition4.WasInvoked());
EXPECT_TRUE(is_deferring());
condition3.CallResumeClosure();
EXPECT_TRUE(condition4.WasInvoked());
EXPECT_TRUE(was_delegate_notified());
EXPECT_FALSE(is_deferring());
}
TEST_F(CommitDeferringConditionRunnerTest, MultipleConditionsWithCancelled) {
MockHandleConditionWrapper condition1(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition1.PassToDelegate());
MockHandleConditionWrapper condition2(
CommitDeferringCondition::Result::kCancelled);
runner()->AddConditionForTesting(condition2.PassToDelegate());
MockHandleConditionWrapper condition3(
CommitDeferringCondition::Result::kProceed);
runner()->AddConditionForTesting(condition3.PassToDelegate());
runner()->ProcessChecks();
EXPECT_FALSE(was_delegate_notified());
EXPECT_TRUE(condition1.WasInvoked());
EXPECT_TRUE(condition2.WasInvoked());
EXPECT_FALSE(condition3.WasInvoked());
EXPECT_FALSE(is_deferring());
}
}