nandi/vflutter_ffipublic Fork 0
4506a586d7400b00d732dcb97167be75ab41cab1
Commits
Clone
git clone https://git.rickub.com/nandi/vflutter_ffi.git
git clone ssh://git@rickub.com/nandi/vflutter_ffi.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

abi_guard_test.dart · 107 lines · 3.4 KBDart Blame HistoryRaw
Replace V with Nim 472eb49 nandithebull 17h ago1// Guards the nf_mandelbrot contract at the C boundary.
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago2//
Replace V with Nim 472eb49 nandithebull 17h ago3// Everything else in the suite goes through lib/nimflutter_ffi.dart, which
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago4// always passes a correctly sized buffer. These tests deliberately bypass it
5// and call the raw symbol the way a careless C caller would, because the
6// point of `buf_len` is to survive exactly that. Needs the native build on
7// the loader path — see widget_test.dart.
8import 'dart:ffi';
9
10import 'package:ffi/ffi.dart';
11import 'package:flutter_test/flutter_test.dart';
Replace V with Nim 472eb49 nandithebull 17h ago12import 'package:nimflutter_ffi/nimflutter_ffi.dart' as v;
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago13
14typedef _MandelbrotNative = Void Function(Pointer<Uint8>, Size, Int32, Int32,
15 Double, Double, Double, Int32, Int32, Int32);
16typedef _MandelbrotDart = void Function(Pointer<Uint8>, int, int, int, double,
17 double, double, int, int, int);
18
19void main() {
20 v.ensureInitialized();
21
Replace V with Nim 472eb49 nandithebull 17h ago22 final mandelbrot = DynamicLibrary.open('libnimflutter.so')
23 .lookupFunction<_MandelbrotNative, _MandelbrotDart>('nf_mandelbrot');
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago24
25 const w = 16;
26 const h = 16;
27 const bytes = w * h * 4;
28 // A canary region past the band. Nothing below may touch it.
29 const canary = 1024;
30 const canaryByte = 0xAB;
31
32 late Pointer<Uint8> buf;
33
34 setUp(() {
35 buf = calloc<Uint8>(bytes + canary);
36 for (var i = bytes; i < bytes + canary; i++) {
37 buf[i] = canaryByte;
38 }
39 });
40
41 tearDown(() => calloc.free(buf));
42
43 bool canaryIntact() {
44 for (var i = bytes; i < bytes + canary; i++) {
45 if (buf[i] != canaryByte) return false;
46 }
47 return true;
48 }
49
Replace V with Nim 472eb49 nandithebull 17h ago50 /// True if Nim wrote anything into the band at all.
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago51 bool bandTouched() {
52 for (var i = 0; i < bytes; i++) {
53 if (buf[i] != 0) return true;
54 }
55 return false;
56 }
57
58 void expectNoOp(String why) {
Replace V with Nim 472eb49 nandithebull 17h ago59 expect(bandTouched(), isFalse, reason: '$why: Nim wrote into the band');
60 expect(canaryIntact(), isTrue, reason: '$why: Nim wrote past the band');
Add a WebAssembly backend for the example 728acaa nandithebull 18h ago61 }
62
63 test('a correctly sized call fills the whole band', () {
64 mandelbrot(buf, bytes, w, h, -0.5, 0.0, 3.0, 50, 0, h);
65 for (var i = 3; i < bytes; i += 4) {
66 expect(buf[i], 255, reason: 'alpha at pixel ${i ~/ 4}');
67 }
68 expect(canaryIntact(), isTrue);
69 });
70
71 test('a buf_len one byte short is refused outright', () {
72 // The tempting bug is to fill what fits and overrun by one; this must
73 // write nothing at all.
74 mandelbrot(buf, bytes - 1, w, h, -0.5, 0.0, 3.0, 50, 0, h);
75 expectNoOp('buf_len short by one');
76 });
77
78 test('a buf_len sized for a single row is refused', () {
79 mandelbrot(buf, w * 4, w, h, -0.5, 0.0, 3.0, 50, 0, h);
80 expectNoOp('buf_len sized for one row');
81 });
82
83 test('a zero buf_len is refused', () {
84 mandelbrot(buf, 0, w, h, -0.5, 0.0, 3.0, 50, 0, h);
85 expectNoOp('buf_len zero');
86 });
87
88 test('a null buffer is a no-op, not a crash', () {
89 mandelbrot(nullptr, bytes, w, h, -0.5, 0.0, 3.0, 50, 0, h);
90 expectNoOp('null buf');
91 });
92
93 test('an inverted band is refused', () {
94 mandelbrot(buf, bytes, w, h, -0.5, 0.0, 3.0, 50, 10, 2);
95 expectNoOp('y1 < y0');
96 });
97
98 test('geometry whose byte count overflows int32 is refused', () {
99 // (y1 - y0) * w * 4 = 2 * 2^30 * 4 wraps to 0 in 32-bit arithmetic, which
100 // is the case a length check alone would happily accept.
101 mandelbrot(buf, bytes, 1 << 30, h, -0.5, 0.0, 3.0, 50, 0, 2);
102 expectNoOp('w = 1 << 30');
103
104 mandelbrot(buf, bytes, w, h, -0.5, 0.0, 3.0, 50, 0, 0x7FFFFFFF);
105 expectNoOp('y1 = INT32_MAX');
106 });
107}