blob: bac6153538a759ab07a32143244526e4e39fbac3 [file] [log] [blame]
// Copyright (c) 2017, 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.
@TestOn('vm')
library;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:term_glyph/term_glyph.dart' as term_glyph;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
import 'utils.dart';
void main() {
group('create()', () {
test('creates a directory and its contents', () async {
await d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('file2.txt', 'contents2'),
]).create();
expect(
File(p.join(d.sandbox, 'dir', 'file1.txt')).readAsString(),
completion(equals('contents1')),
);
expect(
File(p.join(d.sandbox, 'dir', 'file2.txt')).readAsString(),
completion(equals('contents2')),
);
expect(
File(p.join(d.sandbox, 'dir', 'subdir', 'subfile1.txt')).readAsString(),
completion(equals('subcontents1')),
);
expect(
File(p.join(d.sandbox, 'dir', 'subdir', 'subfile2.txt')).readAsString(),
completion(equals('subcontents2')),
);
});
test('works if the directory already exists', () async {
await d.dir('dir').create();
await d.dir('dir', [d.file('name.txt', 'contents')]).create();
expect(
File(p.join(d.sandbox, 'dir', 'name.txt')).readAsString(),
completion(equals('contents')),
);
});
});
group('validate()', () {
test('completes successfully if the filesystem matches the descriptor',
() async {
final dirPath = p.join(d.sandbox, 'dir');
final subdirPath = p.join(dirPath, 'subdir');
await Directory(subdirPath).create(recursive: true);
await File(p.join(dirPath, 'file1.txt')).writeAsString('contents1');
await File(p.join(dirPath, 'file2.txt')).writeAsString('contents2');
await File(p.join(subdirPath, 'subfile1.txt'))
.writeAsString('subcontents1');
await File(p.join(subdirPath, 'subfile2.txt'))
.writeAsString('subcontents2');
await d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('file2.txt', 'contents2'),
]).validate();
});
test("fails if the directory doesn't exist", () async {
final dirPath = p.join(d.sandbox, 'dir');
await Directory(dirPath).create();
await File(p.join(dirPath, 'file1.txt')).writeAsString('contents1');
await File(p.join(dirPath, 'file2.txt')).writeAsString('contents2');
expect(
d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('file2.txt', 'contents2'),
]).validate(),
throwsA(
toString(
equals('Directory not found: "${p.join('dir', 'subdir')}".'),
),
),
);
});
test('emits an error for each child that fails to validate', () async {
final dirPath = p.join(d.sandbox, 'dir');
final subdirPath = p.join(dirPath, 'subdir');
await Directory(subdirPath).create(recursive: true);
await File(p.join(dirPath, 'file1.txt')).writeAsString('contents1');
await File(p.join(subdirPath, 'subfile2.txt'))
.writeAsString('subwrongtents2');
var errors = 0;
final controller = StreamController<String>();
runZonedGuarded(
() {
d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('file2.txt', 'contents2'),
]).validate();
},
expectAsync2(
(error, _) {
errors++;
controller.add(error.toString());
if (errors == 3) controller.close();
},
count: 3,
),
);
expect(
controller.stream.toList(),
completion(
allOf([
contains(
'File not found: "${p.join('dir', 'subdir', 'subfile1.txt')}".',
),
contains('File not found: "${p.join('dir', 'file2.txt')}".'),
contains(
startsWith('File "${p.join('dir', 'subdir', 'subfile2.txt')}" '
'should contain:'),
),
]),
),
);
});
});
group('load()', () {
test('loads a file', () {
final dir = d.dir(
'dir',
[d.file('name.txt', 'contents'), d.file('other.txt', 'wrong')],
);
expect(
utf8.decodeStream(dir.load('name.txt')),
completion(equals('contents')),
);
});
test('loads a deeply-nested file', () {
final dir = d.dir('dir', [
d.dir(
'subdir',
[d.file('name.txt', 'subcontents'), d.file('other.txt', 'wrong')],
),
d.dir('otherdir', [d.file('other.txt', 'wrong')]),
d.file('name.txt', 'contents'),
]);
expect(
utf8.decodeStream(dir.load('subdir/name.txt')),
completion(equals('subcontents')),
);
});
test('fails to load a nested directory', () {
final dir = d.dir('dir', [
d.dir('subdir', [
d.dir('subsubdir', [d.file('name.txt', 'subcontents')]),
]),
d.file('name.txt', 'contents'),
]);
expect(
dir.load('subdir/subsubdir').toList(),
throwsA(
toString(
equals('Couldn\'t find a file descriptor named '
'"subsubdir" within "dir/subdir".'),
),
),
);
});
test('fails to load an absolute path', () {
final dir = d.dir('dir', [d.file('name.txt', 'contents')]);
expect(() => dir.load('/name.txt'), throwsArgumentError);
});
test("fails to load '..'", () {
final dir = d.dir('dir', [d.file('name.txt', 'contents')]);
expect(() => dir.load('..'), throwsArgumentError);
});
test("fails to load a file that doesn't exist", () {
final dir = d.dir('dir', [
d.dir('subdir', [d.file('name.txt', 'contents')]),
]);
expect(
dir.load('subdir/not-name.txt').toList(),
throwsA(
toString(
equals('Couldn\'t find a file descriptor named '
'"not-name.txt" within "dir/subdir".'),
),
),
);
});
test('fails to load a file that exists multiple times', () {
final dir = d.dir('dir', [
d.dir(
'subdir',
[d.file('name.txt', 'contents'), d.file('name.txt', 'contents')],
),
]);
expect(
dir.load('subdir/name.txt').toList(),
throwsA(
toString(
equals('Found multiple file descriptors named '
'"name.txt" within "dir/subdir".'),
),
),
);
});
test('loads a file next to a subdirectory with the same name', () {
final dir = d.dir('dir', [
d.file('name', 'contents'),
d.dir('name', [d.file('subfile', 'contents')]),
]);
expect(
utf8.decodeStream(dir.load('name')),
completion(equals('contents')),
);
});
});
group('describe()', () {
late bool oldAscii;
setUpAll(() {
oldAscii = term_glyph.ascii;
term_glyph.ascii = true;
});
tearDownAll(() {
term_glyph.ascii = oldAscii;
});
test('lists the contents of the directory', () {
final dir = d.dir(
'dir',
[d.file('file1.txt', 'contents1'), d.file('file2.txt', 'contents2')],
);
expect(
dir.describe(),
equals('dir\n'
'+-- file1.txt\n'
"'-- file2.txt"),
);
});
test('lists the contents of nested directories', () {
final dir = d.dir('dir', [
d.file('file1.txt', 'contents1'),
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
d.dir('subsubdir', [d.file('subsubfile.txt', 'subsubcontents')]),
]),
d.file('file2.txt', 'contents2'),
]);
expect(
dir.describe(),
equals('dir\n'
'+-- file1.txt\n'
'+-- subdir\n'
'| +-- subfile1.txt\n'
'| +-- subfile2.txt\n'
"| '-- subsubdir\n"
"| '-- subsubfile.txt\n"
"'-- file2.txt"),
);
});
test('with no contents returns the directory name', () {
expect(d.dir('dir').describe(), equals('dir'));
});
});
group('fromFilesystem()', () {
test('creates a descriptor based on the physical filesystem', () async {
final dir = d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('subfile2.txt', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('file2.txt', 'contents2'),
]);
await dir.create();
final descriptor =
d.DirectoryDescriptor.fromFilesystem('dir', p.join(d.sandbox, 'dir'));
await descriptor.create(p.join(d.sandbox, 'dir2'));
await dir.validate(p.join(d.sandbox, 'dir2'));
});
test('ignores hidden files', () async {
await d.dir('dir', [
d.dir('subdir', [
d.file('subfile1.txt', 'subcontents1'),
d.file('.hidden', 'subcontents2'),
]),
d.file('file1.txt', 'contents1'),
d.file('.DS_Store', 'contents2'),
]).create();
final descriptor = d.DirectoryDescriptor.fromFilesystem(
'dir2',
p.join(d.sandbox, 'dir'),
);
await descriptor.create();
await d.dir('dir2', [
d.dir(
'subdir',
[d.file('subfile1.txt', 'subcontents1'), d.nothing('.hidden')],
),
d.file('file1.txt', 'contents1'),
d.nothing('.DS_Store'),
]).validate();
});
});
test('io refers to the directory within the sandbox', () {
expect(d.file('dir').io.path, equals(p.join(d.sandbox, 'dir')));
});
}