diff --git a/test/auto_to_tun_migration_test.dart b/test/auto_to_tun_migration_test.dart new file mode 100644 index 0000000..8f6798c --- /dev/null +++ b/test/auto_to_tun_migration_test.dart @@ -0,0 +1,20 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:revoltvpn/logic/connection_settings.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('legacy Auto connection mode migrates to TUN', () async { + SharedPreferences.setMockInitialValues({ + 'connection_mode': 'auto', + 'app_routing_mode': 'all', + }); + + await ConnectionSettings.initialize(); + + expect(ConnectionSettings.mode, ConnectionMode.tun); + final prefs = await SharedPreferences.getInstance(); + expect(prefs.getString('connection_mode'), ConnectionMode.tun.name); + }); +} diff --git a/test/no_ass_migration_test.dart b/test/no_ass_migration_test.dart new file mode 100644 index 0000000..6f835f1 --- /dev/null +++ b/test/no_ass_migration_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:revoltvpn/logic/connection_settings.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('legacy ASS migrates to SOCKS5 selected-only without losing packages', () async { + SharedPreferences.setMockInitialValues({ + 'connection_mode': 'ass', + 'app_routing_mode': 'selected', + 'app_routing_packages': [ + 'com.android.chrome', + 'com.discord', + ], + }); + + await ConnectionSettings.initialize(); + + expect(ConnectionSettings.mode, ConnectionMode.proxy); + expect(ConnectionSettings.routingMode, AppRoutingMode.selected); + expect( + ConnectionSettings.appPackages, + ['com.android.chrome', 'com.discord'], + ); + }); +} diff --git a/test/secure_socks_session_test.dart b/test/secure_socks_session_test.dart new file mode 100644 index 0000000..8c4ca5b --- /dev/null +++ b/test/secure_socks_session_test.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:revoltvpn/logic/secure_socks_session.dart'; + +void main() { + test('secure SOCKS session replaces unauthenticated proxy inbounds', () async { + const baseConfig = ''' +{ + "inbounds": [ + { + "tag": "legacy-socks", + "listen": "127.0.0.1", + "port": 10807, + "protocol": "socks", + "settings": {"auth": "noauth", "udp": true} + }, + { + "tag": "legacy-http", + "listen": "127.0.0.1", + "port": 10808, + "protocol": "http" + }, + { + "tag": "non-proxy-inbound", + "listen": "127.0.0.1", + "port": 12000, + "protocol": "dokodemo-door" + } + ], + "outbounds": [] +} +'''; + + final first = await SecureSocksSession.create(baseConfig); + final second = await SecureSocksSession.create(baseConfig); + + expect(first.port, greaterThan(1024)); + expect(first.port, lessThanOrEqualTo(65535)); + expect(first.username, matches(RegExp(r'^[0-9a-f]{32}$'))); + expect(first.password, matches(RegExp(r'^[0-9a-f]{64}$'))); + expect(second.username, isNot(first.username)); + expect(second.password, isNot(first.password)); + + final decoded = jsonDecode(first.configJson) as Map; + final inbounds = decoded['inbounds'] as List; + + expect( + inbounds.where((value) => value['protocol'] == 'http'), + isEmpty, + ); + + final socks = inbounds + .cast>() + .singleWhere((value) => value['protocol'] == 'socks'); + expect(socks['tag'], SecureSocksSession.inboundTag); + expect(socks['listen'], '127.0.0.1'); + expect(socks['port'], first.port); + + final settings = socks['settings'] as Map; + expect(settings['auth'], 'password'); + expect(settings['ip'], '127.0.0.1'); + expect(settings.containsKey('accounts'), isFalse); + + final users = settings['users'] as List; + expect(users, hasLength(1)); + expect(users.single['user'], first.username); + expect(users.single['pass'], first.password); + + expect( + inbounds.where((value) => value['protocol'] == 'dokodemo-door'), + hasLength(1), + ); + }); +} diff --git a/test/xray_socks_schema_test.dart b/test/xray_socks_schema_test.dart new file mode 100644 index 0000000..1024fbc --- /dev/null +++ b/test/xray_socks_schema_test.dart @@ -0,0 +1,18 @@ +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('stock runtime patch validates the current SOCKS5 users schema', () { + final source = File( + 'tool/patch_flutter_vless_secure_socks_v2.dart', + ).readAsStringSync(); + + expect(source, contains('settings.optJSONArray("users")')); + expect(source, contains('settings.optString("auth") != "password"')); + expect(source, contains('inbound.optString("listen") != "127.0.0.1"')); + expect(source, contains('account.optString("user").isEmpty()')); + expect(source, contains('account.optString("pass").isEmpty()')); + expect(source, isNot(contains('settings.optJSONArray("accounts")'))); + }); +}