Files
AnyPS5/core/libs/tests/GuestImeModalDialog.cpp
T
MarcZX10 8cd02e0b20 test(libSceIme): cover the modal dialog session
A guest test drives the session through its exported functions: refusal
without a presenter, with no buttons, with four buttons and with a focus or
cancel button out of range; focus clamping; confirm and cancel; close and
reset; the D-pad, the left stick and the Cross and Circle presses that only
count after the buttons were seen released; and the IME keyboard taking back
the view and the input until it releases them.
2026-10-29 14:06:12 +00:00

137 lines
6.7 KiB
C++

#include "prx/libSceIme/include/ModalDialog.hpp"
#include <cstdio>
#include <cstdlib>
namespace {
constexpr std::uint32_t Left = 0x0080;
constexpr std::uint32_t Right = 0x0020;
constexpr std::uint32_t Circle = 0x2000;
constexpr std::uint32_t Cross = 0x4000;
void Require(bool value, const char* what) {
if (value) return;
std::fprintf(stderr, "FAIL %s\n", what);
std::exit(1);
}
void IgnoreText(ImeHostInputKind, const char16_t*, std::size_t) {}
ModalDialogRequest YesNo(std::size_t focus, std::size_t cancel) {
ModalDialogRequest request;
request.message = u"Overwrite?";
request.buttons = {u"Yes", u"No"};
request.focus = focus;
request.cancel = cancel;
return request;
}
ImeHostPad Pad(std::uint32_t buttons, std::uint8_t leftX = 128) {
ImeHostPad pad;
pad.buttons = buttons;
pad.leftX = leftX;
return pad;
}
std::size_t Chosen(ModalDialogState expected) {
std::size_t chosen = 7;
Require(ModalDialogPoll_nid_postfix(chosen) == expected, "unexpected state");
return chosen;
}
}
int main() {
Require(!ModalDialogHasPresenter_nid_postfix(), "a presenter is registered at start");
Require(!ModalDialogOpen_nid_postfix(YesNo(0, 1)), "opened without a presenter");
Chosen(ModalDialogState::Idle);
Require(!ModalDialogCapturesInput_nid_postfix(), "captures input while idle");
ModalDialogSetPresenter_nid_postfix(true);
Require(ModalDialogHasPresenter_nid_postfix(), "presenter not registered");
ModalDialogRequest none;
Require(!ModalDialogOpen_nid_postfix(none), "opened without buttons");
ModalDialogRequest four = YesNo(0, 1);
four.buttons = {u"a", u"b", u"c", u"d"};
Require(!ModalDialogOpen_nid_postfix(four), "opened with four buttons");
Require(!ModalDialogOpen_nid_postfix(YesNo(2, 1)), "opened with a focus past the buttons");
Require(!ModalDialogOpen_nid_postfix(YesNo(0, 2)), "opened with a cancel button past the buttons");
Chosen(ModalDialogState::Idle);
Require(ModalDialogOpen_nid_postfix(YesNo(0, 1)), "valid request refused");
Require(!ModalDialogOpen_nid_postfix(YesNo(0, 1)), "second open accepted while showing");
Chosen(ModalDialogState::Showing);
Require(ModalDialogCapturesInput_nid_postfix(), "does not capture input while showing");
ModalDialogView view;
Require(ModalDialogReadView_nid_postfix(view), "no view while showing");
Require(view.message == u"Overwrite?" && view.buttons.size() == 2, "view content");
Require(view.buttons[0].selected && !view.buttons[1].selected && view.buttons[1].label == u"No", "view focus");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Previous);
Require(ModalDialogReadView_nid_postfix(view) && view.buttons[0].selected, "focus moved before the first button");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Next);
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Next);
Require(ModalDialogReadView_nid_postfix(view) && view.buttons[1].selected, "focus moved past the last button");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
Require(Chosen(ModalDialogState::Answered) == 1, "confirm did not choose the focused button");
Require(!ModalDialogCapturesInput_nid_postfix(), "captures input once answered");
Require(!ModalDialogReadView_nid_postfix(view), "view after the answer");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Previous);
Require(Chosen(ModalDialogState::Answered) == 1, "an answered dialog changed");
Require(ModalDialogOpen_nid_postfix(YesNo(1, 1)), "reopen refused after an answer");
Chosen(ModalDialogState::Showing);
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Cancel);
Require(Chosen(ModalDialogState::Answered) == 1, "cancel did not choose the cancel button");
ModalDialogRequest noCancel = YesNo(0, ModalDialogNoButton);
Require(ModalDialogOpen_nid_postfix(noCancel), "request without cancel refused");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Cancel);
Chosen(ModalDialogState::Showing);
ModalDialogClose_nid_postfix();
Chosen(ModalDialogState::Closed);
Require(!ModalDialogCapturesInput_nid_postfix(), "captures input once closed");
ModalDialogReset_nid_postfix();
Chosen(ModalDialogState::Idle);
Require(ModalDialogOpen_nid_postfix(YesNo(0, 1)), "reopen refused after a reset");
ModalDialogPublishPad_nid_postfix(Pad(Cross));
Chosen(ModalDialogState::Showing);
ModalDialogPublishPad_nid_postfix(Pad(0));
ModalDialogPublishPad_nid_postfix(Pad(Right));
Require(ModalDialogReadView_nid_postfix(view) && view.buttons[1].selected, "D-pad right did not move the focus");
ModalDialogPublishPad_nid_postfix(Pad(Right));
ModalDialogPublishPad_nid_postfix(Pad(0));
ModalDialogPublishPad_nid_postfix(Pad(0, 20));
Require(ModalDialogReadView_nid_postfix(view) && view.buttons[0].selected, "stick left did not move the focus");
ModalDialogPublishPad_nid_postfix(Pad(0, 128));
ModalDialogPublishPad_nid_postfix(Pad(Left));
Require(ModalDialogReadView_nid_postfix(view) && view.buttons[0].selected, "focus moved before the first button");
ModalDialogPublishPad_nid_postfix(Pad(0));
ModalDialogPublishPad_nid_postfix(Pad(Circle));
Require(Chosen(ModalDialogState::Answered) == 1, "Circle did not cancel");
Require(ModalDialogOpen_nid_postfix(YesNo(0, 1)), "reopen refused");
ModalDialogPublishPad_nid_postfix(Pad(Cross | Circle));
ModalDialogPublishPad_nid_postfix(Pad(Cross | Circle));
Chosen(ModalDialogState::Showing);
ModalDialogPublishPad_nid_postfix(Pad(0));
ModalDialogPublishPad_nid_postfix(Pad(Cross));
Require(Chosen(ModalDialogState::Answered) == 0, "Cross did not confirm the focused button");
Require(ModalDialogOpen_nid_postfix(YesNo(0, 1)), "reopen refused before the IME check");
ImeSetHostTextSink_nid_no_patch(&IgnoreText);
Require(!ModalDialogCapturesInput_nid_postfix(), "captures input while the IME owns the keyboard");
Require(!ModalDialogReadView_nid_postfix(view), "view while the IME owns the keyboard");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
Chosen(ModalDialogState::Showing);
ImeSetHostTextSink_nid_no_patch(nullptr);
Require(ModalDialogCapturesInput_nid_postfix(), "does not resume after the IME releases the keyboard");
Require(ModalDialogReadView_nid_postfix(view), "no view after the IME releases the keyboard");
ModalDialogPublishInput_nid_postfix(ModalDialogInputKind::Confirm);
Require(Chosen(ModalDialogState::Answered) == 0, "confirm after the IME released the keyboard");
ModalDialogSetPresenter_nid_postfix(false);
Require(!ModalDialogOpen_nid_postfix(YesNo(0, 1)), "opened after the presenter went away");
}