Run common tests for ReplayFileSystem. (#31)
diff --git a/test/common_tests.dart b/test/common_tests.dart
index c3c2abf..21312e3 100644
--- a/test/common_tests.dart
+++ b/test/common_tests.dart
@@ -10,12 +10,20 @@
import 'package:file/file.dart';
import 'package:file/testing.dart';
import 'package:test/test.dart';
-import 'package:test/test.dart' as testpkg show group, test;
+import 'package:test/test.dart' as testpkg show group, test, setUp;
/// Callback used in [runCommonTests] to produce the root folder in which all
/// file system entities will be created.
typedef String RootPathGenerator();
+/// Callback used in [runCommonTests] to create the file system under test.
+/// It must return either a [FileSystem] or a [Future] that completes with a
+/// [FileSystem].
+typedef dynamic FileSystemGenerator();
+
+/// A function to run before tests (passed to [setUp]).
+typedef dynamic SetUpCallback();
+
/// Runs a suite of tests common to all file system implementations. All file
/// system implementations should run *at least* these tests to ensure
/// compliance with file system API.
@@ -29,14 +37,24 @@
/// not yet fully complete). The format of each entry in the list is:
/// `$group1Description > $group2Description > ... > $testDescription`.
/// Entries may use regular expression syntax.
+///
+/// If [replay] is specified, each test (and its setup callbacks) will run
+/// twice - once as a "setup" pass with the file system returned by
+/// [createFileSystem], and again as the "test" pass with the file system
+/// returned by [replay]. This is intended for use with `ReplayFileSystem`,
+/// where in order for the file system to behave as expected, a recording of
+/// the invocation(s) must first be made.
void runCommonTests(
- FileSystem createFileSystem(), {
+ FileSystemGenerator createFileSystem, {
RootPathGenerator root,
List<String> skip: const <String>[],
+ FileSystemGenerator replay,
}) {
RootPathGenerator rootfn = root;
group('common', () {
+ FileSystemGenerator createFs;
+ List<SetUpCallback> setUps;
FileSystem fs;
String root;
@@ -52,11 +70,36 @@
stack.removeLast();
}
+ testpkg.setUp(() async {
+ createFs = createFileSystem;
+ setUps = <SetUpCallback>[];
+ fs = null;
+ root = null;
+ });
+
+ void setUp(callback()) {
+ testpkg.setUp(replay == null ? callback : () => setUps.add(callback));
+ }
+
void group(String description, body()) =>
skipIfNecessary(description, () => testpkg.group(description, body));
- void test(String description, body()) =>
- skipIfNecessary(description, () => testpkg.test(description, body));
+ void test(String description, body()) => skipIfNecessary(description, () {
+ if (replay == null) {
+ testpkg.test(description, body);
+ } else {
+ group('rerun', () {
+ testpkg.setUp(() async {
+ await Future.forEach(setUps, (SetUpCallback setUp) => setUp());
+ await body();
+ createFs = replay;
+ await Future.forEach(setUps, (SetUpCallback setUp) => setUp());
+ });
+
+ testpkg.test(description, body);
+ });
+ }
+ });
/// Returns [path] prefixed by the [root] namespace.
/// This is only intended for absolute paths.
@@ -68,10 +111,10 @@
return root == '/' ? path : (path == '/' ? root : '$root$path');
}
- setUp(() {
+ setUp(() async {
root = rootfn != null ? rootfn() : '/';
assert(root.startsWith('/') && (root == '/' || !root.endsWith('/')));
- fs = createFileSystem();
+ fs = await createFs();
});
group('FileSystem', () {
@@ -588,7 +631,7 @@
expect(fs.link(ns('/baz')).targetSync(), ns('/foo'));
});
- test('succeedsIfDestinationIsLinkToNotFound', () {
+ test('throwsIfDestinationIsLinkToNotFound', () {
Directory src = fs.directory(ns('/foo'))..createSync();
fs.link(ns('/bar')).createSync(ns('/baz'));
expectFileSystemException('Not a directory', () {
diff --git a/test/replay_test.dart b/test/replay_test.dart
index 517c553..65d317b 100644
--- a/test/replay_test.dart
+++ b/test/replay_test.dart
@@ -11,6 +11,8 @@
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
+import 'common_tests.dart';
+
void main() {
group('Replay', () {
RecordingFileSystem recordingFileSystem;
@@ -33,6 +35,21 @@
return new ReplayFileSystem(recording: recording.destination);
}
+ runCommonTests(
+ () => recordingFileSystem,
+ replay: replay,
+ skip: <String>[
+ // ReplayFileSystem does not yet replay exceptions
+ '.*(disallows|throws).*',
+
+ // TODO(tvolkert): Enable when ReplayFileSystem is complete.
+ 'FileSystem',
+ 'Directory',
+ 'File',
+ 'Link',
+ ],
+ );
+
group('ReplayFileSystem', () {
test('directory', () async {
recordingFileSystem.directory('/foo');