Skip to content

Commit de18630

Browse files
committed
ci: verify against shared cobs-conformance vectors
Adds tool/conformance.dart which checks encode/decode for both COBS and COBS/R against the canonical vectors at firechip/cobs-conformance, and a CI job that downloads the pinned v1.0.0 vectors and runs it. tool/ is excluded from the published package via .pubignore. Signed-off-by: Alexander Salas Bastidas <ajsb85@firechip.dev>
1 parent 1d66d87 commit de18630

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,16 @@ jobs:
5858
run: |
5959
dart pub global activate pana
6060
dart pub global run pana --no-warning --exit-code-threshold 20 .
61+
62+
conformance:
63+
name: Conformance vectors
64+
runs-on: ubuntu-latest
65+
steps:
66+
- uses: actions/checkout@v7
67+
- uses: dart-lang/setup-dart@v1
68+
- name: Install dependencies
69+
run: dart pub get
70+
- name: Download shared conformance vectors
71+
run: curl -sSfL -o vectors.jsonl https://raw.githubusercontent.com/firechip/cobs-conformance/v1.0.0/vectors/vectors.jsonl
72+
- name: Check conformance
73+
run: dart run tool/conformance.dart vectors.jsonl

.pubignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Dev-only conformance tooling; not part of the published package.
2+
tool/

tool/conformance.dart

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Verifies this package against the shared conformance vectors from
2+
// https://github.com/firechip/cobs-conformance
3+
//
4+
// Usage: dart run tool/conformance.dart <vectors.jsonl>
5+
import 'dart:convert';
6+
import 'dart:io';
7+
import 'dart:typed_data';
8+
9+
import 'package:cobs_codec/cobs_codec.dart';
10+
11+
Uint8List _hex(String s) {
12+
final out = Uint8List(s.length ~/ 2);
13+
for (var i = 0; i < out.length; i++) {
14+
out[i] = int.parse(s.substring(i * 2, i * 2 + 2), radix: 16);
15+
}
16+
return out;
17+
}
18+
19+
String _toHex(List<int> b) =>
20+
b.map((x) => x.toRadixString(16).padLeft(2, '0')).join();
21+
22+
void main(List<String> args) {
23+
final path = args.isNotEmpty ? args[0] : 'vectors.jsonl';
24+
var checked = 0;
25+
var failures = 0;
26+
27+
void check(bool ok, String what) {
28+
if (!ok) {
29+
failures++;
30+
if (failures <= 10) stderr.writeln('MISMATCH: $what');
31+
}
32+
}
33+
34+
for (final line in File(path).readAsLinesSync()) {
35+
if (line.trim().isEmpty) continue;
36+
final v = json.decode(line) as Map<String, dynamic>;
37+
final decodedHex = v['decoded'] as String;
38+
final cobsHex = v['cobs'] as String;
39+
final cobsrHex = v['cobsr'] as String;
40+
final decoded = _hex(decodedHex);
41+
42+
check(_toHex(cobsEncode(decoded)) == cobsHex, 'cobs encode $decodedHex');
43+
check(_toHex(cobsrEncode(decoded)) == cobsrHex, 'cobsr encode $decodedHex');
44+
check(_toHex(cobsDecode(_hex(cobsHex))) == decodedHex, 'cobs decode $cobsHex');
45+
check(_toHex(cobsrDecode(_hex(cobsrHex))) == decodedHex,
46+
'cobsr decode $cobsrHex');
47+
checked++;
48+
}
49+
50+
stdout.writeln('Conformance: checked $checked vectors, $failures failures.');
51+
if (checked == 0) {
52+
stderr.writeln('ERROR: no vectors found in $path');
53+
exit(1);
54+
}
55+
if (failures > 0) exit(1);
56+
}

0 commit comments

Comments
 (0)