File size: 4,981 Bytes
3708354 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <array>
#include <string>
#include <thread>
#include <boost/asio.hpp>
#include <boost/crc.hpp>
#include <catch2/catch_test_macros.hpp>
#include "input_common/drivers/udp_client.h"
#include "input_common/helpers/udp_protocol.h"
class FakeCemuhookServer {
public:
FakeCemuhookServer()
: socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
~FakeCemuhookServer() {
is_running = false;
boost::system::error_code error_code;
socket.shutdown(boost::asio::socket_base::shutdown_both, error_code);
socket.close();
if (handler.joinable()) {
handler.join();
}
}
u16 GetPort() {
return socket.local_endpoint().port();
}
std::string GetHost() {
return socket.local_endpoint().address().to_string();
}
void Run(const std::vector<InputCommon::CemuhookUDP::Response::TouchPad> touch_movement_path) {
constexpr size_t HeaderSize = sizeof(InputCommon::CemuhookUDP::Header);
constexpr size_t PadDataSize =
sizeof(InputCommon::CemuhookUDP::Message<InputCommon::CemuhookUDP::Response::PadData>);
REQUIRE(touch_movement_path.size() > 0);
is_running = true;
handler = std::thread([touch_movement_path, this]() {
auto current_touch_position = touch_movement_path.begin();
while (is_running) {
boost::asio::ip::udp::endpoint sender_endpoint;
boost::system::error_code error_code;
auto received_size = socket.receive_from(boost::asio::buffer(receive_buffer),
sender_endpoint, 0, error_code);
if (received_size < HeaderSize) {
continue;
}
InputCommon::CemuhookUDP::Header header{};
std::memcpy(&header, receive_buffer.data(), HeaderSize);
switch (header.type) {
case InputCommon::CemuhookUDP::Type::PadData: {
InputCommon::CemuhookUDP::Response::PadData pad_data{};
pad_data.touch[0] = *current_touch_position;
const auto pad_message = InputCommon::CemuhookUDP::CreateMessage(
InputCommon::CemuhookUDP::SERVER_MAGIC, pad_data, 0);
std::memcpy(send_buffer.data(), &pad_message, PadDataSize);
socket.send_to(boost::asio::buffer(send_buffer, PadDataSize), sender_endpoint,
0, error_code);
bool can_advance =
std::next(current_touch_position) != touch_movement_path.end();
if (can_advance) {
std::advance(current_touch_position, 1);
}
break;
}
case InputCommon::CemuhookUDP::Type::PortInfo:
case InputCommon::CemuhookUDP::Type::Version:
default:
break;
}
}
});
}
private:
boost::asio::io_service io_service;
boost::asio::ip::udp::socket socket;
std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer;
std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer;
bool is_running = false;
std::thread handler;
};
TEST_CASE("CalibrationConfigurationJob completed", "[input_common]") {
Common::Event complete_event;
FakeCemuhookServer server;
server.Run({{
.is_active = 1,
.x = 0,
.y = 0,
},
{
.is_active = 1,
.x = 200,
.y = 200,
}});
InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status{};
u16 min_x{};
u16 min_y{};
u16 max_x{};
u16 max_y{};
InputCommon::CemuhookUDP::CalibrationConfigurationJob job(
server.GetHost(), server.GetPort(),
[&status,
&complete_event](InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status_) {
status = status_;
if (status ==
InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed) {
complete_event.Set();
}
},
[&](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) {
min_x = min_x_;
min_y = min_y_;
max_x = max_x_;
max_y = max_y_;
});
complete_event.WaitUntil(std::chrono::system_clock::now() + std::chrono::seconds(10));
REQUIRE(status == InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed);
REQUIRE(min_x == 0);
REQUIRE(min_y == 0);
REQUIRE(max_x == 200);
REQUIRE(max_y == 200);
}
|