// 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 "ash/accelerators/accelerator_table.h"
#include "base/macros.h"
#include "base/md5.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 as of 2017-11-30.
constexpr int kNonSearchAcceleratorsNum = 92;
// The hash of non-Search-based accelerators as of 2017-11-30.
// See HashAcceleratorData().
// TODO: adding Search-based accelerators should not update this hash
// (crbug.com/778432).
constexpr char kNonSearchAcceleratorsHash[] =
    "cc7e1da44f75a8bc3a8605a06934c8a4";

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

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, 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_LE(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
