ซอร์สที่เผยแพร่
ดาวน์โหลด ZIP ของซอร์ส
CH-J SM Mobile
เรียกดูไดเรกทอรีและไฟล์ของรุ่นแอปพลิเคชันที่ระบุ
CH-J / SM Mobile
175 ไฟล์
sm-mobile-20261016T185235Z-8e93ecc1b59a
วันที่เพิ่ม: · วันที่บิลด์:
1
import 'dart:convert';2
import 'package:flutter/material.dart';3
import 'package:flutter_secure_storage/flutter_secure_storage.dart';4
import 'package:flutter_test/flutter_test.dart';5
import 'package:integration_test/integration_test.dart';6
import 'package:sm_mobile/core/app_controller.dart';7
import 'package:sm_mobile/main.dart';8
import 'package:sm_mobile/models/server_profile.dart';9
import 'package:sm_mobile/services/secure_store.dart';10
import 'package:sm_mobile/ui/terminal_page.dart';12
/// Native window changes on a real device, emulator or simulator.13
///14
/// After connecting to the isolated OpenSSH fixture the test watches the15
/// window for SM_ADAPTIVE_SECONDS. Rotate, fold, unfold, resize or split the16
/// window meanwhile (by hand, or by a script driving the emulator). Every new17
/// window shape must keep the same SSH client and terminal page, and the18
/// server's PTY must report the terminal's new rows and columns.19
void main() {20
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized();21
const seconds = int.fromEnvironment('SM_ADAPTIVE_SECONDS', defaultValue: 90);22
const minShapes = int.fromEnvironment('SM_ADAPTIVE_MIN_SHAPES');23
testWidgets(24
'native resize, rotation and folding keep the SSH session and PTY size',25
(tester) async {26
final namespace = 'sm_adaptive_${newId()}';27
final store = DeviceStore(28
FlutterSecureStorage(29
aOptions: AndroidOptions(30
resetOnError: false,31
storageNamespace: namespace,32
),33
iOptions: IOSOptions(34
accountName: namespace,35
accessibility: KeychainAccessibility.unlocked_this_device,36
),37
),38
);39
final c = AppController(store);40
// Frames are produced by the real engine; waiting must not depend on41
// them, because a hidden window (for example after folding) has none.42
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;43
Future<void> idle(int ms) =>44
Future<void>.delayed(Duration(milliseconds: ms));45
Future<void> until(bool Function() predicate, String what) async {46
for (var i = 0; i < 300 && !predicate(); i++) {47
await idle(100);48
}49
expect(predicate(), true, reason: what);50
}52
final lifecycle = AppLifecycleListener(53
onStateChange: (state) {54
// ignore: avoid_print55
print('ADAPT lifecycle ${state.name}');56
},57
);59
await c.initialize();60
c.locale = const Locale('en');61
// The background lock stays on: if folding or resizing were reported as62
// leaving the app, it would lock, disconnect and fail this test.63
await c.acceptLicense();64
await c.openVault('native adaptive master password', create: true);65
final profile = ServerProfile(66
name: 'Isolated adaptive test',67
host: const String.fromEnvironment(68
'SM_TEST_HOST',69
defaultValue: '127.0.0.1',70
),71
username: const String.fromEnvironment('SM_TEST_USER'),72
port: 22229,73
auth: AuthMethod.privateKey,74
);75
const fingerprint = String.fromEnvironment('SM_TEST_FINGERPRINT');76
await c.ssh.connect(77
profile,78
credential: utf8.decode(79
base64Decode(const String.fromEnvironment('SM_TEST_KEY_B64')),80
),81
passphrase: 'isolated-test-passphrase',82
prompt: (_, _, shown) async => shown == fingerprint,83
);84
expect(c.ssh.error, null);85
expect(c.ssh.connected, true);86
final client = c.ssh.client, terminal = c.ssh.terminal;88
await tester.pumpWidget(SmMobileApp(c));89
await idle(1500);90
await tester.tap(find.text('Terminal').last);91
await idle(1500);92
final page = tester.state(find.byType(TerminalPage));94
String shape() {95
final v = tester.view;96
final s = v.physicalSize / v.devicePixelRatio;97
return '${s.width.toStringAsFixed(1)}x${s.height.toStringAsFixed(1)}dp'98
' @${v.devicePixelRatio}x physical ${v.physicalSize.width.toInt()}'99
'x${v.physicalSize.height.toInt()} features '100
'${v.displayFeatures.map((f) => '${f.type.name}/${f.state.name}').join(',')}';101
}103
final seen = <String>{};104
var probe = 0;105
Future<void> check(String now) async {106
if (!c.vault.unlocked || !c.ssh.connected) {107
// ignore: avoid_print108
print('ADAPT session lost at $now (locked: ${!c.vault.unlocked})');109
}110
expect(tester.takeException(), null, reason: now);111
expect(c.ssh.connected, true, reason: now);112
expect(c.ssh.client, same(client), reason: '$now: no reconnect');113
expect(c.ssh.terminal, same(terminal), reason: now);114
expect(tester.state(find.byType(TerminalPage)), same(page));115
final rows = terminal.viewHeight, cols = terminal.viewWidth;116
final step = probe++;117
terminal.onOutput!(118
"printf 'SZ%s_%s_\\n' $step \"\$(stty size | tr ' ' x)\"\r",119
);120
final expected = 'SZ${step}_${rows}x${cols}_';121
await until(122
() => terminal.buffer.getText().contains(expected),123
'$now: remote PTY ${rows}x$cols',124
);125
// ignore: avoid_print126
print('ADAPT ok $now terminal ${rows}x$cols');127
}129
var last = shape();130
seen.add(last);131
await check(last);132
// ignore: avoid_print133
print('ADAPT ready ${seconds}s');134
final end = DateTime.now().add(const Duration(seconds: seconds));135
while (DateTime.now().isBefore(end)) {136
await idle(250);137
final now = shape();138
if (now == last && c.vault.unlocked) continue;139
// Let the window settle before measuring the new terminal size.140
await idle(800);141
last = shape();142
seen.add(last);143
await check(last);144
}145
// ignore: avoid_print146
print('ADAPT shapes ${seen.length}');147
expect(seen.length, greaterThanOrEqualTo(minShapes));149
lifecycle.dispose();150
await tester.pumpWidget(const SizedBox());151
c.dispose();152
for (final key in ['vault', 'consent', 'preferences']) {153
await store.delete(key);154
}155
},156
timeout: const Timeout(Duration(seconds: seconds + 180)),157
);158
}SHA-256
46f35a640990680071f119f206f02c300c4f0863e9277ab7c69ae4b231a3006cCH-J Proprietary Software License 1.14 · ซอร์สโค้ดนี้ให้ไว้ภายใต้ CH-J Proprietary Software License 1.14 การเปิดให้เข้าถึงไม่ได้เปลี่ยนแปลงเงื่อนไขของสัญญาอนุญาตหรือให้สิทธิ์เพิ่มเติม
SHA-256 ของไฟล์บีบอัด
46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655