Publish Framework tray enhancements and idle fingerprint retry

This commit is contained in:
ajp_anton
2026-09-20 20:48:34 +00:00
parent 61ef199667
commit ddb912d4ba
25 changed files with 654 additions and 61 deletions
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
import QtQml
import QtTest
import ".."
TestCase {
id: testCase
name: "FingerprintRetry"
property alias authenticator: auth
QtObject {
id: auth
property int authenticatorTypes: 0
property int starts: 0
signal noninteractiveInfo(int kind, QtObject source)
signal noninteractiveError(int kind, QtObject source)
signal failed(int kind, QtObject source)
signal succeeded()
function startAuthenticating() { ++starts; }
}
FedoraToolsFingerprintRetry {
id: retry
auth: testCase.authenticator
fingerprintType: 1
}
function initTestCase() {
compare(retry.interval, 6000);
compare(retry.repeat, false);
}
function init() {
retry.enabled = false;
auth.authenticatorTypes = 0;
auth.starts = 0;
retry.interval = 20;
retry.enabled = true;
}
function beginFingerprint() {
auth.authenticatorTypes = 1;
auth.noninteractiveInfo(1, auth);
}
function test_idleTimeoutRetriesWithoutInput() {
beginFingerprint();
wait(50);
compare(auth.starts, 0); // Never restart a working conversation.
auth.authenticatorTypes = 0;
verify(retry.running);
tryCompare(auth, "starts", 1);
wait(60);
compare(auth.starts, 1); // No polling while the reader stays unavailable.
beginFingerprint();
auth.authenticatorTypes = 0;
tryCompare(auth, "starts", 2); // Later idle timeouts can also recover.
}
function test_noReaderOrNoInstructions() {
wait(60);
compare(auth.starts, 0);
auth.authenticatorTypes = 1;
auth.authenticatorTypes = 0;
wait(60);
compare(auth.starts, 0);
}
function test_failedScansDoNotGetAutomaticNewAttempts() {
beginFingerprint();
auth.noninteractiveError(1, auth);
auth.noninteractiveInfo(1, auth); // Another instruction or timeout message.
auth.failed(1, auth);
auth.authenticatorTypes = 0;
wait(60);
compare(auth.starts, 0);
}
function test_unavailableRetryDoesNotLoop() {
beginFingerprint();
auth.authenticatorTypes = 0;
tryCompare(auth, "starts", 1);
auth.authenticatorTypes = 1; // PAM marks active before opening the reader.
auth.failed(1, auth);
auth.authenticatorTypes = 0;
wait(60);
compare(auth.starts, 1);
}
function test_smartcardDoesNotArmOrCancelFingerprintRetry() {
auth.authenticatorTypes = 2;
auth.noninteractiveInfo(2, auth);
auth.authenticatorTypes = 0;
wait(60);
compare(auth.starts, 0);
beginFingerprint();
auth.noninteractiveError(2, auth);
auth.authenticatorTypes = 2;
tryCompare(auth, "starts", 1);
}
function test_cancelPendingRetry_data() {
return [ {tag: "manual restart"}, {tag: "success"},
{tag: "password failure"}, {tag: "hidden or suspended"} ];
}
function test_cancelPendingRetry(data) {
beginFingerprint();
auth.authenticatorTypes = 0;
verify(retry.running);
switch (data.tag) {
case "manual restart": auth.authenticatorTypes = 1; break;
case "success": auth.succeeded(); break;
case "password failure": auth.failed(0, auth); break;
case "hidden or suspended": retry.enabled = false; break;
}
wait(60);
compare(auth.starts, 0);
}
function test_passwordFailureBeforeAvailabilityChange() {
beginFingerprint();
auth.failed(0, auth);
auth.authenticatorTypes = 0;
wait(60);
compare(auth.starts, 0);
}
}