From 86c11634379ab87238d794f8f9e8bbc991041e4d Mon Sep 17 00:00:00 2001 From: cirakg Date: Tue, 27 Oct 2026 01:08:30 +0100 Subject: fix(import): splitting pasted otpauth:// links runs no character loop OtpAuth.splitUris/firstWord looped over every character in one event, so pasting about 100 links tripped the watchdog (the UI fixture imports Aegis JSON, so it never ran this path). They now use native searches only. New make watchdog case uris_100 (13,576 characters, twice per event) trips on the old code and passes now. fr70: make lint, make test, make watchdog pass. Co-Authored-By: Claude Opus 5.5 --- source/util/StressTest.mc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source/util') diff --git a/source/util/StressTest.mc b/source/util/StressTest.mc index a9d9293..8956c4b 100644 --- a/source/util/StressTest.mc +++ b/source/util/StressTest.mc @@ -130,6 +130,10 @@ module StressTest { // queued (ManageRun), then confirmed (ChangeQueueJob). // * SPACES: an unlocked code entry and a REPLACE of `material` spaces // (refused: "Contents: missing"). + // * URIS: no vault. Setup builds 100 pasted otpauth:// links (about 150 + // characters each) in steps of ten; the measured run is the + // Importer's text work in one event, done twice: OtpAuth.splitUris + // and the detect step's Text.trim + Text.findIgnoreCase. class VaultCase extends Jobs.Job { static const UNLOCK = 0; static const COUNT = 1; @@ -139,6 +143,8 @@ module StressTest { static const LEGACY = 5; static const SECRET = 6; static const SPACES = 7; + static const URIS = 8; + static const LINKS = 100; // Unlocked entries, one queued item each (ChangeQueue.MAX_ITEMS). static const LOCKS = 16; static const PIN = "1234"; @@ -167,6 +173,8 @@ module StressTest { private var _done as Array = [] as Array; // LEGACY: the keys each vault's menu read. private var _keys as Array> = [] as Array>; + // URIS: the pasted text. + private var _text as String = ""; function initialize(label as String, type as Number, pendingCount as Number, materialBytes as Number) { Job.initialize(); @@ -198,6 +206,16 @@ module StressTest { // One bounded setup step; true when every vault is ready. private function setup(budget as Number) as Boolean { + if (kind == URIS) { + var secret = repeat("ABCDEFGH", 4); + for (var i = 0; i < 10; i++) { + var n = (_n + 1).toString(); + _text += "otpauth://totp/Issuer" + n + ":account" + n + "@example.com?secret=" + secret + + "&issuer=Issuer" + n + "&algorithm=SHA1&digits=6&period=30\n"; + _n++; + } + return _n >= LINKS; + } var v = _vaults.size() > 0 ? _vaults[_vaults.size() - 1] : null; if (_phase == 0) { v = new Vault(new RamBackend(), new TimeSource()); @@ -340,6 +358,14 @@ module StressTest { // The measured run. private function measure(budget as Number) as Boolean { + if (kind == URIS) { + for (var i = 0; i < MARGIN; i++) { + var trimmed = Text.trim(_text); + var first = Text.findIgnoreCase(trimmed, OtpAuth.MIGRATION_PREFIX, 0) + Text.findIgnoreCase(trimmed, OtpAuth.PREFIX, 0); + result = " uris=" + OtpAuth.splitUris(trimmed).size() + " chars=" + _text.length() + " first=" + first; + } + return true; + } if (kind == COUNT) { for (var i = 0; i < MARGIN; i++) { ChangeQueue.changed(); @@ -508,6 +534,7 @@ module StressTest { new VaultCase("queue_legacy_4k", VaultCase.LEGACY, 0, Entry.MAX_PAYLOAD_BYTES), new VaultCase("replace_secret_1k", VaultCase.SECRET, 0, 0), new VaultCase("replace_spaces_4k", VaultCase.SPACES, 0, Entry.MAX_PAYLOAD_BYTES), + new VaultCase("uris_100", VaultCase.URIS, 0, 0), // Last, so it stays on the screen: app-diag.sh decodes it. new Item("qr_fit", Codes.QR, new Qr.QrJob(SCREEN_TEXT, 1, largestQrVersion(w, h, round), -1)) ] as Array; -- cgit v1.2.3