// Copyright 2016 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 <stddef.h>

#include <algorithm>
#include <vector>

#include "cc/base/tiling_data.h"
#include "cc/test/geometry_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cc {
namespace {

void TestSpiralIterate(int source_line_number,
                       const TilingData& tiling_data,
                       const gfx::Rect& consider,
                       const gfx::Rect& ignore,
                       const gfx::Rect& center,
                       const std::vector<std::pair<int, int>>& expected) {
  std::vector<std::pair<int, int>> actual_forward;
  for (TilingData::SpiralDifferenceIterator it(&tiling_data, consider, ignore,
                                               center);
       it; ++it) {
    actual_forward.push_back(it.index());
  }

  EXPECT_EQ(expected.size(), actual_forward.size()) << "error from line "
                                                    << source_line_number;
  for (size_t i = 0; i < std::min(expected.size(), actual_forward.size());
       ++i) {
    EXPECT_EQ(expected[i].first, actual_forward[i].first)
        << "i: " << i << " error from line: " << source_line_number;
    EXPECT_EQ(expected[i].second, actual_forward[i].second)
        << "i: " << i << " error from line: " << source_line_number;
  }

  std::vector<std::pair<int, int>> actual_reverse;
  for (TilingData::ReverseSpiralDifferenceIterator it(&tiling_data, consider,
                                                      ignore, center);
       it; ++it) {
    actual_reverse.push_back(it.index());
  }

  std::vector<std::pair<int, int>> reversed_expected = expected;
  std::reverse(reversed_expected.begin(), reversed_expected.end());
  EXPECT_EQ(reversed_expected.size(), actual_reverse.size())
      << "error from line " << source_line_number;
  for (size_t i = 0;
       i < std::min(reversed_expected.size(), actual_reverse.size()); ++i) {
    EXPECT_EQ(reversed_expected[i].first, actual_reverse[i].first)
        << "i: " << i << " error from line: " << source_line_number;
    EXPECT_EQ(reversed_expected[i].second, actual_reverse[i].second)
        << "i: " << i << " error from line: " << source_line_number;
  }
}

TEST(SpiralIteratorTest, NoIgnoreFullConsider) {
  TilingData tiling_data(gfx::Size(10, 10), gfx::Size(30, 30), false);
  gfx::Rect consider(30, 30);
  gfx::Rect ignore;
  std::vector<std::pair<int, int>> expected;

  // Center is in the center of the tiling.
  gfx::Rect center(15, 15, 1, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  4│  3│  2│
  //    ├───┼───┼───┤
  //  1 │  5│  *│  1│
  //    ├───┼───┼───┤
  //  2 │  6│  7│  8│
  //    └───┴───┴───┘
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(2, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center is off to the right side of the tiling (and far away).
  center = gfx::Rect(100, 15, 1, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  7│  4│  1│
  //    ├───┼───┼───┤
  //  1 │  8│  5│  2│    *
  //    ├───┼───┼───┤
  //  2 │  9│  6│  3│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center is the bottom right corner of the tiling.
  center = gfx::Rect(25, 25, 1, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  6│  5│  4│
  //    ├───┼───┼───┤
  //  1 │  7│  2│  1│
  //    ├───┼───┼───┤
  //  2 │  8│  3│  *│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center is off the top left side of the tiling.
  center = gfx::Rect(-60, -50, 1, 1);

  // Layout of the tiling data, and expected return order:
  //  * x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  1│  2│  6│
  //    ├───┼───┼───┤
  //  1 │  3│  4│  5│
  //    ├───┼───┼───┤
  //  2 │  7│  8│  9│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(2, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Two tile center.
  center = gfx::Rect(15, 15, 1, 10);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  5│  4│  3│
  //    ├───┼───┼───┤
  //  1 │  6│  *│  2│
  //    ├───┼───┼───┤
  //  2 │  7│  *│  1│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);
}

TEST(SpiralIteratorTest, SmallConsider) {
  TilingData tiling_data(gfx::Size(10, 10), gfx::Size(50, 50), false);
  gfx::Rect ignore;
  std::vector<std::pair<int, int>> expected;
  gfx::Rect center(15, 15, 1, 1);

  // Consider is one cell.
  gfx::Rect consider(1, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │  1│   │   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  1 │   │  *│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  2 │   │   │   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  3 │   │   │   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  4 │   │   │   │   │   │
  //    └───┴───┴───┴───┴───┘
  expected.push_back(std::make_pair(0, 0));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Consider is bottom right corner.
  consider = gfx::Rect(25, 25, 10, 10);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │   │   │   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  1 │   │  *│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  2 │   │   │  1│  2│   │
  //    ├───┼───┼───┼───┼───┤
  //  3 │   │   │  3│  4│   │
  //    ├───┼───┼───┼───┼───┤
  //  4 │   │   │   │   │   │
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(3, 2));
  expected.push_back(std::make_pair(2, 3));
  expected.push_back(std::make_pair(3, 3));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Consider is one column.
  consider = gfx::Rect(11, 0, 1, 100);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │   │  2│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  1 │   │  *│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  2 │   │  3│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  3 │   │  4│   │   │   │
  //    ├───┼───┼───┼───┼───┤
  //  4 │   │  5│   │   │   │
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(1, 3));
  expected.push_back(std::make_pair(1, 4));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);
}

TEST(SpiralIteratorTest, HasIgnore) {
  TilingData tiling_data(gfx::Size(10, 10), gfx::Size(50, 50), false);
  gfx::Rect consider(50, 50);
  std::vector<std::pair<int, int>> expected;
  gfx::Rect center(15, 15, 1, 1);

  // Full ignore.
  gfx::Rect ignore(50, 50);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │  I│  I│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  1 │  I│  *│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  2 │  I│  I│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  3 │  I│  I│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  4 │  I│  I│  I│  I│  I│
  //    └───┴───┴───┴───┴───┘
  expected.clear();

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // 3 column ignore.
  ignore = gfx::Rect(15, 0, 20, 100);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │  1│  I│  I│  I│  8│
  //    ├───┼───┼───┼───┼───┤
  //  1 │  2│  *│  I│  I│  7│
  //    ├───┼───┼───┼───┼───┤
  //  2 │  3│  I│  I│  I│  6│
  //    ├───┼───┼───┼───┼───┤
  //  3 │  4│  I│  I│  I│  5│
  //    ├───┼───┼───┼───┼───┤
  //  4 │  9│  I│  I│  I│ 10│
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(0, 3));
  expected.push_back(std::make_pair(4, 3));
  expected.push_back(std::make_pair(4, 2));
  expected.push_back(std::make_pair(4, 1));
  expected.push_back(std::make_pair(4, 0));
  expected.push_back(std::make_pair(0, 4));
  expected.push_back(std::make_pair(4, 4));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Ignore covers the top half.
  ignore = gfx::Rect(50, 25);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │  I│  I│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  1 │  I│  *│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  2 │  I│  I│  I│  I│  I│
  //    ├───┼───┼───┼───┼───┤
  //  3 │  1│  2│  3│  4│  5│
  //    ├───┼───┼───┼───┼───┤
  //  4 │  6│  7│  8│  9│ 10│
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 3));
  expected.push_back(std::make_pair(1, 3));
  expected.push_back(std::make_pair(2, 3));
  expected.push_back(std::make_pair(3, 3));
  expected.push_back(std::make_pair(4, 3));
  expected.push_back(std::make_pair(0, 4));
  expected.push_back(std::make_pair(1, 4));
  expected.push_back(std::make_pair(2, 4));
  expected.push_back(std::make_pair(3, 4));
  expected.push_back(std::make_pair(4, 4));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);
}

TEST(SpiralIteratorTest, RectangleCenter) {
  TilingData tiling_data(gfx::Size(10, 10), gfx::Size(50, 50), false);
  gfx::Rect consider(50, 50);
  std::vector<std::pair<int, int>> expected;
  gfx::Rect ignore;

  // Two cell center
  gfx::Rect center(25, 25, 1, 10);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │ 19│ 18│ 17│ 16│ 15│
  //    ├───┼───┼───┼───┼───┤
  //  1 │ 20│  5│  4│  3│ 14│
  //    ├───┼───┼───┼───┼───┤
  //  2 │ 21│  6│  *│  2│ 13│
  //    ├───┼───┼───┼───┼───┤
  //  3 │ 22│  7│  *│  1│ 12│
  //    ├───┼───┼───┼───┼───┤
  //  4 │ 23│  8│  9│ 10│ 11│
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(3, 3));
  expected.push_back(std::make_pair(3, 2));
  expected.push_back(std::make_pair(3, 1));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(1, 3));
  expected.push_back(std::make_pair(1, 4));
  expected.push_back(std::make_pair(2, 4));
  expected.push_back(std::make_pair(3, 4));
  expected.push_back(std::make_pair(4, 4));
  expected.push_back(std::make_pair(4, 3));
  expected.push_back(std::make_pair(4, 2));
  expected.push_back(std::make_pair(4, 1));
  expected.push_back(std::make_pair(4, 0));
  expected.push_back(std::make_pair(3, 0));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(0, 3));
  expected.push_back(std::make_pair(0, 4));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Three by two center.
  center = gfx::Rect(15, 25, 20, 10);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2   3   4
  //  y ┌───┬───┬───┬───┬───┐
  //  0 │ 19│ 18│ 17│ 16│ 15│
  //    ├───┼───┼───┼───┼───┤
  //  1 │  7│  6│  5│  4│  3│
  //    ├───┼───┼───┼───┼───┤
  //  2 │  8│  *│  *│  *│  2│
  //    ├───┼───┼───┼───┼───┤
  //  3 │  9│  *│  *│  *│  1│
  //    ├───┼───┼───┼───┼───┤
  //  4 │ 10│ 11│ 12│ 13│ 14│
  //    └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(4, 3));
  expected.push_back(std::make_pair(4, 2));
  expected.push_back(std::make_pair(4, 1));
  expected.push_back(std::make_pair(3, 1));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(0, 3));
  expected.push_back(std::make_pair(0, 4));
  expected.push_back(std::make_pair(1, 4));
  expected.push_back(std::make_pair(2, 4));
  expected.push_back(std::make_pair(3, 4));
  expected.push_back(std::make_pair(4, 4));
  expected.push_back(std::make_pair(4, 0));
  expected.push_back(std::make_pair(3, 0));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Column center off the left side.
  center = gfx::Rect(-50, 0, 30, 50);

  // Layout of the tiling data, and expected return order:
  //     x 0   1   2   3   4
  //   y ┌───┬───┬───┬───┬───┐
  // * 0 │  5│ 10│ 15│ 20│ 25│
  //     ├───┼───┼───┼───┼───┤
  // * 1 │  4│  9│ 14│ 19│ 24│
  //     ├───┼───┼───┼───┼───┤
  // * 2 │  3│  8│ 13│ 18│ 23│
  //     ├───┼───┼───┼───┼───┤
  // * 3 │  2│  7│ 12│ 17│ 22│
  //     ├───┼───┼───┼───┼───┤
  // * 4 │  1│  6│ 11│ 16│ 21│
  //     └───┴───┴───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 4));
  expected.push_back(std::make_pair(0, 3));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(1, 4));
  expected.push_back(std::make_pair(1, 3));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(2, 4));
  expected.push_back(std::make_pair(2, 3));
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(3, 4));
  expected.push_back(std::make_pair(3, 3));
  expected.push_back(std::make_pair(3, 2));
  expected.push_back(std::make_pair(3, 1));
  expected.push_back(std::make_pair(3, 0));
  expected.push_back(std::make_pair(4, 4));
  expected.push_back(std::make_pair(4, 3));
  expected.push_back(std::make_pair(4, 2));
  expected.push_back(std::make_pair(4, 1));
  expected.push_back(std::make_pair(4, 0));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);
}

TEST(SpiralIteratorTest, EdgeCases) {
  TilingData tiling_data(gfx::Size(10, 10), gfx::Size(30, 30), false);
  std::vector<std::pair<int, int>> expected;
  gfx::Rect center;
  gfx::Rect consider;
  gfx::Rect ignore;

  // Ignore contains, but is not equal to, consider and center.
  ignore = gfx::Rect(15, 0, 20, 30);
  consider = gfx::Rect(20, 10, 10, 20);
  center = gfx::Rect(25, 0, 5, 5);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │   │  I│  *│
  //    ├───┼───┼───┤
  //  1 │   │  I│  I│
  //    ├───┼───┼───┤
  //  2 │   │  I│  I│
  //    └───┴───┴───┘
  expected.clear();

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center intersects with consider.
  ignore = gfx::Rect();
  center = gfx::Rect(0, 15, 30, 15);
  consider = gfx::Rect(15, 30);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  2│  1│   │
  //    ├───┼───┼───┤
  //  1 │  *│  *│  *│
  //    ├───┼───┼───┤
  //  2 │  *│  *│  *│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 0));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Consider and ignore are non-intersecting.
  ignore = gfx::Rect(5, 30);
  consider = gfx::Rect(25, 0, 5, 30);
  center = gfx::Rect(15, 0, 1, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  I│  *│  1│
  //    ├───┼───┼───┤
  //  1 │  I│   │  2│
  //    ├───┼───┼───┤
  //  2 │  I│   │  3│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center intersects with ignore.
  consider = gfx::Rect(30, 30);
  center = gfx::Rect(15, 0, 1, 30);
  ignore = gfx::Rect(0, 15, 30, 1);

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  3│  *│  2│
  //    ├───┼───┼───┤
  //  1 │  I│  *│  I│
  //    ├───┼───┼───┤
  //  2 │  4│  *│  1│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center and ignore are the same.
  consider = gfx::Rect(30, 30);
  center = gfx::Rect(15, 0, 1, 30);
  ignore = center;

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  4│  *│  3│
  //    ├───┼───┼───┤
  //  1 │  5│  *│  2│
  //    ├───┼───┼───┤
  //  2 │  6│  *│  1│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Empty tiling data.
  TilingData empty_data(gfx::Size(0, 0), gfx::Size(0, 0), false);

  expected.clear();

  TestSpiralIterate(__LINE__, empty_data, consider, ignore, center, expected);

  // Empty consider.
  ignore = gfx::Rect();
  center = gfx::Rect(1, 1, 1, 1);
  consider = gfx::Rect();

  expected.clear();

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Empty center. Note: This arbitrarily puts the center to be off the top-left
  // corner.
  consider = gfx::Rect(30, 30);
  ignore = gfx::Rect();
  center = gfx::Rect();

  // Layout of the tiling data, and expected return order:
  //    x 0   1   2
  //  y ┌───┬───┬───┐
  //  0 │  1│  2│  6│
  //    ├───┼───┼───┤
  //  1 │  3│  4│  5│
  //    ├───┼───┼───┤
  //  2 │  7│  8│  9│
  //    └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(2, 2));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Every rect is empty.
  ignore = gfx::Rect();
  center = gfx::Rect();
  consider = gfx::Rect();

  expected.clear();

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Center is just to the left of cover, and off of the tiling's left side.
  consider = gfx::Rect(30, 30);
  ignore = gfx::Rect();
  center = gfx::Rect(-20, 0, 19, 30);

  // Layout of the tiling data, and expected return order:
  //     x 0   1   2
  //   y ┌───┬───┬───┐
  // * 0 │  3│  6│  9│
  //     ├───┼───┼───┤
  // * 1 │  2│  5│  8│
  //     ├───┼───┼───┤
  // * 2 │  1│  4│  7│
  //     └───┴───┴───┘
  expected.clear();
  expected.push_back(std::make_pair(0, 2));
  expected.push_back(std::make_pair(0, 1));
  expected.push_back(std::make_pair(0, 0));
  expected.push_back(std::make_pair(1, 2));
  expected.push_back(std::make_pair(1, 1));
  expected.push_back(std::make_pair(1, 0));
  expected.push_back(std::make_pair(2, 2));
  expected.push_back(std::make_pair(2, 1));
  expected.push_back(std::make_pair(2, 0));

  TestSpiralIterate(__LINE__, tiling_data, consider, ignore, center, expected);

  // Tiling is smaller than tile size and center rect is not intersecting to
  // tiling rect.
  TilingData smaller_tiling(gfx::Size(10, 10), gfx::Size(1, 1), false);
  consider = gfx::Rect(10, 10);
  ignore = gfx::Rect();
  center = gfx::Rect(2, 2, 10, 10);

  // Layout of the tiling data, and expected return order:
  //    x   0
  //  y ┌───────┐
  //    │  1    │
  //  0 │       │
  //    │     * │
  //    └───────┘
  expected.clear();
  expected.push_back(std::make_pair(0, 0));

  TestSpiralIterate(__LINE__, smaller_tiling, consider, ignore, center,
                    expected);
}

}  // namespace

}  // namespace cc
