Browse Source
Merge pull request #7302 from VPeruS/check-deadlock
Merge pull request #7302 from VPeruS/check-deadlock
[input_common] Fixed thread hangnce_cpp
committed by
GitHub
4 changed files with 190 additions and 44 deletions
-
32src/input_common/drivers/udp_client.cpp
-
21src/input_common/helpers/udp_protocol.h
-
3src/tests/CMakeLists.txt
-
136src/tests/input_common/calibration_configuration_job.cpp
@ -0,0 +1,136 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <array>
|
||||
|
#include <string>
|
||||
|
#include <thread>
|
||||
|
#include <boost/asio.hpp>
|
||||
|
#include <boost/crc.hpp>
|
||||
|
#include <catch2/catch.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); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue