| // 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:io' as io; | |
| import 'package:file/chroot.dart'; | |
| import 'package:file/file.dart'; | |
| import 'package:file/local.dart'; | |
| import 'package:file/memory.dart'; | |
| import 'package:file_testing/file_testing.dart'; | |
| import 'package:test/test.dart'; | |
| import 'common_tests.dart'; | |
| void main() { | |
| group('ChrootFileSystem', () { | |
| ChrootFileSystem createMemoryBackedChrootFileSystem() { | |
| var fs = MemoryFileSystem(); | |
| fs.directory('/tmp').createSync(); | |
| return ChrootFileSystem(fs, '/tmp'); | |
| } | |
| // TODO(jamesderlin): Make ChrootFile.openSync return a delegating | |
| // RandomAccessFile that uses the chroot'd path. | |
| var skipCommon = <String>[ | |
| // ignore: lines_longer_than_80_chars | |
| 'File > open > .* > RandomAccessFile > read > openReadHandleDoesNotChange', | |
| 'File > open > .* > RandomAccessFile > openWriteHandleDoesNotChange', | |
| ]; | |
| group('memoryBacked', () { | |
| runCommonTests(createMemoryBackedChrootFileSystem, skip: skipCommon); | |
| }); | |
| group('localBacked', () { | |
| late ChrootFileSystem fs; | |
| late io.Directory tmp; | |
| setUp(() { | |
| tmp = io.Directory.systemTemp.createTempSync('file_test_'); | |
| tmp = io.Directory(tmp.resolveSymbolicLinksSync()); | |
| fs = ChrootFileSystem(const LocalFileSystem(), tmp.path); | |
| }); | |
| tearDown(() { | |
| tmp.deleteSync(recursive: true); | |
| }); | |
| runCommonTests( | |
| () => fs, | |
| skip: <String>[ | |
| // https://github.com/dart-lang/sdk/issues/28275 | |
| 'Link > rename > throwsIfDestinationExistsAsDirectory', | |
| // https://github.com/dart-lang/sdk/issues/28277 | |
| 'Link > rename > throwsIfDestinationExistsAsFile', | |
| ...skipCommon, | |
| ], | |
| ); | |
| }, skip: io.Platform.isWindows); | |
| group('chrootSpecific', () { | |
| late ChrootFileSystem fs; | |
| late MemoryFileSystem mem; | |
| setUp(() { | |
| fs = createMemoryBackedChrootFileSystem(); | |
| mem = fs.delegate as MemoryFileSystem; | |
| }); | |
| group('FileSystem', () { | |
| group('currentDirectory', () { | |
| test('staysInJailIfSetToParentOfRoot', () { | |
| fs.currentDirectory = '../../../..'; | |
| fs.file('foo').createSync(); | |
| expect(mem.file('/tmp/foo'), exists); | |
| }); | |
| test('throwsIfSetToSymlinkToDirectoryOutsideJail', () { | |
| mem.directory('/bar').createSync(); | |
| mem.link('/tmp/foo').createSync('/bar'); | |
| expectFileSystemException(ErrorCodes.ENOENT, () { | |
| fs.currentDirectory = '/foo'; | |
| }); | |
| }); | |
| }); | |
| group('stat', () { | |
| test('isNotFoundForJailbreakPath', () { | |
| mem.file('/foo').createSync(); | |
| expect(fs.statSync('../foo').type, FileSystemEntityType.notFound); | |
| }); | |
| test('isNotFoundForSymlinkWithJailbreakTarget', () { | |
| mem.file('/foo').createSync(); | |
| mem.link('/tmp/bar').createSync('/foo'); | |
| expect(mem.statSync('/tmp/bar').type, FileSystemEntityType.file); | |
| expect(fs.statSync('/bar').type, FileSystemEntityType.notFound); | |
| }); | |
| test('isNotFoundForSymlinkToOutsideAndBackInsideJail', () { | |
| mem.file('/tmp/bar').createSync(); | |
| mem.link('/foo').createSync('/tmp/bar'); | |
| mem.link('/tmp/baz').createSync('/foo'); | |
| expect(mem.statSync('/tmp/baz').type, FileSystemEntityType.file); | |
| expect(fs.statSync('/baz').type, FileSystemEntityType.notFound); | |
| }); | |
| }); | |
| group('type', () { | |
| test('isNotFoundForJailbreakPath', () { | |
| mem.file('/foo').createSync(); | |
| expect(fs.typeSync('../foo'), FileSystemEntityType.notFound); | |
| }); | |
| test('isNotFoundForSymlinkWithJailbreakTarget', () { | |
| mem.file('/foo').createSync(); | |
| mem.link('/tmp/bar').createSync('/foo'); | |
| expect(mem.typeSync('/tmp/bar'), FileSystemEntityType.file); | |
| expect(fs.typeSync('/bar'), FileSystemEntityType.notFound); | |
| }); | |
| test('isNotFoundForSymlinkToOutsideAndBackInsideJail', () { | |
| mem.file('/tmp/bar').createSync(); | |
| mem.link('/foo').createSync('/tmp/bar'); | |
| mem.link('/tmp/baz').createSync('/foo'); | |
| expect(mem.typeSync('/tmp/baz'), FileSystemEntityType.file); | |
| expect(fs.typeSync('/baz'), FileSystemEntityType.notFound); | |
| }); | |
| }); | |
| }); | |
| group('File', () { | |
| group('delegate', () { | |
| test('referencesRootEntityForJailbreakPath', () { | |
| mem.file('/foo').createSync(); | |
| dynamic f = fs.file('../foo'); | |
| // ignore: avoid_dynamic_calls | |
| expect(f.delegate.path, '/tmp/foo'); | |
| }); | |
| }); | |
| group('create', () { | |
| test('createsAtRootIfPathReferencesJailbreakFile', () { | |
| fs.file('../foo').createSync(); | |
| expect(mem.file('/foo'), isNot(exists)); | |
| expect(mem.file('/tmp/foo'), exists); | |
| }); | |
| }); | |
| group('copy', () { | |
| test('copiesToRootDirectoryIfDestinationIsJailbreakPath', () { | |
| var f = fs.file('/foo')..createSync(); | |
| f.copySync('../bar'); | |
| expect(mem.file('/bar'), isNot(exists)); | |
| expect(mem.file('/tmp/bar'), exists); | |
| }); | |
| }); | |
| }); | |
| group('Link', () { | |
| group('target', () { | |
| test('chrootAndDelegateFileSystemsReturnSameValue', () { | |
| mem.file('/foo').createSync(); | |
| mem.link('/tmp/bar').createSync('/foo'); | |
| mem.link('/tmp/baz').createSync('../foo'); | |
| expect(mem.link('/tmp/bar').targetSync(), '/foo'); | |
| expect(fs.link('/bar').targetSync(), '/foo'); | |
| expect(mem.link('/tmp/baz').targetSync(), '../foo'); | |
| expect(fs.link('/baz').targetSync(), '../foo'); | |
| }); | |
| }); | |
| }); | |
| }); | |
| }); | |
| } |