fix: read back sent copies after the sec 5.6 upstream fix, pinned at 2d65d66

This commit is contained in:
randogoth 2026-09-28 23:49:39 +03:00
parent 52947e153d
commit d6f4c434fa
36 changed files with 4223 additions and 3118 deletions

View file

@ -4,6 +4,8 @@
// router flow itself.
import "dart:io";
import "dart:math";
import "dart:typed_data";
import "package:flutter/material.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
@ -12,11 +14,17 @@ import "package:hive_flutter/hive_flutter.dart";
import "package:smol_mail/data/providers/providers.dart";
import "package:smol_mail/presentation/app_widget.dart";
import "package:smol_mail/smol/address.dart";
import "package:smol_mail/smol/client.dart";
import "package:smol_mail/smol/crypto.dart";
import "package:smol_mail/smol/errors.dart";
import "package:smol_mail/smol/proto.dart";
import "package:smol_mail/smol/store.dart";
import "package:smol_mail/smol/ui.dart";
Uint8List randomBytes(int n) => Uint8List.fromList(List.generate(n, (_) => Random.secure().nextInt(256)));
// A syntactically valid server key for the stubbed pin step: the flow under
// test is the UI routing, not the handshake.
const fakePin = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
/// A [SmolClient] whose network operations complete instantly, so the test
/// exercises the flow rather than the network. [restoreAndRecall] still
@ -32,14 +40,14 @@ class StubClient extends SmolClient {
throw SmolError("no pinned key for ${addr.host}");
}
store.restoreMaster(unhex(masterHex.trim()), 0);
store.setAccount(addr);
store.native.setAccount(addr.short);
return addr;
}
@override
Future<SmolAddress> recallAccount(String addressText) async {
final addr = parseAddress(addressText);
store.setAccount(addr);
store.native.setAccount(addr.short);
return addr;
}
}
@ -53,11 +61,11 @@ void main() {
final dir = await Directory.systemTemp.createTemp("smol-recall-flow");
Hive.init(dir.path);
storeA = await SmolStore.open(
stateBox: "recall-a-state", mailBox: "recall-a-mail");
dbPath: "${dir.path}/a.db", stateBox: "recall-a-state", readBox: "recall-a-read");
storeB = await SmolStore.open(
stateBox: "recall-b-state", mailBox: "recall-b-mail");
dbPath: "${dir.path}/b.db", stateBox: "recall-b-state", readBox: "recall-b-read");
storeC = await SmolStore.open(
stateBox: "recall-c-state", mailBox: "recall-c-mail");
dbPath: "${dir.path}/c.db", stateBox: "recall-c-state", readBox: "recall-c-read");
});
Widget app(SmolStore store) => ProviderScope(
@ -99,13 +107,14 @@ void main() {
expect(find.text("Register a new address instead"), findsNothing);
fields = find.byType(TextField);
expect(fields, findsNWidgets(2)); // address (carried over), server key
await tester.enterText(fields.at(1), b32encode(randomBytes(32)));
await tester.enterText(fields.at(1), fakePin);
await tester.tap(find.text("Pin and Recall"));
await tester.pumpAndSettle();
expect(find.text("Inbox"), findsOneWidget);
expect(store.master(), master);
expect(store.account()!.user, "randogoth");
expect(parseAddress(SmolClient(store).accountAddress()!.short).user,
"randogoth");
});
testWidgets("restore requires an address before it will submit",
@ -141,7 +150,7 @@ void main() {
await tester.tap(find.text("Create Identity"));
await tester.pumpAndSettle();
expect(store.master(), isNotNull);
expect(store.account(), isNull);
expect(SmolClient(store).accountAddress(), isNull);
// Simulate returning to onboarding later (e.g. a cold restart). Pumping
// app(store) directly would just rebuild the existing OnboardingScreen
@ -164,7 +173,7 @@ void main() {
// Lands on the recall-framed register step (no pin yet); pin it and finish.
expect(find.byType(TextField), findsNWidgets(2));
await tester.enterText(find.byType(TextField).at(1), b32encode(randomBytes(32)));
await tester.enterText(find.byType(TextField).at(1), fakePin);
await tester.tap(find.text("Pin and Recall"));
await tester.pumpAndSettle();