testDriverContract function
- @isTestGroup
- required String packageName,
- required SqlDialect dialect,
- required DdlGenerator createDdlGenerator(),
- required Schema probe,
Verifies the CLI-facing contract of the driver package packageName.
Where testDriverConformance proves runtime behavior against a real
database, this suite proves the package layout the CLI relies on:
- the main library exports a
dialectconstant, passed asdialect. - the driver's table function tags tables with its dialect's
name, which is what snapshot building filters on. lib/ddl.dartexists and itsmainserves the DDL generator over the isolate protocol, answering a realgeneraterequest exactly like the in-process generator.
testDriverContract(
packageName: 'raindrop_sqlite',
dialect: dialect,
createDdlGenerator: SQLiteHarness().createDdlGenerator,
probe: sqliteTable('probe', UserSchema.new),
);
Implementation
@isTestGroup
void testDriverContract({
required String packageName,
required SqlDialect dialect,
required DdlGenerator Function() createDdlGenerator,
required Schema<dynamic> probe,
}) {
group('driver contract', () {
test('the exported dialect constant is the one tables are tagged with', () {
expect(dialect.name, createDdlGenerator().dialect.name);
expect(probe.$.dialect?.name, dialect.name);
});
test('the table function tags tables with the dialect name', () {
expect(probe.$.dialect?.name, createDdlGenerator().dialect.name);
});
test('lib/ddl.dart serves the DDL generator over the isolate protocol',
() async {
final entrypoint = await Isolate.resolvePackageUri(
Uri.parse('package:$packageName/ddl.dart'),
);
expect(
entrypoint,
isNotNull,
reason: 'package:$packageName/ddl.dart must exist: it is the '
'entrypoint the CLI spawns for DDL generation.',
);
final generator = createDdlGenerator();
final operations = fixtureCreateTableOperations(generator.dialect);
final handshake = ReceivePort();
final errors = ReceivePort();
final exit = ReceivePort();
final isolate = await Isolate.spawnUri(
entrypoint!,
[],
handshake.sendPort,
onError: errors.sendPort,
onExit: exit.sendPort,
packageConfig: await _packageConfig(),
);
try {
final failure = errors.first.then(
// Fires only when the entrypoint fails to load.
// coverage:ignore-start
(error) => throw StateError('The DDL entrypoint failed:\n$error'),
// coverage:ignore-end
);
final commands =
await Future.any([handshake.first, failure]) as SendPort;
final replies = ReceivePort();
commands.send({
'action': 'generate',
'operations': [for (final op in operations) op.toMap()],
'replyPort': replies.sendPort,
});
final reply = ((await Future.any([replies.first, failure]))! as Map)
.cast<String, Object?>();
replies.close();
expect(reply['success'], isTrue, reason: '${reply['error']}');
expect(reply['sql'], generator.generate(operations));
} finally {
handshake.close();
errors.close();
isolate.kill(priority: Isolate.immediate);
await exit.first;
exit.close();
}
});
});
}