- Add VariableSpec class with magnitude field validation - Add Formula class supporting multiple input/output variables - Support d4rt_code as string or object with code field - Add comprehensive tests for parsing and serialization - Fix broken test import in pruebas_d4rt_test.dart Follows README.md format requirements exactly
154 lines
4.9 KiB
Dart
154 lines
4.9 KiB
Dart
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:convert';
|
|
import 'dart:core';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:convert/convert.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
void main() {
|
|
var bytes = Uint8List.fromList([for (var i = 0; i < 256; i++) i]);
|
|
for (var cp in [
|
|
latin2,
|
|
latin3,
|
|
latin4,
|
|
latin5,
|
|
latin6,
|
|
latin7,
|
|
latin8,
|
|
latin9,
|
|
latin10,
|
|
latinCyrillic,
|
|
latinGreek,
|
|
latinHebrew,
|
|
latinThai,
|
|
latinArabic
|
|
]) {
|
|
group('${cp.name} codepage', () {
|
|
test('ascii compatible', () {
|
|
for (var byte = 0x20; byte < 0x7f; byte++) {
|
|
expect(cp[byte], byte);
|
|
}
|
|
});
|
|
|
|
test('bidirectional mapping', () {
|
|
// Maps both directions.
|
|
for (var byte = 0; byte < 256; byte++) {
|
|
var char = cp[byte];
|
|
if (char != 0xFFFD) {
|
|
var string = String.fromCharCode(char);
|
|
expect(cp.encode(string), [byte]);
|
|
expect(cp.decode([byte]), string);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('decode invalid characters not allowed', () {
|
|
expect(() => cp.decode([0xfffd]), throwsA(isA<FormatException>()));
|
|
});
|
|
|
|
test('decode invalid characters allowed', () {
|
|
// Decode works like operator[].
|
|
expect(cp.decode(bytes, allowInvalid: true),
|
|
String.fromCharCodes([for (var i = 0; i < 256; i++) cp[i]]));
|
|
});
|
|
|
|
test('chunked conversion', () {
|
|
late final String decodedString;
|
|
final outputSink = StringConversionSink.withCallback(
|
|
(accumulated) => decodedString = accumulated);
|
|
final inputSink = cp.decoder.startChunkedConversion(outputSink);
|
|
final expected = StringBuffer();
|
|
|
|
for (var byte = 0; byte < 256; byte++) {
|
|
var char = cp[byte];
|
|
if (char != 0xFFFD) {
|
|
inputSink.add([byte]);
|
|
expected.writeCharCode(char);
|
|
}
|
|
}
|
|
inputSink.close();
|
|
expect(decodedString, expected.toString());
|
|
});
|
|
});
|
|
}
|
|
test('latin-2 roundtrip', () {
|
|
// Data from http://www.columbia.edu/kermit/latin2.html
|
|
var latin2text = '\xa0Ą˘Ł¤ĽŚ§¨ŠŞŤŹ\xadŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇ'
|
|
'ÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙';
|
|
expect(latin2.decode(latin2.encode(latin2text)), latin2text);
|
|
});
|
|
|
|
test('latin-3 roundtrip', () {
|
|
// Data from http://www.columbia.edu/kermit/latin3.html
|
|
var latin2text = '\xa0Ħ˘£¤\u{FFFD}Ĥ§¨İŞĞĴ\xad\u{FFFD}ݰħ²³´µĥ·¸ışğĵ½'
|
|
'\u{FFFD}żÀÁÂ\u{FFFD}ÄĊĈÇÈÉÊËÌÍÎÏ\u{FFFD}ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ'
|
|
'\u{FFFD}äċĉçèéêëìíîï\u{FFFD}ñòóôġö÷ĝùúûüŭŝ˙';
|
|
var encoded = latin3.encode(latin2text, invalidCharacter: 0);
|
|
var decoded = latin3.decode(encoded, allowInvalid: true);
|
|
expect(decoded, latin2text);
|
|
});
|
|
|
|
group('Custom code page', () {
|
|
late final cp = CodePage('custom', "ABCDEF${"\uFFFD" * 250}");
|
|
|
|
test('simple encode', () {
|
|
var result = cp.encode('BADCAFE');
|
|
expect(result, [1, 0, 3, 2, 0, 5, 4]);
|
|
});
|
|
|
|
test('unencodable character', () {
|
|
expect(() => cp.encode('GAD'), throwsFormatException);
|
|
});
|
|
|
|
test('unencodable character with invalidCharacter', () {
|
|
expect(cp.encode('GAD', invalidCharacter: 0x3F), [0x3F, 0, 3]);
|
|
});
|
|
|
|
test('simple decode', () {
|
|
expect(cp.decode([1, 0, 3, 2, 0, 5, 4]), 'BADCAFE');
|
|
});
|
|
|
|
test('undecodable byte', () {
|
|
expect(() => cp.decode([6, 1, 255]), throwsFormatException);
|
|
});
|
|
|
|
test('undecodable byte with allowInvalid', () {
|
|
expect(cp.decode([6, 1, 255], allowInvalid: true), '\u{FFFD}B\u{FFFD}');
|
|
});
|
|
|
|
test('chunked conversion', () {
|
|
late final String decodedString;
|
|
final outputSink = StringConversionSink.withCallback(
|
|
(accumulated) => decodedString = accumulated);
|
|
final inputSink = cp.decoder.startChunkedConversion(outputSink);
|
|
|
|
inputSink
|
|
..add([1])
|
|
..add([0])
|
|
..add([3])
|
|
..close();
|
|
expect(decodedString, 'BAD');
|
|
});
|
|
|
|
test('chunked conversion - byte conversion sink', () {
|
|
late final String decodedString;
|
|
final outputSink = StringConversionSink.withCallback(
|
|
(accumulated) => decodedString = accumulated);
|
|
final bytes = [1, 0, 3, 2, 0, 5, 4];
|
|
|
|
final inputSink = cp.decoder.startChunkedConversion(outputSink);
|
|
expect(inputSink, isA<ByteConversionSink>());
|
|
|
|
(inputSink as ByteConversionSink)
|
|
..addSlice(bytes, 1, 3, false)
|
|
..addSlice(bytes, 4, 5, false)
|
|
..addSlice(bytes, 6, 6, true);
|
|
|
|
expect(decodedString, 'ADA');
|
|
});
|
|
});
|
|
}
|