mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-05-06 09:13:48 +08:00

- Add support for SIGTSTP: https://github.com/ArthurSonzogni/FTXUI/issues/330 This - Add support for task posting. This allows folks to defer function execution, and execute it directly below the main loop. The task are executed in a FIFO order.
238 lines
6.8 KiB
C++
238 lines
6.8 KiB
C++
#include <gtest/gtest-message.h> // for Message
|
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
|
#include <algorithm> // for max
|
|
#include <memory> // for unique_ptr, allocator
|
|
#include <variant> // for get
|
|
|
|
#include "ftxui/component/event.hpp" // for Event, Event::Escape
|
|
#include "ftxui/component/receiver.hpp" // for MakeReceiver, ReceiverImpl
|
|
#include "ftxui/component/terminal_input_parser.hpp"
|
|
#include "gtest/gtest_pred_impl.h" // for AssertionResult, Test, EXPECT_EQ, EXPECT_TRUE, EXPECT_FALSE, TEST
|
|
|
|
using namespace ftxui;
|
|
|
|
// Test char |c| to are trivially converted into |Event::Character(c)|.
|
|
TEST(Event, Character) {
|
|
std::vector<char> basic_char;
|
|
for (char c = 'a'; c <= 'z'; ++c)
|
|
basic_char.push_back(c);
|
|
for (char c = 'A'; c <= 'Z'; ++c)
|
|
basic_char.push_back(c);
|
|
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
for (char c : basic_char)
|
|
parser.Add(c);
|
|
}
|
|
|
|
Task received;
|
|
for (char c : basic_char) {
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_TRUE(std::get<Event>(received).is_character());
|
|
EXPECT_EQ(c, std::get<Event>(received).character()[0]);
|
|
}
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, EscapeKeyWithoutWaiting) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, EscapeKeyNotEnoughWait) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
parser.Timeout(49);
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, EscapeKeyEnoughWait) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
parser.Timeout(50);
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_EQ(std::get<Event>(received), Event::Escape);
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, MouseLeftClick) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
parser.Add('[');
|
|
parser.Add('3');
|
|
parser.Add('2');
|
|
parser.Add(';');
|
|
parser.Add('1');
|
|
parser.Add('2');
|
|
parser.Add(';');
|
|
parser.Add('4');
|
|
parser.Add('2');
|
|
parser.Add('M');
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
|
EXPECT_EQ(Mouse::Left, std::get<Event>(received).mouse().button);
|
|
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
|
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, MouseMiddleClick) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
parser.Add('[');
|
|
parser.Add('3');
|
|
parser.Add('3');
|
|
parser.Add(';');
|
|
parser.Add('1');
|
|
parser.Add('2');
|
|
parser.Add(';');
|
|
parser.Add('4');
|
|
parser.Add('2');
|
|
parser.Add('M');
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
|
EXPECT_EQ(Mouse::Middle, std::get<Event>(received).mouse().button);
|
|
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
|
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, MouseRightClick) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
parser.Add('\x1B');
|
|
parser.Add('[');
|
|
parser.Add('3');
|
|
parser.Add('4');
|
|
parser.Add(';');
|
|
parser.Add('1');
|
|
parser.Add('2');
|
|
parser.Add(';');
|
|
parser.Add('4');
|
|
parser.Add('2');
|
|
parser.Add('M');
|
|
}
|
|
|
|
Task received;
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_TRUE(std::get<Event>(received).is_mouse());
|
|
EXPECT_EQ(Mouse::Right, std::get<Event>(received).mouse().button);
|
|
EXPECT_EQ(12, std::get<Event>(received).mouse().x);
|
|
EXPECT_EQ(42, std::get<Event>(received).mouse().y);
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
|
|
TEST(Event, UTF8) {
|
|
struct {
|
|
std::vector<unsigned char> input;
|
|
bool valid;
|
|
} kTestCase[] = {
|
|
// Basic characters.
|
|
{{'a'}, true},
|
|
{{'z'}, true},
|
|
{{'A'}, true},
|
|
{{'Z'}, true},
|
|
{{'0'}, true},
|
|
{{'9'}, true},
|
|
|
|
// UTF-8 of various size:
|
|
{{0b0100'0001}, true},
|
|
{{0b1100'0010, 0b1000'0000}, true},
|
|
{{0b1110'0010, 0b1000'0000, 0b1000'0000}, true},
|
|
{{0b1111'0010, 0b1000'0000, 0b1000'0000, 0b1000'0000}, true},
|
|
|
|
// Overlong UTF-8 encoding:
|
|
{{0b1100'0000, 0b1000'0000}, false},
|
|
{{0b1110'0000, 0b1000'0000, 0b1000'0000}, false},
|
|
{{0b1111'0000, 0b1000'0000, 0b1000'0000, 0b1000'0000}, false},
|
|
|
|
// Test limits in between the various legal regions
|
|
// https://unicode.org/versions/corrigendum1.html
|
|
// Limit in between the valid and ina
|
|
// {{0x7F}, true}, => Special sequence.
|
|
{{0x80}, false},
|
|
// ---
|
|
{{0xC1, 0x80}, false},
|
|
{{0xC2, 0x7F}, false},
|
|
{{0xC2, 0x80}, true},
|
|
// ---
|
|
{{0xDF, 0xBF}, true},
|
|
{{0xDF, 0xC0}, false},
|
|
// ---
|
|
{{0xE0, 0x9F, 0x80}, false},
|
|
{{0xE0, 0xA0, 0x7F}, false},
|
|
{{0xE0, 0xA0, 0x80}, true},
|
|
// ---
|
|
{{0xE0, 0xBF, 0xBF}, true},
|
|
// ---
|
|
{{0xE1, 0x7F, 0x80}, false},
|
|
{{0xE1, 0x80, 0x7f}, false},
|
|
{{0xE1, 0x80, 0x80}, true},
|
|
// --
|
|
{{0xEF, 0xBF, 0xBF}, true},
|
|
{{0xEF, 0xC0, 0xBF}, false},
|
|
{{0xEF, 0xBF, 0xC0}, false},
|
|
// --
|
|
{{0xF0, 0x90, 0x80}, false},
|
|
{{0xF0, 0x8F, 0x80, 0x80}, false},
|
|
{{0xF0, 0x90, 0x80, 0x7F}, false},
|
|
{{0xF0, 0x90, 0x80, 0x80}, true},
|
|
// --
|
|
{{0xF1, 0x80, 0x80, 0x80}, true},
|
|
// --
|
|
{{0xF1, 0xBF, 0xBF, 0xBF}, true},
|
|
// --
|
|
{{0xF2, 0x80, 0x80, 0x80}, true},
|
|
// --
|
|
{{0xF4, 0x8F, 0xBF, 0xBF}, true},
|
|
{{0xF4, 0x90, 0xBF, 0xBF}, false},
|
|
|
|
};
|
|
for (auto test : kTestCase) {
|
|
auto event_receiver = MakeReceiver<Task>();
|
|
{
|
|
auto parser = TerminalInputParser(event_receiver->MakeSender());
|
|
for (auto input : test.input)
|
|
parser.Add(input);
|
|
}
|
|
Task received;
|
|
if (test.valid) {
|
|
EXPECT_TRUE(event_receiver->Receive(&received));
|
|
EXPECT_TRUE(std::get<Event>(received).is_character());
|
|
}
|
|
EXPECT_FALSE(event_receiver->Receive(&received));
|
|
}
|
|
}
|
|
|
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
|
// Use of this source code is governed by the MIT license that can be found in
|
|
// the LICENSE file.
|