CH-J SM Mobilepengurusan pelayan melalui SSH
Menu
Sumber yang diterbitkan

CH-J SM Mobile

Layari direktori dan fail untuk keluaran aplikasi tertentu.

Muat turun ZIP sumber
CH-J / SM Mobile 175 fail
sm-mobile-20261016T185235Z-8e93ecc1b59a Ditambah: · Dibina:
codec_test.dart Ditambah: Tarikh tidak direkodkan 8.1 KB · 232 baris
Kod Muat turun fail
1import 'dart:convert';
2import 'dart:typed_data';
3import 'package:flutter_test/flutter_test.dart';
4import 'package:sm_mobile/services/editor/languages.dart';
5import 'package:sm_mobile/services/editor/text_codec.dart';
6import 'package:sm_mobile/services/editor/validation.dart';
8Uint8List b(List<int> v) => Uint8List.fromList(v);
10/// Decodes, then encodes the same text with the detected settings: the
11/// bytes must come back unchanged.
12void roundTrip(Uint8List bytes, TextEncoding expected, {LineBreak? lineBreak}) {
13 final d = decodeDocument(bytes);
14 expect(d.encoding, expected);
15 expect(d.exact, true);
16 if (lineBreak != null) expect(d.lineBreaks.dominant, lineBreak);
17 final again = encodeText(
18 withLineBreaks(d.text, d.lineBreaks.dominant),
19 d.encoding,
20 );
21 expect(again, bytes);
24void main() {
25 group('encodings are preserved byte for byte', () {
26 const text = 'Příliš žluťoučký kůň úpěl ďábelské ódy – €\n';
27 test('UTF-8 with and without BOM', () {
28 roundTrip(b(utf8.encode(text)), TextEncoding.utf8);
29 roundTrip(
30 b([0xef, 0xbb, 0xbf, ...utf8.encode(text)]),
31 TextEncoding.utf8Bom,
32 );
33 });
34 test('UTF-16 LE/BE with BOM and LE without BOM', () {
35 for (final e in [TextEncoding.utf16le, TextEncoding.utf16be]) {
36 roundTrip(encodeText('A😀$text', e), e);
37 }
38 final noBom = encodeText(
39 'plain ascii text\n',
40 TextEncoding.utf16le,
41 ).sublist(2);
42 expect(detectEncoding(noBom), TextEncoding.utf16le);
43 });
44 test('legacy 8-bit text is never guessed silently', () {
45 final cp1250 = encodeText(text, TextEncoding.windows1250);
46 expect(detectEncoding(cp1250), isNull);
47 expect(() => decodeDocument(cp1250), throwsA(isA<UnknownEncoding>()));
48 final d = decodeDocument(cp1250, encoding: TextEncoding.windows1250);
49 expect(d.text, text);
50 expect(encodeText(d.text, TextEncoding.windows1250), cp1250);
51 final iso = encodeText('Žluťoučký\n', TextEncoding.iso88592);
52 expect(
53 decodeDocument(iso, encoding: TextEncoding.iso88592).text,
54 'Žluťoučký\n',
55 );
56 expect(decodeText(b([0xe9]), TextEncoding.latin1), 'é');
57 });
58 test('undefined bytes and unrepresentable characters are reported', () {
59 expect(
60 () => decodeText(b([0x81]), TextEncoding.windows1252),
61 throwsFormatException,
62 );
63 expect(
64 () => encodeText('日本', TextEncoding.windows1250),
65 throwsA(isA<UnencodableText>().having((u) => u.count, 'count', 2)),
66 );
67 expect(
68 () => decodeText(b([0xc3]), TextEncoding.utf8),
69 throwsFormatException,
70 );
71 });
72 });
74 group('line endings and final newline', () {
75 test('LF, CRLF and CR are kept; final newline presence is kept', () {
76 roundTrip(
77 b(utf8.encode('a\nb\n')),
78 TextEncoding.utf8,
79 lineBreak: LineBreak.lf,
80 );
81 roundTrip(
82 b(utf8.encode('a\r\nb\r\n')),
83 TextEncoding.utf8,
84 lineBreak: LineBreak.crlf,
85 );
86 roundTrip(
87 b(utf8.encode('a\rb\r')),
88 TextEncoding.utf8,
89 lineBreak: LineBreak.cr,
90 );
91 roundTrip(b(utf8.encode('a\nb')), TextEncoding.utf8);
92 expect(decodeDocument(b(utf8.encode('a\nb'))).finalNewline, false);
93 expect(decodeDocument(b(utf8.encode('a\nb\n'))).finalNewline, true);
94 });
95 test('mixed endings are detected and not reported as exact', () {
96 final d = decodeDocument(b(utf8.encode('a\r\nb\nc\r\n')));
97 expect(d.lineBreaks.mixed, true);
98 expect(d.lineBreaks.dominant, LineBreak.crlf);
99 expect(d.exact, false);
100 });
101 });
103 test('binary data is recognised, UTF-16 text is not binary', () {
104 expect(looksBinary(b([0x89, 0x50, 0x4e, 0x47, 0, 0, 0, 0x0d])), true);
105 expect(looksBinary(b(utf8.encode('server {\n listen 80;\n}\n'))), false);
106 expect(looksBinary(encodeText('hello world', TextEncoding.utf16le)), false);
107 });
109 group('syntax detection', () {
110 final cases = {
111 'index.html': 'HTML',
112 'page.xhtml': 'HTML',
113 'index.php': 'PHP',
114 'style.scss': 'SCSS',
115 'style.sass': 'Sass (indented)',
116 'app.mjs': 'JavaScript',
117 'App.tsx': 'TypeScript',
118 'data.jsonl': 'JSON Lines',
119 'schema.xsd': 'XML',
120 'compose.yml': 'YAML',
121 'README.md': 'Markdown',
122 'main.py': 'Python',
123 'main.dart': 'Dart',
124 'Main.kt': 'Kotlin',
125 'lib.rs': 'Rust',
126 'main.go': 'Go',
127 'x.hpp': 'C++',
128 'P.cs': 'C#',
129 'a.rb': 'Ruby',
130 'a.pm': 'Perl',
131 'a.lua': 'Lua',
132 'a.psm1': 'PowerShell',
133 'a.zsh': 'Shell (Bash/sh/zsh)',
134 'a.fish': 'fish',
135 'q.sql': 'SQL',
136 's.gql': 'GraphQL',
137 'app.toml': 'TOML',
138 'nginx.service': 'systemd unit',
139 'app.desktop': 'systemd unit',
140 'Info.plist': 'Property list (XML)',
141 '.htaccess': 'Apache config',
142 '.gitignore': 'Unix config',
143 '.editorconfig': 'INI / config',
144 '.env': '.env',
145 '.env.production': '.env',
146 'Dockerfile': 'Dockerfile',
147 'Dockerfile.dev': 'Dockerfile',
148 'Makefile': 'Makefile',
149 'CMakeLists.txt': 'CMake',
150 'nginx.conf': 'NGINX',
151 '/etc/nginx/sites-available/site.conf': 'NGINX',
152 'httpd.conf': 'Apache config',
153 'sshd_config': 'SSH config',
154 '/home/u/.ssh/config': 'SSH config',
155 'hosts': 'Unix config',
156 'fstab': 'Unix config',
157 'crontab': 'Unix config',
158 '.bashrc': 'Shell (Bash/sh/zsh)',
159 'x.patch': 'Diff / patch',
160 'main.tf': 'Terraform (HCL)',
161 'build.gradle': 'Gradle',
162 'a.proto': 'Protocol Buffers',
163 'run.bat': 'Batch (cmd)',
164 'server.pem': 'PEM / key / certificate',
165 'notes.txt': 'Text',
166 'app.log': 'Log',
167 'table.tsv': 'CSV / TSV',
168 };
169 test('by name, extension and path', () {
170 cases.forEach((name, label) {
171 expect(detectSyntax(name).label, label, reason: name);
172 });
173 });
174 test('files without extension: shebang and content', () {
175 expect(
176 detectSyntax('deploy', content: '#!/usr/bin/env bash\n').id,
177 'bash',
178 );
179 expect(
180 detectSyntax('tool', content: '#!/usr/bin/python3\n').id,
181 'python',
182 );
183 expect(
184 detectSyntax('unit', content: '[Unit]\nDescription=x\n').id,
185 'systemd',
186 );
187 expect(detectSyntax('page', content: '<!DOCTYPE html><html>').id, 'html');
188 expect(detectSyntax('README').id, 'text');
189 });
190 test('every highlighted syntax has a bundled grammar', () {
191 for (final s in syntaxes) {
192 if (s.grammar != null) {
193 expect(grammars[s.grammar], isNotNull, reason: s.id);
194 }
195 }
196 });
197 test('viewer kinds', () {
198 expect(fileKind('a.HEIC'), FileKind.image);
199 expect(fileKind('a.svg'), FileKind.svg);
200 expect(fileKind('a.docx'), FileKind.office);
201 expect(fileKind('a.tar.gz'), FileKind.archive);
202 expect(fileKind('a.ipynb'), FileKind.notebook);
203 expect(fileKind('a.crt'), FileKind.certificate);
204 expect(fileKind('a.mp4'), FileKind.video);
205 expect(fileKind('blob', head: b([0x25, 0x50, 0x44, 0x46])), FileKind.pdf);
206 expect(fileKind('nginx.conf'), FileKind.text);
207 });
208 });
210 group('validation never changes the text', () {
211 test('JSON, JSON Lines, YAML and XML report line and column', () {
212 expect(validate('json', '{"a": [1, 2]}'), isNull);
213 final j = validate('json', '{\n "a": 1,\n "b": }')!;
214 expect(j.line, 3);
215 expect(validate('jsonl', '{"a":1}\n{"b":\n')!.line, 2);
216 expect(validate('yaml', 'a: 1\nb: [1, 2\n'), isNotNull);
217 expect(validate('yaml', 'a: 1\nlist:\n - x\n'), isNull);
218 final x = validate('xml', '<a>\n <b></a>')!;
219 expect(x.line, isNotNull);
220 expect(validate('xml', '<?xml version="1.0"?><a><b/></a>'), isNull);
221 expect(validate('python', 'whatever'), isNull);
222 });
223 test('formatting is explicit and only for valid input', () {
224 expect(
225 formatText('json', '{"a":[1,2]}'),
226 '{\n "a": [\n 1,\n 2\n ]\n}',
227 );
228 expect(formatText('json', '{"a":'), isNull);
229 expect(formatText('xml', '<a><b/></a>', indent: 2), '<a>\n <b/>\n</a>');
230 });
231 });
SHA-256f3eeb5dd0ad463382d282fcfe9d3998d133049d16244a95de6e3a9146942489b

CH-J Proprietary Software License 1.14 · Kod sumber disediakan di bawah CH-J Proprietary Software License 1.14. Ketersediaannya tidak mengubah terma lesen atau memberikan hak tambahan.

SHA-256 arkib46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655
Fail