mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
test(libSceImeDialog): cover pasting into a dialog
Insert at the caret, line breaks and controls, the maximum length and surrogate pair boundaries, a clipboard of megabytes, invalid UTF-8, a paste while no dialog captures the keyboard and while a composition is shown.
This commit is contained in:
1 parent
45523d4cfd
commit
cd272d6958
2 files changed
+168
No files matched your search
@@ -32,4 +32,14 @@ if(BUILD_TESTING)
|
||||
set_tests_properties(guest_ime_dialog_composition PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceImeDialog>")
|
||||
endif()
|
||||
|
||||
add_test_executable(guest_ime_dialog_paste_tests ${LIBS_INCLUDE_DIR}/tests/GuestImeDialogPaste.cpp)
|
||||
target_include_directories(guest_ime_dialog_paste_tests PRIVATE ${LIBS_INCLUDE_DIR})
|
||||
target_link_libraries(guest_ime_dialog_paste_tests PRIVATE libSceImeDialog libSceIme libc)
|
||||
configure_windows_unwind(guest_ime_dialog_paste_tests)
|
||||
add_test(NAME guest_ime_dialog_paste COMMAND guest_ime_dialog_paste_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_ime_dialog_paste PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceImeDialog>")
|
||||
endif()
|
||||
endif()
|
||||
@@ -0,0 +1,158 @@
|
||||
#include "prx/libSceImeDialog/include/Api.hpp"
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libSceIme/include/ImeInput.hpp"
|
||||
#include "prx/libSceIme/include/ImeKeyboardView.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int StatusRunning = 1;
|
||||
|
||||
void Require(bool value, const char* message) {
|
||||
if (value) return;
|
||||
std::fprintf(stderr, "%s\n", message);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
void Paste(const std::string& utf8) {
|
||||
ImePublishPaste_nid_postfix(utf8.data(), utf8.size());
|
||||
}
|
||||
|
||||
void Publish(ImeHostInputKind kind, const char* text = "", std::int32_t start = 0, std::int32_t length = 0) {
|
||||
ImeHostInput input{};
|
||||
input.kind = kind;
|
||||
std::strncpy(input.text, text, sizeof(input.text) - 1);
|
||||
input.start = start;
|
||||
input.length = length;
|
||||
ImePublishInput_nid_postfix(input);
|
||||
}
|
||||
|
||||
Param DialogParam(char16_t* buffer, std::uint32_t maxLength) {
|
||||
Param param{};
|
||||
param.max_text_length = maxLength;
|
||||
param.input_text_buffer = buffer;
|
||||
return param;
|
||||
}
|
||||
|
||||
ImeKeyboardView View() {
|
||||
ImeKeyboardView view;
|
||||
Require(ImeReadKeyboardView_nid_postfix(view), "the dialog shows no keyboard");
|
||||
return view;
|
||||
}
|
||||
|
||||
void Open(const Param& param) {
|
||||
Require(sceImeDialogInit(¶m, nullptr) == 0, "init");
|
||||
Require(sceImeDialogGetStatus() == StatusRunning, "not running");
|
||||
}
|
||||
|
||||
void Close() {
|
||||
Require(sceImeDialogTerm() == 0, "term");
|
||||
}
|
||||
|
||||
void CheckInsertAtCaret() {
|
||||
char16_t buffer[16] = u"ab";
|
||||
const Param param = DialogParam(buffer, 8);
|
||||
Open(param);
|
||||
Publish(ImeHostInputKind::Left);
|
||||
Paste("XY");
|
||||
auto view = View();
|
||||
Require(view.text == u"aXYb" && view.caret == 3, "a paste lands at the caret and moves it");
|
||||
Require(std::u16string(buffer) == u"ab", "a paste reached the buffer before the dialog was accepted");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckLineBreaksAndControls() {
|
||||
char16_t buffer[16] = u"";
|
||||
const Param param = DialogParam(buffer, 16);
|
||||
Open(param);
|
||||
Paste(std::string("a\r\nb\nc\td\x01" "e\x7f" "f", 13));
|
||||
Require(View().text == u"abcdef", "line breaks and controls are not removed from a paste");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckMaxLength() {
|
||||
char16_t buffer[16] = u"abc";
|
||||
const Param param = DialogParam(buffer, 5);
|
||||
Open(param);
|
||||
Paste("d\xf0\x9f\x98\x80");
|
||||
Require(View().text == u"abcd", "a paste split a surrogate pair at the limit");
|
||||
Paste("ef");
|
||||
Require(View().text == u"abcde", "a paste went past the maximum length");
|
||||
Paste("g");
|
||||
Require(View().text == u"abcde", "a paste into a full dialog changed it");
|
||||
Close();
|
||||
|
||||
char16_t wide[16] = u"";
|
||||
const Param roomForPair = DialogParam(wide, 4);
|
||||
Open(roomForPair);
|
||||
Paste("x\xf0\x9f\x98\x80\xf0\x9f\x98\x80");
|
||||
Require(View().text == u"x\U0001F600", "a pair that fits is not kept whole");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckHugeClipboard() {
|
||||
char16_t buffer[2049] = u"";
|
||||
const Param param = DialogParam(buffer, 2048);
|
||||
Open(param);
|
||||
const std::string huge(8u * 1024u * 1024u, 'x');
|
||||
Paste(huge);
|
||||
Require(View().text.size() == 2048, "a huge clipboard did not fill the dialog to its limit exactly");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckInvalidUtf8() {
|
||||
char16_t buffer[16] = u"";
|
||||
const Param param = DialogParam(buffer, 16);
|
||||
Open(param);
|
||||
Paste("a\xff" "b\xe3\x81");
|
||||
Require(View().text == u"a\uFFFDb\uFFFD", "an invalid clipboard is not replaced");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckNothingCaptured() {
|
||||
Require(!ImeCapturesKeyboard_nid_postfix(), "something is capturing");
|
||||
Paste("ignored");
|
||||
char16_t buffer[16] = u"";
|
||||
const Param param = DialogParam(buffer, 16);
|
||||
Open(param);
|
||||
Require(View().text.empty(), "a paste before init was kept");
|
||||
Close();
|
||||
Paste("ignored");
|
||||
Open(param);
|
||||
Require(View().text.empty(), "a paste after term was kept");
|
||||
Require(sceImeDialogAbort() == 0, "abort");
|
||||
Paste("ignored");
|
||||
ImeKeyboardView view;
|
||||
Require(!ImeReadKeyboardView_nid_postfix(view), "a finished dialog shows a keyboard");
|
||||
Close();
|
||||
}
|
||||
|
||||
void CheckPasteWhileComposing() {
|
||||
char16_t buffer[16] = u"ab";
|
||||
const Param param = DialogParam(buffer, 16);
|
||||
Open(param);
|
||||
Publish(ImeHostInputKind::Preedit, "ni", 2, 0);
|
||||
Paste("XY");
|
||||
Require(View().text == u"ab", "a paste went in while a composition was shown");
|
||||
Publish(ImeHostInputKind::Preedit, "");
|
||||
Paste("XY");
|
||||
Require(View().text == u"abXY", "a paste does not work once the composition ends");
|
||||
Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
CheckNothingCaptured();
|
||||
CheckInsertAtCaret();
|
||||
CheckLineBreaksAndControls();
|
||||
CheckMaxLength();
|
||||
CheckHugeClipboard();
|
||||
CheckInvalidUtf8();
|
||||
CheckPasteWhileComposing();
|
||||
}
|
||||
Reference in new issue
Block a user