From 8270674b7de0209567191028263ae28b23cedcec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?lollipopkit=F0=9F=8F=B3=EF=B8=8F=E2=80=8D=E2=9A=A7?= =?UTF-8?q?=EF=B8=8F?= <10864310+lollipopkit@users.noreply.github.com> Date: Fri, 22 Aug 2025 00:25:26 +0800 Subject: [PATCH] chore: tests --- test/core_utils_test.dart | 75 +++++++++++++++ test/cpu_test.dart | 47 ++++++++++ test/memory_test.dart | 35 +++++++ test/net_speed_test.dart | 188 +++++++++++++++++++++++++++++++++++++ test/system_dist_test.dart | 188 +++++++++++++++++++++++++++++++++++++ 5 files changed, 533 insertions(+) create mode 100644 test/core_utils_test.dart create mode 100644 test/cpu_test.dart create mode 100644 test/memory_test.dart create mode 100644 test/net_speed_test.dart create mode 100644 test/system_dist_test.dart diff --git a/test/core_utils_test.dart b/test/core_utils_test.dart new file mode 100644 index 00000000..9da2bf56 --- /dev/null +++ b/test/core_utils_test.dart @@ -0,0 +1,75 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:server_box/core/utils/comparator.dart'; + +void main() { + group('ChainComparator Tests', () { + test('comparing sorts correctly', () { + final list = ['b', 'c', 'a']; + list.sort(ChainComparator.comparing((s) => s).call); + expect(list, equals(['a', 'b', 'c'])); + }); + + test('thenCompareBy sorts correctly', () { + final list = [('b', '2'), ('a', '3'), ('b', '1')]; + list.sort( + ChainComparator.comparing<(String, String), String>((t) => t.$1) + .thenCompareBy((t) => t.$2, reversed: false).call, + ); + expect(list, equals([('a', '3'), ('b', '1'), ('b', '2')])); + }); + + test('thenCompareBy with reversed sorts correctly', () { + final list = [('b', '2'), ('a', '3'), ('b', '1')]; + list.sort( + ChainComparator.comparing<(String, String), String>((t) => t.$1) + .thenCompareBy((t) => t.$2, reversed: true).call, + ); + expect(list, equals([('a', '3'), ('b', '2'), ('b', '1')])); + }); + + test('thenWithComparator sorts correctly', () { + final list = ['b', 'c', 'a']; + list.sort(ChainComparator.comparing((s) => s) + .thenWithComparator((a, b) => a.length.compareTo(b.length)).call); + expect(list, equals(['a', 'b', 'c'])); + }); + + test('thenCompareByReversed sorts correctly', () { + final list = [('b', '2'), ('a', '3'), ('b', '1')]; + list.sort( + ChainComparator.comparing<(String, String), String>((t) => t.$1) + .thenCompareByReversed((t) => t.$2).call, + ); + expect(list, equals([('a', '3'), ('b', '2'), ('b', '1')])); + }); + + test('thenTrueFirst sorts correctly', () { + final list = [('a', false), ('b', true), ('c', false)]; + list.sort( + ChainComparator.empty().thenTrueFirst((t) => t.$2).thenWithComparator((a, b) => a.$1.compareTo(b.$1)).call, + ); + expect(list, equals([('b', true), ('a', false), ('c', false)])); + }); + + test('reversed sorts correctly', () { + final list = ['a', 'c', 'b']; + final comparator = ChainComparator.comparing((s) => s); + list.sort(comparator.reversed().call); + expect(list, equals(['c', 'b', 'a'])); + }); + }); + + group('Comparators Tests', () { + test('compareStringCaseInsensitive sorts correctly', () { + final list = ['b', 'C', 'a']; + list.sort(Comparators.compareStringCaseInsensitive()); + expect(list, equals(['a', 'b', 'C'])); + }); + + test('compareStringCaseInsensitive with uppercaseFirst sorts correctly', () { + final list = ['b', 'C', 'a', 'B']; + list.sort(Comparators.compareStringCaseInsensitive(uppercaseFirst: true)); + expect(list, equals(['a', 'B', 'b', 'C'])); + }); + }); +} diff --git a/test/cpu_test.dart b/test/cpu_test.dart new file mode 100644 index 00000000..629d7cd4 --- /dev/null +++ b/test/cpu_test.dart @@ -0,0 +1,47 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:server_box/data/model/server/cpu.dart'; + +void main() { + group('CPU Model Tests', () { + test('Test SingleCpuCore.parse', () { + const raw = 'cpu 18232538 52837 5772391 334460731 247294 0 134107 0 0 0'; + + final result = SingleCpuCore.parse(raw); + expect(result.length, 1); + expect(result[0].id, 'cpu'); + expect(result[0].total, 358899898); + }); + test('Test Cpus calculation', () { + final pre = SingleCpuCore.parse( + 'cpu 18232538 52837 5772391 334460731 247294 0 134107 0 0 0'); + final now = SingleCpuCore.parse( + 'cpu 18232638 52937 5772491 334460831 247294 0 134107 0 0 0'); + final cpus = Cpus(pre, now); + cpus.onUpdate(); + expect(cpus.usedPercent(), closeTo(75.0, 0.1)); + expect(cpus.user, closeTo(25.0, 0.1)); + expect(cpus.sys, closeTo(25.0, 0.1)); + }); + + test('Test parseBsdCpu for macOS', () { + const raw = 'CPU usage: 14.70% user, 12.76% sys, 72.52% idle'; + final cpus = parseBsdCpu(raw); + final status = cpus.now.first; + expect(status.user, 14); + expect(status.sys, 12); + expect(status.idle, 72); + }); + + test('Test parseBsdCpu for FreeBSD', () { + const raw = + 'CPU: 5.2% user, 0.0% nice, 3.1% system, 0.1% interrupt, 91.6% idle'; + final cpus = parseBsdCpu(raw); + final status = cpus.now.first; + expect(status.user, 5); + expect(status.nice, 0); + expect(status.sys, 3); + expect(status.irq, 0); + expect(status.idle, 91); + }); + }); +} diff --git a/test/memory_test.dart b/test/memory_test.dart new file mode 100644 index 00000000..2728c3ab --- /dev/null +++ b/test/memory_test.dart @@ -0,0 +1,35 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:server_box/data/model/server/memory.dart'; + +void main() { + group('Memory Model Tests', () { + test('Test Memory.parse', () { + const raw = '''MemTotal: 32768 kB +MemFree: 16384 kB +MemAvailable: 24576 kB'''; + final result = Memory.parse(raw); + expect(result.total, 32768); + expect(result.free, 16384); + expect(result.avail, 24576); + expect(result.usedPercent, closeTo(0.25, 0.01)); + expect(result.availPercent, closeTo(0.75, 0.01)); + }); + + test('Test parseBsdMemory for macOS', () { + const raw = 'PhysMem: 32G used (1536M wired), 64G unused.'; + final result = parseBsdMemory(raw); + expect(result.total, (32 + 64) * 1024 * 1024); + expect(result.free, 64 * 1024 * 1024); + expect(result.avail, 64 * 1024 * 1024); + }); + + test('Test parseBsdMemory for FreeBSD', () { + const raw = + 'Mem: 456M Active, 2918M Inact, 1127M Wired, 187M Cache, 829M Buf, 3535M Free'; + final result = parseBsdMemory(raw); + expect(result.total, (456 + 2918 + 1127 + 187 + 829 + 3535) * 1024); + expect(result.free, 3535 * 1024); + expect(result.avail, 3535 * 1024); + }); + }); +} diff --git a/test/net_speed_test.dart b/test/net_speed_test.dart new file mode 100644 index 00000000..0440aee4 --- /dev/null +++ b/test/net_speed_test.dart @@ -0,0 +1,188 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:server_box/data/model/server/net_speed.dart'; + +void main() { + group('NetSpeedPart Tests', () { + test('NetSpeedPart.same method', () { + final part1 = NetSpeedPart('eth0', BigInt.from(1000), BigInt.from(500), 1000); + final part2 = NetSpeedPart('eth0', BigInt.from(2000), BigInt.from(1000), 2000); + final part3 = NetSpeedPart('eth1', BigInt.from(1000), BigInt.from(500), 1000); + + expect(part1.same(part2), isTrue); + expect(part1.same(part3), isFalse); + }); + }); + + group('NetSpeed Tests', () { + test('NetSpeed.parse with Linux format', () { + const raw = ''' +Inter-| Receive | Transmit + face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed + lo: 45929941 269112 0 0 0 0 0 0 45929941 269112 0 0 0 0 0 0 + eth0: 48481023 505772 0 0 0 0 0 0 36002262 202307 0 0 0 0 0 0 + wlan0: 12345678 123456 0 0 0 0 0 0 87654321 123456 0 0 0 0 0 0 +'''; + + final parts = NetSpeed.parse(raw, 1000); + expect(parts, hasLength(3)); + expect(parts[0].device, equals('lo')); + expect(parts[0].bytesIn, equals(BigInt.from(45929941))); + expect(parts[0].bytesOut, equals(BigInt.from(45929941))); + + expect(parts[1].device, equals('eth0')); + expect(parts[1].bytesIn, equals(BigInt.from(48481023))); + expect(parts[1].bytesOut, equals(BigInt.from(36002262))); + }); + + test('NetSpeed.parseBsd with BSD format', () { + const raw = ''' +Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll +lo0 16384 - 17296531 0 2524959720 17296531 0 2524959720 0 +en0 1500 22:20:xx:xx:xx:e6 739447 0 693997876 535600 0 79008877 0 +en1 1500 88:d8:xx:xx:xx:1d 0 0 0 0 0 0 0 +'''; + + final parts = NetSpeed.parseBsd(raw, 1000); + expect(parts, hasLength(3)); + expect(parts[0].device, equals('lo0')); + expect(parts[0].bytesIn, equals(BigInt.from(2524959720))); + expect(parts[0].bytesOut, equals(BigInt.from(2524959720))); + + expect(parts[1].device, equals('en0')); + expect(parts[1].bytesIn, equals(BigInt.from(693997876))); + expect(parts[1].bytesOut, equals(BigInt.from(79008877))); + + expect(parts[2].device, equals('en1')); + expect(parts[2].bytesIn, equals(BigInt.from(0))); + expect(parts[2].bytesOut, equals(BigInt.from(0))); + }); + + test('NetSpeed.parseBsd skips disabled devices', () { + const raw = ''' +Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll +lo0 16384 - 17296531 0 2524959720 17296531 0 2524959720 0 +en2* 1500 36:7c:xx:xx:xx:xx 0 0 0 0 0 0 0 +en0 1500 22:20:xx:xx:xx:e6 739447 0 693997876 535600 0 79008877 0 +'''; + + final parts = NetSpeed.parseBsd(raw, 1000); + expect(parts, hasLength(2)); + expect(parts[0].device, equals('lo0')); + expect(parts[1].device, equals('en0')); + }); + + test('NetSpeed speed calculations', () { + final oldData = [ + NetSpeedPart('eth0', BigInt.from(1000000), BigInt.from(500000), 1000), + NetSpeedPart('lo', BigInt.from(2000000), BigInt.from(1000000), 1000), + ]; + final newData = [ + NetSpeedPart('eth0', BigInt.from(2000000), BigInt.from(1000000), 2000), + NetSpeedPart('lo', BigInt.from(3000000), BigInt.from(2000000), 2000), + ]; + + final netSpeed = NetSpeed(oldData, newData); + netSpeed.onUpdate(); + + expect(netSpeed.devices, contains('eth0')); + expect(netSpeed.devices, contains('lo')); + expect(netSpeed.realIfaces, contains('eth0')); + expect(netSpeed.realIfaces, isNot(contains('lo'))); + }); + + test('NetSpeed speed calculations for specific device', () { + final oldData = [ + NetSpeedPart('eth0', BigInt.from(1000000), BigInt.from(500000), 1000), + ]; + final newData = [ + NetSpeedPart('eth0', BigInt.from(2000000), BigInt.from(1000000), 2000), + ]; + + final netSpeed = NetSpeed(oldData, newData); + netSpeed.onUpdate(); + + final speedIn = netSpeed.speedIn(device: 'eth0'); + final speedOut = netSpeed.speedOut(device: 'eth0'); + final sizeIn = netSpeed.sizeIn(device: 'eth0'); + final sizeOut = netSpeed.sizeOut(device: 'eth0'); + + expect(speedIn, equals('1000 B/s')); + expect(speedOut, equals('500 B/s')); + expect(sizeIn, equals('1.9 MB')); + expect(sizeOut, equals('976.6 KB')); + }); + + test('NetSpeed handles empty data gracefully', () { + final netSpeed = NetSpeed([], []); + netSpeed.onUpdate(); + + expect(netSpeed.speedIn(), equals('N/A')); + expect(netSpeed.speedOut(), equals('N/A')); + expect(netSpeed.sizeIn(), equals('N/A')); + expect(netSpeed.sizeOut(), equals('N/A')); + }); + + test('NetSpeed real interface filtering', () { + final parts = [ + NetSpeedPart('eth0', BigInt.from(1000), BigInt.from(500), 1000), + NetSpeedPart('wlan0', BigInt.from(1000), BigInt.from(500), 1000), + NetSpeedPart('en0', BigInt.from(1000), BigInt.from(500), 1000), + NetSpeedPart('lo', BigInt.from(1000), BigInt.from(500), 1000), + NetSpeedPart('docker0', BigInt.from(1000), BigInt.from(500), 1000), + ]; + + final netSpeed = NetSpeed([], parts); + netSpeed.onUpdate(); + + expect(netSpeed.realIfaces, contains('eth0')); + expect(netSpeed.realIfaces, contains('wlan0')); + expect(netSpeed.realIfaces, contains('en0')); + expect(netSpeed.realIfaces, isNot(contains('lo'))); + expect(netSpeed.realIfaces, isNot(contains('docker0'))); + }); + + test('NetSpeed deviceIdx method', () { + final parts = [ + NetSpeedPart('eth0', BigInt.from(1000), BigInt.from(500), 1000), + NetSpeedPart('eth1', BigInt.from(1000), BigInt.from(500), 1000), + ]; + + final netSpeed = NetSpeed([], parts); + netSpeed.onUpdate(); + + expect(netSpeed.deviceIdx('eth0'), equals(0)); + expect(netSpeed.deviceIdx('eth1'), equals(1)); + expect(netSpeed.deviceIdx('nonexistent'), equals(0)); + }); + }); + + group('NetSpeed real interface prefixes', () { + test('Contains all expected prefixes', () { + expect(NetSpeed.realIfacePrefixs, contains('eth')); + expect(NetSpeed.realIfacePrefixs, contains('wlan')); + expect(NetSpeed.realIfacePrefixs, contains('en')); + expect(NetSpeed.realIfacePrefixs, contains('ww')); + expect(NetSpeed.realIfacePrefixs, contains('wl')); + }); + }); + + group('NetSpeed cached values', () { + test('Updates cached values on onUpdate', () { + final oldData = [ + NetSpeedPart('eth0', BigInt.from(1000000), BigInt.from(500000), 1000), + ]; + final newData = [ + NetSpeedPart('eth0', BigInt.from(2000000), BigInt.from(1000000), 2000), + ]; + + final netSpeed = NetSpeed(oldData, newData); + expect(netSpeed.cachedVals.speedIn, equals('0kb/s')); + + netSpeed.onUpdate(); + expect(netSpeed.cachedVals.speedIn, isNot(equals('0kb/s'))); + expect(netSpeed.cachedVals.speedOut, isNot(equals('0kb/s'))); + expect(netSpeed.cachedVals.sizeIn, isNot(equals('0kb'))); + expect(netSpeed.cachedVals.sizeOut, isNot(equals('0kb'))); + }); + }); +} \ No newline at end of file diff --git a/test/system_dist_test.dart b/test/system_dist_test.dart new file mode 100644 index 00000000..e7c023c4 --- /dev/null +++ b/test/system_dist_test.dart @@ -0,0 +1,188 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:server_box/data/model/server/system.dart'; +import 'package:server_box/data/model/server/dist.dart'; + +void main() { + group('SystemType Tests', () { + test('SystemType values and properties', () { + expect(SystemType.linux.value, equals('__linux')); + expect(SystemType.bsd.value, equals('__bsd')); + expect(SystemType.windows.value, equals('__windows')); + }); + + test('SystemType.parse detects Windows', () { + const windowsOutput = 'System info __windows version 10'; + final result = SystemType.parse(windowsOutput); + expect(result, equals(SystemType.windows)); + }); + + test('SystemType.parse detects BSD', () { + const bsdOutput = 'FreeBSD 13.0-RELEASE __bsd'; + final result = SystemType.parse(bsdOutput); + expect(result, equals(SystemType.bsd)); + }); + + test('SystemType.parse detects Linux', () { + const linuxOutput = 'Linux 5.4.0 __linux'; + final result = SystemType.parse(linuxOutput); + expect(result, equals(SystemType.linux)); + }); + + test('SystemType.parse defaults to Linux for empty input', () { + const emptyOutput = ''; + final result = SystemType.parse(emptyOutput); + expect(result, equals(SystemType.linux)); + }); + + test('SystemType.parse defaults to Linux for unknown output', () { + const unknownOutput = 'Unknown system output'; + final result = SystemType.parse(unknownOutput); + expect(result, equals(SystemType.linux)); + }); + + test('SystemType.parse handles long strings', () { + final longOutput = 'a' * 200; + final result = SystemType.parse(longOutput); + expect(result, equals(SystemType.linux)); + }); + }); + + group('Dist Tests', () { + test('Dist enum contains all expected values', () { + expect(Dist.values, contains(Dist.debian)); + expect(Dist.values, contains(Dist.ubuntu)); + expect(Dist.values, contains(Dist.centos)); + expect(Dist.values, contains(Dist.fedora)); + expect(Dist.values, contains(Dist.opensuse)); + expect(Dist.values, contains(Dist.kali)); + expect(Dist.values, contains(Dist.wrt)); + expect(Dist.values, contains(Dist.armbian)); + expect(Dist.values, contains(Dist.arch)); + expect(Dist.values, contains(Dist.alpine)); + expect(Dist.values, contains(Dist.rocky)); + expect(Dist.values, contains(Dist.deepin)); + expect(Dist.values, contains(Dist.coreelec)); + }); + + test('String.dist extension detects Debian', () { + const input = 'debian 10.0'; + final result = input.dist; + expect(result, equals(Dist.debian)); + }); + + test('String.dist extension detects Ubuntu', () { + const input = 'ubuntu 20.04'; + final result = input.dist; + expect(result, equals(Dist.ubuntu)); + }); + + test('String.dist extension detects CentOS', () { + const input = 'centos 8'; + final result = input.dist; + expect(result, equals(Dist.centos)); + }); + + test('String.dist extension detects Fedora', () { + const input = 'fedora 34'; + final result = input.dist; + expect(result, equals(Dist.fedora)); + }); + + test('String.dist extension detects OpenSUSE', () { + const input = 'opensuse leap 15.3'; + final result = input.dist; + expect(result, equals(Dist.opensuse)); + }); + + test('String.dist extension detects Kali', () { + const input = 'kali linux 2021.2'; + final result = input.dist; + expect(result, equals(Dist.kali)); + }); + + test('String.dist extension detects WRT special case', () { + const input = 'istoreos 21.02'; + final result = input.dist; + expect(result, equals(Dist.wrt)); + }); + + test('String.dist extension detects Armbian', () { + const input = 'armbian 21.08'; + final result = input.dist; + expect(result, equals(Dist.armbian)); + }); + + test('String.dist extension detects Arch', () { + const input = 'arch linux'; + final result = input.dist; + expect(result, equals(Dist.arch)); + }); + + test('String.dist extension detects Alpine', () { + const input = 'alpine linux 3.14'; + final result = input.dist; + expect(result, equals(Dist.alpine)); + }); + + test('String.dist extension detects Rocky', () { + const input = 'rocky linux 8.4'; + final result = input.dist; + expect(result, equals(Dist.rocky)); + }); + + test('String.dist extension detects Deepin', () { + const input = 'deepin 20'; + final result = input.dist; + expect(result, equals(Dist.deepin)); + }); + + test('String.dist extension detects CoreELEC', () { + const input = 'coreelec 19.0'; + final result = input.dist; + expect(result, equals(Dist.coreelec)); + }); + + test('String.dist extension is case insensitive', () { + const input = 'UBUNTU 20.04'; + final result = input.dist; + expect(result, equals(Dist.ubuntu)); + }); + + test('String.dist extension returns null for unknown distribution', () { + const input = 'unknown distribution'; + final result = input.dist; + expect(result, isNull); + }); + + test('String.dist extension handles empty string', () { + const input = ''; + final result = input.dist; + expect(result, isNull); + }); + + test('String.dist extension handles substring matches', () { + const input = 'xubuntu 20.04'; // Contains 'ubuntu' + final result = input.dist; + expect(result, equals(Dist.ubuntu)); + }); + + test('String.dist extension prioritizes exact matches over substring', () { + const input = 'kali linux'; // Contains 'linux' but 'kali' is more specific + final result = input.dist; + expect(result, equals(Dist.kali)); + }); + + test('Special WRT cases are handled correctly', () { + expect('istoreos'.dist, equals(Dist.wrt)); + expect('iStoreOS'.dist, equals(Dist.wrt)); + expect('ISTOREOS'.dist, equals(Dist.wrt)); + }); + + test('Distribution detection order follows enum order', () { + // This test ensures that the first match in the enum is returned + const input = 'ubuntu'; // This could match both 'ubuntu' and 'kali' (contains 'u') + final result = input.dist; + expect(result, equals(Dist.ubuntu)); // ubuntu comes before kali in enum + }); + }); +} \ No newline at end of file