mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
parent
4f640dacab
commit
fa3a195077
@ -2,6 +2,10 @@
|
||||
* \brief Testing the functionality of the black hole component
|
||||
* \author Martin Stein
|
||||
* \date 2022-02-11
|
||||
*
|
||||
* FIXME
|
||||
*
|
||||
* Accessing the Audio_in and Audio_out connections is yet missing.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -24,202 +28,314 @@
|
||||
#include <uplink_session/connection.h>
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <input/keycodes.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Test {
|
||||
namespace Black_hole_test {
|
||||
|
||||
class Nic_test;
|
||||
class Uplink_test;
|
||||
class Capture_test;
|
||||
class Event_test;
|
||||
class Main;
|
||||
}
|
||||
|
||||
|
||||
class Test::Main
|
||||
class Black_hole_test::Nic_test
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
NIC_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||
NIC_PKT_SIZE = 100,
|
||||
UPLINK_BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||
UPLINK_PKT_SIZE = 100,
|
||||
BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||
PKT_SIZE = 100,
|
||||
};
|
||||
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Event::Connection _event { _env };
|
||||
Capture::Connection _capture { _env };
|
||||
Capture::Area _capture_screen_size { 1, 1 };
|
||||
Capture::Pixel _capture_pixels[1];
|
||||
Surface<Capture::Pixel> _capture_surface { _capture_pixels, _capture_screen_size };
|
||||
Capture::Connection::Screen _capture_screen { _capture, _env.rm(), _capture_screen_size };
|
||||
Audio_in::Connection _audio_in { _env, "left" };
|
||||
Audio_out::Connection _audio_out { _env, "left" };
|
||||
Allocator_avl _nic_tx_blk_alloc { &_heap };
|
||||
Nic::Connection _nic { _env, &_nic_tx_blk_alloc, NIC_BUF_SIZE, NIC_BUF_SIZE };
|
||||
Signal_handler<Main> _nic_handler { _env.ep(), *this, &Main::_handle_nic };
|
||||
unsigned long _nic_nr_of_sent_pkts { 0 };
|
||||
unsigned long _nic_nr_of_acked_pkts { 0 };
|
||||
Allocator_avl _uplink_tx_blk_alloc { &_heap };
|
||||
Constructible<Uplink::Connection> _uplink { };
|
||||
Signal_handler<Main> _uplink_handler { _env.ep(), *this, &Main::_handle_uplink };
|
||||
unsigned long _uplink_nr_of_sent_pkts { 0 };
|
||||
unsigned long _uplink_nr_of_acked_pkts { 0 };
|
||||
Env &_env;
|
||||
Allocator &_alloc;
|
||||
Signal_context_capability _sigh;
|
||||
Allocator_avl _tx_blk_alloc { &_alloc };
|
||||
Nic::Connection _connection { _env, &_tx_blk_alloc, BUF_SIZE, BUF_SIZE };
|
||||
unsigned long _nr_of_sent_pkts { 0 };
|
||||
unsigned long _nr_of_acked_pkts { 0 };
|
||||
|
||||
void _check_if_test_has_finished()
|
||||
void _submit_pkts()
|
||||
{
|
||||
if (_nic_nr_of_acked_pkts > 100 &&
|
||||
_uplink_nr_of_acked_pkts > 100) {
|
||||
for (; _nr_of_sent_pkts < 40; _nr_of_sent_pkts++) {
|
||||
|
||||
log("Finished");
|
||||
}
|
||||
}
|
||||
|
||||
void _reconstruct_uplink()
|
||||
{
|
||||
_uplink.destruct();
|
||||
_uplink.construct(
|
||||
_env, &_uplink_tx_blk_alloc, UPLINK_BUF_SIZE,
|
||||
UPLINK_BUF_SIZE, Net::Mac_address { 2 });
|
||||
|
||||
_uplink->tx_channel()->sigh_ready_to_submit(_uplink_handler);
|
||||
_uplink->tx_channel()->sigh_ack_avail(_uplink_handler);
|
||||
_uplink->rx_channel()->sigh_ready_to_ack(_uplink_handler);
|
||||
_uplink->rx_channel()->sigh_packet_avail(_uplink_handler);
|
||||
}
|
||||
|
||||
void _handle_uplink()
|
||||
{
|
||||
if (!_uplink.constructed()) {
|
||||
return;
|
||||
}
|
||||
if (_uplink->rx()->packet_avail()) {
|
||||
class Uplink_rx_packet_avail { };
|
||||
throw Uplink_rx_packet_avail { };
|
||||
}
|
||||
if (!_uplink->rx()->ack_slots_free()) {
|
||||
class Uplink_no_rx_ack_slots_free { };
|
||||
throw Uplink_no_rx_ack_slots_free { };
|
||||
}
|
||||
while (_uplink->tx()->ack_avail()) {
|
||||
|
||||
Packet_descriptor const pkt { _uplink->tx()->get_acked_packet() };
|
||||
if (pkt.size() != UPLINK_PKT_SIZE) {
|
||||
class Uplink_packet_size_unexpected { };
|
||||
throw Uplink_packet_size_unexpected { };
|
||||
}
|
||||
_uplink->tx()->release_packet(pkt);
|
||||
_uplink_nr_of_sent_pkts--;
|
||||
_uplink_nr_of_acked_pkts++;
|
||||
}
|
||||
_submit_uplink_pkts();
|
||||
_check_if_test_has_finished();
|
||||
}
|
||||
|
||||
void _submit_uplink_pkts()
|
||||
{
|
||||
for (; _uplink_nr_of_sent_pkts < 40; _uplink_nr_of_sent_pkts++) {
|
||||
|
||||
if (!_uplink->tx()->ready_to_submit()) {
|
||||
class Uplink_submit_queue_full { };
|
||||
throw Uplink_submit_queue_full { };
|
||||
if (!_connection.tx()->ready_to_submit()) {
|
||||
class Submit_queue_full { };
|
||||
throw Submit_queue_full { };
|
||||
}
|
||||
Packet_descriptor pkt;
|
||||
try { pkt = _uplink->tx()->alloc_packet(UPLINK_PKT_SIZE); }
|
||||
try { pkt = _connection.tx()->alloc_packet(PKT_SIZE); }
|
||||
catch (...) {
|
||||
class Uplink_packet_alloc_failed { };
|
||||
throw Uplink_packet_alloc_failed { };
|
||||
class Packet_alloc_failed { };
|
||||
throw Packet_alloc_failed { };
|
||||
}
|
||||
_uplink->tx()->submit_packet(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void _handle_nic()
|
||||
{
|
||||
if (_nic.rx()->packet_avail()) {
|
||||
class Nic_rx_packet_avail { };
|
||||
throw Nic_rx_packet_avail { };
|
||||
}
|
||||
if (!_nic.rx()->ack_slots_free()) {
|
||||
class Nic_no_rx_ack_slots_free { };
|
||||
throw Nic_no_rx_ack_slots_free { };
|
||||
}
|
||||
while (_nic.tx()->ack_avail()) {
|
||||
|
||||
Packet_descriptor const pkt { _nic.tx()->get_acked_packet() };
|
||||
if (pkt.size() != NIC_PKT_SIZE) {
|
||||
class Nic_packet_size_unexpected { };
|
||||
throw Nic_packet_size_unexpected { };
|
||||
}
|
||||
_nic.tx()->release_packet(pkt);
|
||||
_nic_nr_of_sent_pkts--;
|
||||
_nic_nr_of_acked_pkts++;
|
||||
}
|
||||
_submit_nic_pkts();
|
||||
_check_if_test_has_finished();
|
||||
}
|
||||
|
||||
void _submit_nic_pkts()
|
||||
{
|
||||
for (; _nic_nr_of_sent_pkts < 40; _nic_nr_of_sent_pkts++) {
|
||||
|
||||
if (!_nic.tx()->ready_to_submit()) {
|
||||
class Nic_submit_queue_full { };
|
||||
throw Nic_submit_queue_full { };
|
||||
}
|
||||
Packet_descriptor pkt;
|
||||
try { pkt = _nic.tx()->alloc_packet(NIC_PKT_SIZE); }
|
||||
catch (...) {
|
||||
class Nic_packet_alloc_failed { };
|
||||
throw Nic_packet_alloc_failed { };
|
||||
}
|
||||
_nic.tx()->submit_packet(pkt);
|
||||
_connection.tx()->submit_packet(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env) : _env { env }
|
||||
Nic_test(Env &env,
|
||||
Allocator &alloc,
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_env { env },
|
||||
_alloc { alloc },
|
||||
_sigh { sigh }
|
||||
{
|
||||
/* test-drive uplink connection */
|
||||
_reconstruct_uplink();
|
||||
_submit_uplink_pkts();
|
||||
_connection.tx_channel()->sigh_ready_to_submit(_sigh);
|
||||
_connection.tx_channel()->sigh_ack_avail(_sigh);
|
||||
_connection.rx_channel()->sigh_ready_to_ack(_sigh);
|
||||
_connection.rx_channel()->sigh_packet_avail(_sigh);
|
||||
|
||||
/* test-drive nic connection */
|
||||
_nic.tx_channel()->sigh_ready_to_submit(_nic_handler);
|
||||
_nic.tx_channel()->sigh_ack_avail(_nic_handler);
|
||||
_nic.rx_channel()->sigh_ready_to_ack(_nic_handler);
|
||||
_nic.rx_channel()->sigh_packet_avail(_nic_handler);
|
||||
if (!_nic.link_state()) {
|
||||
class Nic_link_down { };
|
||||
throw Nic_link_down { };
|
||||
if (!_connection.link_state()) {
|
||||
class Link_down { };
|
||||
throw Link_down { };
|
||||
}
|
||||
if (_nic.mac_address() == Net::Mac_address { }) {
|
||||
class Nic_mac_invalid { };
|
||||
throw Nic_mac_invalid { };
|
||||
if (_connection.mac_address() == Net::Mac_address { }) {
|
||||
class Mac_invalid { };
|
||||
throw Mac_invalid { };
|
||||
}
|
||||
_submit_nic_pkts();
|
||||
_submit_pkts();
|
||||
}
|
||||
|
||||
/* test-drive event connection */
|
||||
_event.with_batch([&] (Event::Session_client::Batch &batch) {
|
||||
void handle_signal()
|
||||
{
|
||||
if (_connection.rx()->packet_avail()) {
|
||||
class Rx_packet_avail { };
|
||||
throw Rx_packet_avail { };
|
||||
}
|
||||
if (!_connection.rx()->ack_slots_free()) {
|
||||
class No_rx_ack_slots_free { };
|
||||
throw No_rx_ack_slots_free { };
|
||||
}
|
||||
while (_connection.tx()->ack_avail()) {
|
||||
|
||||
Packet_descriptor const pkt {
|
||||
_connection.tx()->get_acked_packet() };
|
||||
|
||||
if (pkt.size() != PKT_SIZE) {
|
||||
class Packet_size_unexpected { };
|
||||
throw Packet_size_unexpected { };
|
||||
}
|
||||
_connection.tx()->release_packet(pkt);
|
||||
_nr_of_sent_pkts--;
|
||||
_nr_of_acked_pkts++;
|
||||
}
|
||||
_submit_pkts();
|
||||
}
|
||||
|
||||
bool finished() const
|
||||
{
|
||||
return _nr_of_acked_pkts > 100;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Black_hole_test::Uplink_test
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128,
|
||||
PKT_SIZE = 100,
|
||||
};
|
||||
|
||||
Env &_env;
|
||||
Allocator &_alloc;
|
||||
Signal_context_capability _sigh;
|
||||
Allocator_avl _tx_blk_alloc { &_alloc };
|
||||
Constructible<Uplink::Connection> _connection { };
|
||||
unsigned long _nr_of_sent_pkts { 0 };
|
||||
unsigned long _nr_of_acked_pkts { 0 };
|
||||
|
||||
void _reconstruct_connection()
|
||||
{
|
||||
_connection.destruct();
|
||||
_connection.construct(
|
||||
_env, &_tx_blk_alloc, BUF_SIZE,
|
||||
BUF_SIZE, Net::Mac_address { 2 });
|
||||
|
||||
_connection->tx_channel()->sigh_ready_to_submit(_sigh);
|
||||
_connection->tx_channel()->sigh_ack_avail(_sigh);
|
||||
_connection->rx_channel()->sigh_ready_to_ack(_sigh);
|
||||
_connection->rx_channel()->sigh_packet_avail(_sigh);
|
||||
}
|
||||
|
||||
void _submit_pkts()
|
||||
{
|
||||
for (; _nr_of_sent_pkts < 40; _nr_of_sent_pkts++) {
|
||||
|
||||
if (!_connection->tx()->ready_to_submit()) {
|
||||
class Submit_queue_full { };
|
||||
throw Submit_queue_full { };
|
||||
}
|
||||
Packet_descriptor pkt;
|
||||
try { pkt = _connection->tx()->alloc_packet(PKT_SIZE); }
|
||||
catch (...) {
|
||||
class Packet_alloc_failed { };
|
||||
throw Packet_alloc_failed { };
|
||||
}
|
||||
_connection->tx()->submit_packet(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Uplink_test(Env &env,
|
||||
Allocator &alloc,
|
||||
Signal_context_capability sigh)
|
||||
:
|
||||
_env { env },
|
||||
_alloc { alloc },
|
||||
_sigh { sigh }
|
||||
{
|
||||
_reconstruct_connection();
|
||||
_submit_pkts();
|
||||
}
|
||||
|
||||
void handle_signal()
|
||||
{
|
||||
if (!_connection.constructed()) {
|
||||
return;
|
||||
}
|
||||
if (_connection->rx()->packet_avail()) {
|
||||
class Rx_packet_avail { };
|
||||
throw Rx_packet_avail { };
|
||||
}
|
||||
if (!_connection->rx()->ack_slots_free()) {
|
||||
class No_rx_ack_slots_free { };
|
||||
throw No_rx_ack_slots_free { };
|
||||
}
|
||||
while (_connection->tx()->ack_avail()) {
|
||||
|
||||
Packet_descriptor const pkt {
|
||||
_connection->tx()->get_acked_packet() };
|
||||
|
||||
if (pkt.size() != PKT_SIZE) {
|
||||
class Packet_size_unexpected { };
|
||||
throw Packet_size_unexpected { };
|
||||
}
|
||||
_connection->tx()->release_packet(pkt);
|
||||
_nr_of_sent_pkts--;
|
||||
_nr_of_acked_pkts++;
|
||||
}
|
||||
_submit_pkts();
|
||||
}
|
||||
|
||||
bool finished() const
|
||||
{
|
||||
return _nr_of_acked_pkts > 100;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Black_hole_test::Capture_test
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Capture::Connection _connection { _env };
|
||||
Capture::Area _screen_size { 1, 1 };
|
||||
Capture::Pixel _pixels[1];
|
||||
Surface<Capture::Pixel> _surface { _pixels, _screen_size };
|
||||
Capture::Connection::Screen _screen { _connection, _env.rm(), _screen_size };
|
||||
bool _finished { false };
|
||||
|
||||
public:
|
||||
|
||||
Capture_test(Env &env)
|
||||
:
|
||||
_env { env }
|
||||
{
|
||||
_screen.apply_to_surface(_surface);
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
bool finished() const
|
||||
{
|
||||
return _finished;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Black_hole_test::Event_test
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Event::Connection _connection { _env };
|
||||
bool _finished { false };
|
||||
|
||||
public:
|
||||
|
||||
Event_test(Env &env)
|
||||
:
|
||||
_env { env }
|
||||
{
|
||||
_connection.with_batch([&] (Event::Session_client::Batch &batch) {
|
||||
batch.submit(Input::Press {Input::KEY_1 });
|
||||
batch.submit(Input::Release {Input::KEY_2 });
|
||||
batch.submit(Input::Relative_motion { 3, 4 });
|
||||
});
|
||||
/* test-drive capture connection */
|
||||
_capture_screen.apply_to_surface(_capture_surface);
|
||||
_finished = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
*
|
||||
* Test-driving audio_in and audio_out connection is yet missing.
|
||||
*/
|
||||
bool finished() const
|
||||
{
|
||||
return _finished;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Black_hole_test::Main
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Signal_handler<Main> _signal_handler { _env.ep(), *this, &Main::_handle_signal };
|
||||
Audio_in::Connection _audio_in { _env, "left" };
|
||||
Audio_out::Connection _audio_out { _env, "left" };
|
||||
Nic_test _nic_test { _env, _heap, _signal_handler };
|
||||
Uplink_test _uplink_test { _env, _heap, _signal_handler };
|
||||
Capture_test _capture_test { _env };
|
||||
Event_test _event_test { _env };
|
||||
|
||||
void _handle_signal()
|
||||
{
|
||||
_nic_test.handle_signal();
|
||||
_uplink_test.handle_signal();
|
||||
_check_if_tests_have_finished();
|
||||
}
|
||||
|
||||
void _check_if_tests_have_finished()
|
||||
{
|
||||
if (_nic_test.finished() &&
|
||||
_uplink_test.finished() &&
|
||||
_capture_test.finished() &&
|
||||
_event_test.finished()) {
|
||||
|
||||
log("Finished");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env)
|
||||
:
|
||||
_env { env }
|
||||
{
|
||||
_check_if_tests_have_finished();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Env &env)
|
||||
{
|
||||
static Test::Main main { env };
|
||||
static Black_hole_test::Main main { env };
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user