You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Kaleidoscope/testing/VirtualDeviceTest.h

147 lines
5.8 KiB

/* -*- mode: c++ -*-
* Copyright (C) 2020 Eric Paniagua (epaniagua@google.com)
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// IWYU pragma: no_include <__memory/unique_ptr.h>
#include <cstddef> // for size_t
#include <cstdint> // for uint32_t, int8_t, uint8_t
#include <initializer_list> // for initializer_list
#include <memory> // IWYU pragma: keep
#include <set> // for set
#include <vector> // for vector
#include "kaleidoscope/KeyAddr.h" // for KeyAddr
#include "kaleidoscope/key_defs.h" // for Key
#include "testing/ExpectedKeyboardReport.h" // for ExpectedKeyboardReport
#include "testing/ExpectedMouseReport.h" // for ExpectedMouseReport
#include "testing/HIDState.h" // for HIDState
#include "testing/SimHarness.h" // for SimHarness
#include "testing/State.h" // for State
#include "testing/gtest.h" // for Test
#include "testing/iostream.h" // for string
namespace kaleidoscope {
namespace testing {
// -----------------------------------------------------------------------------
// Utility classes for use in `PressKey()`/`ReleaseKey()` & `ExpectReport()`
// method invocations. These make those calls simpler by providing
// differentiated types for those polymorphic functions.
class AddKeycodes : public std::set<Key> {
public:
AddKeycodes(std::initializer_list<Key> list)
: std::set<Key>(list) {}
};
class RemoveKeycodes : public std::set<Key> {
public:
RemoveKeycodes(std::initializer_list<Key> list)
: std::set<Key>(list) {}
};
class Keycodes : public std::set<Key> {
public:
Keycodes(std::initializer_list<Key> list)
: std::set<Key>(list) {}
};
// -----------------------------------------------------------------------------
// The base class for testcases
class VirtualDeviceTest : public ::testing::Test {
protected:
void SetUp();
std::unique_ptr<State> RunCycle();
SimHarness sim_;
// ---------------------------------------------------------------------------
// A representation of the set of observed HID reports accumulated by the
// simulator as a testcase executes. It starts out empty, and a call to
// `LoadState()` is required in order to load those reports into this
// `output_state_` variable so that they can be used.
std::unique_ptr<State> output_state_ = nullptr;
// Load any accumulated observed HID reports from the simulator (since the
// previous call to this function).
void LoadState();
// Clear previous state. This should be used at the beginning of each
// `TEST_F()` call to clear out any accumulated state in the input and output
// queues.
void ClearState();
// Get a pointer to the current list of observed HID reports
const HIDState *HIDReports() const;
// Get the timestamp of a logged Keyboard HID report
uint32_t ReportTimestamp(size_t index) const;
// ---------------------------------------------------------------------------
// A vector of timestamps for input events. Calls to `PressKey()` &
// `ReleaseKey()` append timestamps to it when called.
std::vector<uint32_t> input_timestamps_ = {};
// Get the timestamp of a logged input event from `output_state_`
uint32_t EventTimestamp(size_t index) const;
// ---------------------------------------------------------------------------
// Press/release a keyswitch & log the input event timestamp
void PressKey(KeyAddr addr);
void ReleaseKey(KeyAddr addr);
// ---------------------------------------------------------------------------
// The following functions all add an expected value of HID report to the
// queue. They specify modifications to the current (expected) report, and a
// message to display if verification fails. Some versions allow multiple
// keycode changes in a single report; others only a single keycode. Some run
// the simulator for a specified number of milliseconds or cycles first. These
// expected-value reports are all stored in a vector:
std::vector<ExpectedKeyboardReport> expected_keyboard_reports_ = {};
void ExpectKeyboardReport(AddKeycodes added_keys,
RemoveKeycodes removed_keys,
std::string description);
void ExpectKeyboardReport(Keycodes added_keys, std::string description);
void ExpectKeyboardReport(AddKeycodes added_keys, std::string description);
void ExpectKeyboardReport(RemoveKeycodes removed_keys, std::string description);
std::vector<ExpectedMouseReport> expected_mouse_reports_ = {};
void ExpectMouseReport(uint8_t buttons, int8_t x, int8_t y, int8_t v, int8_t h, std::string description);
// ---------------------------------------------------------------------------
std::set<uint8_t> current_keyboard_keycodes_ = {};
// Manage the set of keycodes expected in the next report
void ClearKeyboardReport();
void AddToKeyboardReport(Key key);
void RemoveFromKeyboardReport(Key key);
// ---------------------------------------------------------------------------
// Compare accumulated observed and expected reports, matching both timestamps
// and keycodes.
void CheckReports() const;
void CheckKeyboardReports() const;
void CheckMouseReports() const;
};
} // namespace testing
} // namespace kaleidoscope