blob: 7986a96e08aa6a651a2a991acd425f7de0979291 [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.
#include "fuchsia/engine/browser/fake_semantic_tree.h"
#include <lib/fidl/cpp/binding.h>
#include <zircon/types.h>
#include "base/auto_reset.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
FakeSemanticTree::FakeSemanticTree() : semantic_tree_binding_(this) {}
FakeSemanticTree::~FakeSemanticTree() = default;
void FakeSemanticTree::Bind(
fidl::InterfaceRequest<fuchsia::accessibility::semantics::SemanticTree>
semantic_tree_request) {
semantic_tree_binding_.Bind(std::move(semantic_tree_request));
}
bool FakeSemanticTree::IsTreeValid(
fuchsia::accessibility::semantics::Node* node,
size_t* tree_size) {
(*tree_size)++;
if (!node->has_child_ids())
return true;
bool is_valid = true;
for (auto c : node->child_ids()) {
fuchsia::accessibility::semantics::Node* child = GetNodeWithId(c);
if (!child)
return false;
is_valid &= IsTreeValid(child, tree_size);
}
return is_valid;
}
void FakeSemanticTree::Disconnect() {
semantic_tree_binding_.Close(ZX_ERR_INTERNAL);
}
void FakeSemanticTree::RunUntilNodeCountAtLeast(size_t count) {
DCHECK(!on_commit_updates_);
if (nodes_.size() >= count)
return;
base::RunLoop run_loop;
base::AutoReset<base::RepeatingClosure> auto_reset(
&on_commit_updates_,
base::BindLambdaForTesting([this, count, &run_loop]() {
if (nodes_.size() >= count) {
run_loop.Quit();
}
}));
run_loop.Run();
}
void FakeSemanticTree::RunUntilCommitCountIs(size_t count) {
DCHECK(!on_commit_updates_);
if (count == num_commit_calls_)
return;
base::RunLoop run_loop;
base::AutoReset<base::RepeatingClosure> auto_reset(
&on_commit_updates_,
base::BindLambdaForTesting([this, count, &run_loop]() {
if (static_cast<size_t>(num_commit_calls_) == count) {
run_loop.Quit();
}
}));
run_loop.Run();
}
void FakeSemanticTree::SetNodeUpdatedCallback(
uint32_t node_id,
base::OnceClosure node_updated_callback) {
node_wait_id_ = node_id;
on_node_updated_callback_ = std::move(node_updated_callback);
}
fuchsia::accessibility::semantics::Node* FakeSemanticTree::GetNodeWithId(
uint32_t id) {
auto it = nodes_.find(id);
return it == nodes_.end() ? nullptr : &it->second;
}
fuchsia::accessibility::semantics::Node* FakeSemanticTree::GetNodeFromLabel(
base::StringPiece label) {
fuchsia::accessibility::semantics::Node* to_return = nullptr;
for (auto& n : nodes_) {
auto* node = &n.second;
if (node->has_attributes() && node->attributes().has_label() &&
node->attributes().label() == label) {
// There are sometimes multiple semantic nodes with the same label. Hit
// testing should return the node with the smallest node ID so behaviour
// is consistent with the hit testing API being called.
if (!to_return) {
to_return = node;
} else if (node->node_id() < to_return->node_id()) {
to_return = node;
}
}
}
return to_return;
}
fuchsia::accessibility::semantics::Node* FakeSemanticTree::GetNodeFromRole(
fuchsia::accessibility::semantics::Role role) {
for (auto& n : nodes_) {
auto* node = &n.second;
if (node->has_role() && node->role() == role)
return node;
}
return nullptr;
}
void FakeSemanticTree::UpdateSemanticNodes(
std::vector<fuchsia::accessibility::semantics::Node> nodes) {
num_update_calls_++;
bool wait_node_updated = false;
for (auto& node : nodes) {
if (node.node_id() == node_wait_id_ && on_node_updated_callback_)
wait_node_updated = true;
nodes_[node.node_id()] = std::move(node);
}
if (wait_node_updated)
std::move(on_node_updated_callback_).Run();
}
void FakeSemanticTree::DeleteSemanticNodes(std::vector<uint32_t> node_ids) {
num_delete_calls_++;
for (auto id : node_ids)
nodes_.erase(id);
}
void FakeSemanticTree::CommitUpdates(CommitUpdatesCallback callback) {
num_commit_calls_++;
callback();
if (on_commit_updates_)
on_commit_updates_.Run();
if (nodes_.size() > 0) {
size_t tree_size = 0;
EXPECT_TRUE(IsTreeValid(GetNodeWithId(0), &tree_size));
EXPECT_EQ(tree_size, nodes_.size());
}
}
void FakeSemanticTree::NotImplemented_(const std::string& name) {
NOTIMPLEMENTED() << name;
}
void FakeSemanticTree::Clear() {
nodes_.clear();
}