fb3c278e50
P3 Task 11 (WRITE & COMPILE phase; device run pending MuMu availability). - integration_test/p3_flow_test.dart: login -> album (zh+en) -> category -> invite -> enqueue 3 real JPEGs -> queue completed -> server history (sourceDeviceId) -> ov public API sees 3 -> hide via API + UI sync -> DIO fault-gate offline (waitingNetwork -> retry -> 4 completed) -> password change (session kept) -> relogin -> in-app locale smoke. - integration_test/p3_background_test.dart: IT_PHASE=prepare/verify spec for HOME-background continuation and force-stop kill-restart recovery (2 x ~14MB noise JPEGs give a deterministic mid-flight window). - helpers: dart-define config, fault-injecting DIO adapter, app harness (picker/notification/locale provider overrides), UI step library with live-binding polling (no pumpAndSettle). - scripts/run-mobile-it.sh: device detect (exit 2), backend ensure (compose + api/ov/worker/sync, exit 3), idempotent per-run user seed (no DB reset), APK build/install + adb push of testdata, phase 1 / --background phase 2 orchestration with server-side confirmed-count truth via curl. - services/api seed:it script (create-if-absent staff accounts). - debug-only network security config: cleartext HTTP permitted to 10.0.2.2/127.0.0.1/localhost only (release unaffected). - testdata: 3 x ~120KB + 2 x ~14MB generated JPEGs. Co-Authored-By: Claude Code <noreply@anthropic.com>
51 lines
1.8 KiB
Dart
51 lines
1.8 KiB
Dart
/// 断网场景注入(P3 Task 11,计划偏差登记项)。
|
|
///
|
|
/// 模拟器上断真实网络不便(后端就在宿主 10.0.2.2,断网=断后端不可分区
|
|
/// 观察),按计划改为 **DIO 层故障注入**:包装 App ApiClient 的
|
|
/// HttpClientAdapter,闸门关闭期间所有 cn-api 请求立即以 connectionError
|
|
/// 失败——引擎 initUpload/completeUpload 走该 dio,按 NETWORK_ERROR 分类
|
|
/// 进入 waitingNetwork 退避,恢复后重试成功,即覆盖「断网→等待网络→
|
|
/// 恢复→续传」语义。
|
|
///
|
|
/// 边界(有意,登记为偏差):presign PUT 在 Android 走原生 WorkManager
|
|
/// 桥接(不经 dio),本注入不覆盖该腿;waitingNetwork 判定由 initUpload
|
|
/// 失败驱动,足以驱动状态机目标分支。
|
|
library;
|
|
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:dio/dio.dart';
|
|
|
|
/// 故障闸门:`offline=true` 期间所有经该 adapter 的请求立即失败。
|
|
class FaultGate {
|
|
bool offline = false;
|
|
}
|
|
|
|
/// 包装任意 [HttpClientAdapter] 的故障注入实现。
|
|
class FaultInjectingHttpClientAdapter implements HttpClientAdapter {
|
|
FaultInjectingHttpClientAdapter({required this.gate, required this.inner});
|
|
|
|
final FaultGate gate;
|
|
final HttpClientAdapter inner;
|
|
|
|
@override
|
|
Future<ResponseBody> fetch(
|
|
RequestOptions options,
|
|
Stream<Uint8List>? requestStream,
|
|
Future<void>? cancelFuture,
|
|
) async {
|
|
if (gate.offline) {
|
|
// 与真实断网同型(connectionError → AppException NETWORK_ERROR),
|
|
// 立即抛出避免 10s 连接超时拖慢场景。
|
|
throw DioException.connectionError(
|
|
requestOptions: options,
|
|
reason: 'it fault gate: offline',
|
|
);
|
|
}
|
|
return inner.fetch(options, requestStream, cancelFuture);
|
|
}
|
|
|
|
@override
|
|
void close({bool force = false}) => inner.close(force: force);
|
|
}
|