chromium/ash/wm/window_transient_descendant_iterator_unittest.cc

// 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