// Copyright (c) 2012 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 <set>
#include <tuple>

#include "ash/accelerators/accelerator_table.h"
#include "base/hash/md5.h"
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

namespace {

// The number of non-Search-based accelerators.
constexpr int kNonSearchAcceleratorsNum = 92;
// The hash of non-Search-based accelerators. See HashAcceleratorData().
constexpr char kNonSearchAcceleratorsHash[] =
    "2fc4ce8b0d4f3629b7a4c9bdf1fa0deb";

struct Cmp {
  bool operator()(const AcceleratorData& lhs,
                  const AcceleratorData& rhs) const {
    // Do not check |action|.
    return std::tie(lhs.trigger_on_press, lhs.keycode, lhs.modifiers) <
           std::tie(rhs.trigger_on_press, rhs.keycode, rhs.modifiers);
  }
};

std::string AcceleratorDataToString(const AcceleratorData& accelerator) {
  return base::StringPrintf(
      "trigger_on_press=%s keycode=%d shift=%s control=%s alt=%s search=%s "
      "action=%d",
      accelerator.trigger_on_press ? "true" : "false", accelerator.keycode,
      (accelerator.modifiers & ui::EF_SHIFT_DOWN) ? "true" : "false",
      (accelerator.modifiers & ui::EF_CONTROL_DOWN) ? "true" : "false",
      (accelerator.modifiers & ui::EF_ALT_DOWN) ? "true" : "false",
      (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false",
      accelerator.action);
}

std::string HashAcceleratorData(
    const std::vector<AcceleratorData> accelerators) {
  base::MD5Context context;
  base::MD5Init(&context);
  for (const AcceleratorData& accelerator : accelerators)
    base::MD5Update(&context, AcceleratorDataToString(accelerator));

  base::MD5Digest digest;
  base::MD5Final(&digest, &context);
  return MD5DigestToBase16(digest);
}

}  // namespace

TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) {
  std::set<AcceleratorData, Cmp> accelerators;
  for (size_t i = 0; i < kAcceleratorDataLength; ++i) {
    const AcceleratorData& entry = kAcceleratorData[i];
    EXPECT_TRUE(accelerators.insert(entry).second)
        << "Duplicated accelerator: " << AcceleratorDataToString(entry);
  }
}

TEST(AcceleratorTableTest, CheckDuplicatedReservedActions) {
  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kReservedActionsLength; ++i) {
    EXPECT_TRUE(actions.insert(kReservedActions[i]).second)
        << "Duplicated action: " << kReservedActions[i];
  }
}

TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtLoginOrLockScreen) {
  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kActionsAllowedAtLoginOrLockScreenLength; ++i) {
    EXPECT_TRUE(actions.insert(kActionsAllowedAtLoginOrLockScreen[i]).second)
        << "Duplicated action: " << kActionsAllowedAtLoginOrLockScreen[i];
  }
  for (size_t i = 0; i < kActionsAllowedAtLockScreenLength; ++i) {
    EXPECT_TRUE(actions.insert(kActionsAllowedAtLockScreen[i]).second)
        << "Duplicated action: " << kActionsAllowedAtLockScreen[i];
  }
}

TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtPowerMenu) {
  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kActionsAllowedAtPowerMenuLength; ++i) {
    EXPECT_TRUE(actions.insert(kActionsAllowedAtPowerMenu[i]).second)
        << "Duplicated action: " << kActionsAllowedAtPowerMenu[i];
  }
}

TEST(AcceleratorTableTest, CheckDuplicatedActionsAllowedAtModalWindow) {
  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kActionsAllowedAtModalWindowLength; ++i) {
    EXPECT_TRUE(actions.insert(kActionsAllowedAtModalWindow[i]).second)
        << "Duplicated action: " << kActionsAllowedAtModalWindow[i]
        << " at index: " << i;
  }
}

TEST(AcceleratorTableTest, CheckDuplicatedRepeatableActions) {
  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kRepeatableActionsLength; ++i) {
    EXPECT_TRUE(actions.insert(kRepeatableActions[i]).second)
        << "Duplicated action: " << kRepeatableActions[i] << " at index: " << i;
  }
}

TEST(AcceleratorTableTest, CheckDeprecatedAccelerators) {
  std::set<AcceleratorData, Cmp> deprecated_actions;
  for (size_t i = 0; i < kDeprecatedAcceleratorsLength; ++i) {
    // A deprecated action can never appear twice in the list.
    const AcceleratorData& entry = kDeprecatedAccelerators[i];
    EXPECT_TRUE(deprecated_actions.insert(entry).second)
        << "Duplicate deprecated accelerator: "
        << AcceleratorDataToString(entry);
  }

  std::set<AcceleratorAction> actions;
  for (size_t i = 0; i < kDeprecatedAcceleratorsDataLength; ++i) {
    // There must never be any duplicated actions.
    const DeprecatedAcceleratorData& data = kDeprecatedAcceleratorsData[i];
    EXPECT_TRUE(actions.insert(data.action).second) << "Deprecated action: "
                                                    << data.action;

    // The UMA histogram name must be of the format "Ash.Accelerators.*"
    std::string uma_histogram(data.uma_histogram_name);
    EXPECT_TRUE(base::StartsWith(uma_histogram, "Ash.Accelerators.",
                                 base::CompareCase::SENSITIVE));
  }
}

// All new accelerators should be Search-based and approved by UX.
TEST(AcceleratorTableTest, CheckSearchBasedAccelerators) {
  std::vector<AcceleratorData> non_search_accelerators;
  for (size_t i = 0; i < kAcceleratorDataLength; ++i) {
    const AcceleratorData& entry = kAcceleratorData[i];
    if (entry.modifiers & ui::EF_COMMAND_DOWN)
      continue;
    non_search_accelerators.emplace_back(entry);
  }

  const int accelerators_number = non_search_accelerators.size();
  EXPECT_EQ(accelerators_number, kNonSearchAcceleratorsNum)
      << "All new accelerators should be Search-based and approved by UX.";

  std::stable_sort(non_search_accelerators.begin(),
                   non_search_accelerators.end(), Cmp());
  const std::string non_search_accelerators_hash =
      HashAcceleratorData(non_search_accelerators);

  EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash)
      << "New accelerators must use the Search key. Please talk to the UX "
         "team.\n"
         "If you are removing a non-Search-based accelerator, please update "
         "the date along with the following values\n"
      << "kNonSearchAcceleratorsNum=" << accelerators_number << " and "
      << "kNonSearchAcceleratorsHash=\"" << non_search_accelerators_hash
      << "\"";
}

}  // namespace ash
