// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wm/window_transient_descendant_iterator.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_state.h"
#include "base/functional/bind.h"
#include "ui/aura/window.h"
#include "ui/wm/core/window_util.h"
namespace ash {
class WindowTransientDescendantIteratorTest : public AshTestBase {
public:
WindowTransientDescendantIteratorTest() = default;
WindowTransientDescendantIteratorTest(
const WindowTransientDescendantIteratorTest&) = delete;
WindowTransientDescendantIteratorTest& operator=(
const WindowTransientDescendantIteratorTest&) = delete;
~WindowTransientDescendantIteratorTest() override = default;
// Creates a test set of windows parented like a linked list. The result
// vector will have window in order: ABCD.
void CreateTestLinkedList(
std::vector<std::unique_ptr<aura::Window>>* out_result) {
ASSERT_TRUE(out_result->empty());
for (char c : {'A', 'B', 'C', 'D'}) {
auto window = CreateTestWindow();
window->SetName(std::string(1, c));
if (!out_result->empty())
::wm::AddTransientChild(out_result->back().get(), window.get());
out_result->push_back(std::move(window));
}
}
// A
// / \
// B F
// / \
// C E
// /
// D
// Creates a test set of windows parented like in the diagram above. The
// result vector will have the windows in preorder: ABCDEF.
void CreateTestInOrderTree(
std::vector<std::unique_ptr<aura::Window>>* out_result) {
ASSERT_TRUE(out_result->empty());
auto window_a = CreateTestWindow();
auto window_b = CreateTestWindow();
auto window_c = CreateTestWindow();
auto window_d = CreateTestWindow();
auto window_e = CreateTestWindow();
auto window_f = CreateTestWindow();
window_a->SetName("A");
window_b->SetName("B");
window_c->SetName("C");
window_d->SetName("D");
window_e->SetName("E");
window_f->SetName("F");
// Create the tree structure.
::wm::AddTransientChild(window_a.get(), window_b.get());
::wm::AddTransientChild(window_a.get(), window_f.get());
::wm::AddTransientChild(window_b.get(), window_c.get());
::wm::AddTransientChild(window_b.get(), window_e.get());
::wm::AddTransientChild(window_c.get(), window_d.get());
// Insert windows in preorder traversal: ABCDEF.
out_result->push_back(std::move(window_a));
out_result->push_back(std::move(window_b));
out_result->push_back(std::move(window_c));
out_result->push_back(std::move(window_d));
out_result->push_back(std::move(window_e));
out_result->push_back(std::move(window_f));
}
};
// Tests that case that windows a parented transiently like a linked list.
TEST_F(WindowTransientDescendantIteratorTest, LinkedList) {
std::vector<std::unique_ptr<aura::Window>> windows;
CreateTestLinkedList(&windows);
int index = 0;
std::string str;
for (auto* window : GetTransientTreeIterator(windows[0].get())) {
EXPECT_EQ(windows[index].get(), window);
str += window->GetName();
++index;
}
EXPECT_EQ("ABCD", str);
}
// Tests that case that windows a parented transiently like a tree. The iterator
// should go through the windows with preorder traversal.
TEST_F(WindowTransientDescendantIteratorTest, Tree) {
std::vector<std::unique_ptr<aura::Window>> windows;
CreateTestInOrderTree(&windows);
// The windows in |window| are added with preorder traversal, so they should
// match exactly the window order from the transient iterator.
int index = 0;
std::string str;
for (auto* window : GetTransientTreeIterator(windows[0].get())) {
EXPECT_EQ(windows[index].get(), window);
str += window->GetName();
++index;
}
EXPECT_EQ("ABCDEF", str);
}
// Tests that windows that affected by a given predicate do not show up when
// iterating.
TEST_F(WindowTransientDescendantIteratorTest, LinkedListWithPredicate) {
std::vector<std::unique_ptr<aura::Window>> windows;
CreateTestLinkedList(&windows);
auto predicate = [](aura::Window* w) { return w->GetName() == "C"; };
std::string str;
for (auto* window : GetTransientTreeIterator(
windows[0].get(), base::BindRepeating(predicate))) {
str += window->GetName();
}
EXPECT_EQ("ABD", str);
}
TEST_F(WindowTransientDescendantIteratorTest, TreeWithPredicate) {
std::vector<std::unique_ptr<aura::Window>> windows;
CreateTestInOrderTree(&windows);
auto predicate = [](aura::Window* w) {
return w->GetName() == "B" || w->GetName() == "E";
};
std::string str;
for (auto* window : GetTransientTreeIterator(
windows[0].get(), base::BindRepeating(predicate))) {
str += window->GetName();
}
EXPECT_EQ("ACDF", str);
}
} // namespace ash