chromium/ash/public/cpp/accelerator_keycode_lookup_cache_unittest.cc

// Copyright 2023 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/public/cpp/accelerator_keycode_lookup_cache.h"

#include <memory>
#include <string>

#include "ui/base/ime/ash/input_method_manager.h"
#include "ui/base/ime/ash/mock_input_method_manager.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h"

#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

using KeyCodeLookupEntry = AcceleratorKeycodeLookupCache::KeyCodeLookupEntry;

class AcceleratorKeycodeLookupCacheTest : public testing::Test {
 public:
  class TestInputMethodManager : public input_method::MockInputMethodManager {
   public:
    void AddObserver(
        input_method::InputMethodManager::Observer* observer) override {
      observers_.AddObserver(observer);
    }

    void RemoveObserver(
        input_method::InputMethodManager::Observer* observer) override {
      observers_.RemoveObserver(observer);
    }

    // Calls all observers with Observer::InputMethodChanged
    void NotifyInputMethodChanged() {
      for (auto& observer : observers_) {
        observer.InputMethodChanged(
            /*manager=*/this, /*profile=*/nullptr, /*show_message=*/false);
      }
    }

    base::ObserverList<InputMethodManager::Observer>::Unchecked observers_;
  };

  AcceleratorKeycodeLookupCacheTest() {
    input_method_manager_ = new TestInputMethodManager();
    input_method::InputMethodManager::Initialize(input_method_manager_);

    layout_engine_ = std::make_unique<ui::StubKeyboardLayoutEngine>();
    ui::KeyboardLayoutEngineManager::ResetKeyboardLayoutEngine();
    ui::KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
        layout_engine_.get());

    lookup_cache_ = std::make_unique<AcceleratorKeycodeLookupCache>();
  }

  ~AcceleratorKeycodeLookupCacheTest() override = default;

 protected:
  std::map<std::pair<ui::KeyboardCode, bool>, KeyCodeLookupEntry> cache() {
    return lookup_cache_->key_code_to_cache_entry_;
  }

  std::unique_ptr<AcceleratorKeycodeLookupCache> lookup_cache_;
  std::unique_ptr<ui::StubKeyboardLayoutEngine> layout_engine_;
  // Test global singleton. Delete is handled by InputMethodManager::Shutdown().
  raw_ptr<TestInputMethodManager> input_method_manager_;
};

TEST_F(AcceleratorKeycodeLookupCacheTest, ImeChanged) {
  const std::u16string expected = u"a";

  EXPECT_TRUE(cache().empty());
  lookup_cache_->InsertOrAssign(ui::KeyboardCode::VKEY_A,
                                /*remap_positional_key=*/false,
                                ui::DomCode::NONE, ui::DomKey::NONE,
                                ui::KeyboardCode::VKEY_A, expected);
  // Expect the cache to be populated.
  std::optional<KeyCodeLookupEntry> found_entry = lookup_cache_->Find(
      ui::KeyboardCode::VKEY_A, /*remap_positional_key=*/false);
  EXPECT_TRUE(found_entry.has_value());
  EXPECT_EQ(expected, found_entry->key_display);

  // Trigger IME change event, expect the cache to be cleared.
  input_method_manager_->NotifyInputMethodChanged();
  EXPECT_TRUE(cache().empty());
  found_entry = lookup_cache_->Find(ui::KeyboardCode::VKEY_A,
                                    /*remap_positional_key=*/false);
  EXPECT_FALSE(found_entry.has_value());
}

}  // namespace ash