/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This file is part of ObjFW. It may be distributed under the terms of the
* Q Public License 1.0, which can be found in the file LICENSE.QPL included in
* the packaging of this file.
*
* Alternatively, it may be distributed under the terms of the GNU General
* Public License, either version 2 or 3, which can be found in the file
* LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
* file.
*/
#include "config.h"
#import "ObjFW.h"
#import "ObjFWTest.h"
@interface OFFileManagerTests: OTTestCase
{
OFFileManager *_fileManager;
OFIRI *_testsDirectoryIRI, *_testFileIRI;
}
@end
@implementation OFFileManagerTests
- (void)setUp
{
_fileManager = [[OFFileManager defaultManager] retain];
_testsDirectoryIRI = [[[OFSystemInfo temporaryDirectoryIRI]
IRIByAppendingPathComponent: @"objfw-tests"] retain];
_testFileIRI = [[_testsDirectoryIRI
IRIByAppendingPathComponent: @"test.txt"] retain];
/* In case a previous test run failed and left things. */
if ([_fileManager directoryExistsAtIRI: _testsDirectoryIRI])
[_fileManager removeItemAtIRI: _testsDirectoryIRI];
[_fileManager createDirectoryAtIRI: _testsDirectoryIRI];
[@"test" writeToIRI: _testFileIRI];
}
- (void)tearDown
{
[_fileManager removeItemAtIRI: _testsDirectoryIRI];
}
- (void)dealloc
{
[_fileManager release];
[_testsDirectoryIRI release];
[_testFileIRI release];
[super dealloc];
}
- (void)testCurrentDirectoryPath
{
OTAssertEqualObjects(
_fileManager.currentDirectoryPath.lastPathComponent, @"tests");
}
- (void)testAttributesOfItemAtPath
{
OFFileAttributes attributes;
attributes = [_fileManager attributesOfItemAtPath:
_testsDirectoryIRI.fileSystemRepresentation];
OTAssertEqual(attributes.fileType, OFFileTypeDirectory);
attributes = [_fileManager attributesOfItemAtPath:
_testFileIRI.fileSystemRepresentation];
OTAssertEqual(attributes.fileType, OFFileTypeRegular);
OTAssertEqual(attributes.fileSize, 4);
}
- (void)testSetAttributesOfItemAtPath
{
OFDate *date = [OFDate dateWithTimeIntervalSince1970: 946681200];
OFFileAttributes attributes;
attributes = [OFDictionary
dictionaryWithObject: date
forKey: OFFileModificationDate];
[_fileManager setAttributes: attributes
ofItemAtPath: _testFileIRI.fileSystemRepresentation];
attributes = [_fileManager attributesOfItemAtPath:
_testFileIRI.fileSystemRepresentation];
OTAssertEqual(attributes.fileType, OFFileTypeRegular);
OTAssertEqual(attributes.fileSize, 4);
OTAssertEqualObjects(attributes.fileModificationDate, date);
}
- (void)testFileExistsAtPath
{
OTAssertTrue([_fileManager fileExistsAtPath:
_testsDirectoryIRI.fileSystemRepresentation]);
OTAssertTrue([_fileManager fileExistsAtPath:
_testFileIRI.fileSystemRepresentation]);
}
- (void)testDirectoryExistsAtPath
{
OTAssertTrue([_fileManager directoryExistsAtPath:
_testsDirectoryIRI.fileSystemRepresentation]);
OTAssertFalse([_fileManager directoryExistsAtPath:
_testFileIRI.fileSystemRepresentation]);
}
- (void)testDirectoryAtPathCreateParents
{
OFIRI *nestedDirectoryIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"0/1/2/3/4/5"];
[_fileManager
createDirectoryAtPath: nestedDirectoryIRI.fileSystemRepresentation
createParents: true];
OTAssertTrue([_fileManager directoryExistsAtPath:
nestedDirectoryIRI.fileSystemRepresentation]);
}
- (void)testContentsOfDirectoryAtPath
{
OFIRI *file1IRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"1.txt"];
OFIRI *file2IRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"2.txt"];
[@"1" writeToIRI: file1IRI];
[@"2" writeToIRI: file2IRI];
OTAssertEqualObjects([_fileManager contentsOfDirectoryAtPath:
_testsDirectoryIRI.fileSystemRepresentation].sortedArray,
([OFArray arrayWithObjects: @"1.txt", @"2.txt", @"test.txt", nil]));
}
- (void)testSubpathsOfDirectoryAtPath
{
OFIRI *subdirectory1IRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"a"];
OFIRI *subdirectory2IRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"b"];
OFIRI *file1IRI = [subdirectory1IRI
IRIByAppendingPathComponent: @"1.txt"];
OFIRI *file2IRI = [subdirectory2IRI
IRIByAppendingPathComponent: @"2.txt"];
[_fileManager createDirectoryAtIRI: subdirectory1IRI];
[_fileManager createDirectoryAtIRI: subdirectory2IRI];
[@"1" writeToIRI: file1IRI];
[@"2" writeToIRI: file2IRI];
OTAssertEqualObjects([_fileManager subpathsOfDirectoryAtPath:
_testsDirectoryIRI.fileSystemRepresentation].sortedArray,
([OFArray arrayWithObjects:
_testsDirectoryIRI.fileSystemRepresentation,
subdirectory1IRI.fileSystemRepresentation,
file1IRI.fileSystemRepresentation,
subdirectory2IRI.fileSystemRepresentation,
file2IRI.fileSystemRepresentation,
_testFileIRI.fileSystemRepresentation, nil]));
}
- (void)testChangeCurrentDirectoryPath
{
OFString *oldDirectoryPath = _fileManager.currentDirectoryPath;
OTAssertFalse([_fileManager fileExistsAtPath: @"test.txt"]);
[_fileManager changeCurrentDirectoryPath:
_testsDirectoryIRI.fileSystemRepresentation];
@try {
/*
* We can't check whether currentDirectoryPath is
* _testsDirectoryIRI.fileSystemRepresentation because they
* could be different due to symlinks. Therefore check for
* presence of test.txt instead.
*/
OTAssertTrue([_fileManager fileExistsAtPath: @"test.txt"]);
} @finally {
[_fileManager changeCurrentDirectoryPath: oldDirectoryPath];
}
}
- (void)testCopyItemAtPathToPath
{
OFIRI *sourceIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"source"];
OFIRI *destinationIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"destination"];
OFIRI *subdirectory1IRI = [sourceIRI
IRIByAppendingPathComponent: @"a"];
OFIRI *subdirectory2IRI = [sourceIRI
IRIByAppendingPathComponent: @"b"];
OFIRI *file1IRI = [subdirectory1IRI
IRIByAppendingPathComponent: @"1.txt"];
OFIRI *file2IRI = [subdirectory2IRI
IRIByAppendingPathComponent: @"2.txt"];
[_fileManager createDirectoryAtIRI: subdirectory1IRI
createParents: true];
[_fileManager createDirectoryAtIRI: subdirectory2IRI
createParents: true];
[@"1" writeToIRI: file1IRI];
[@"2" writeToIRI: file2IRI];
subdirectory1IRI = [destinationIRI IRIByAppendingPathComponent: @"a"];
subdirectory2IRI = [destinationIRI IRIByAppendingPathComponent: @"b"];
file1IRI = [subdirectory1IRI IRIByAppendingPathComponent: @"1.txt"];
file2IRI = [subdirectory2IRI IRIByAppendingPathComponent: @"2.txt"];
OTAssertFalse([_fileManager directoryExistsAtIRI: subdirectory1IRI]);
OTAssertFalse([_fileManager directoryExistsAtIRI: subdirectory2IRI]);
OTAssertFalse([_fileManager fileExistsAtIRI: file1IRI]);
OTAssertFalse([_fileManager fileExistsAtIRI: file2IRI]);
[_fileManager copyItemAtPath: sourceIRI.fileSystemRepresentation
toPath: destinationIRI.fileSystemRepresentation];
OTAssertTrue([_fileManager directoryExistsAtIRI: subdirectory1IRI]);
OTAssertTrue([_fileManager directoryExistsAtIRI: subdirectory2IRI]);
OTAssertEqualObjects([OFString stringWithContentsOfIRI: file1IRI],
@"1");
OTAssertEqualObjects([OFString stringWithContentsOfIRI: file2IRI],
@"2");
}
- (void)testMoveItemAtPathToPath
{
OFIRI *sourceIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"source"];
OFIRI *destinationIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"destination"];
OFIRI *subdirectory1IRI = [sourceIRI
IRIByAppendingPathComponent: @"a"];
OFIRI *subdirectory2IRI = [sourceIRI
IRIByAppendingPathComponent: @"b"];
OFIRI *file1IRI = [subdirectory1IRI
IRIByAppendingPathComponent: @"1.txt"];
OFIRI *file2IRI = [subdirectory2IRI
IRIByAppendingPathComponent: @"2.txt"];
[_fileManager createDirectoryAtIRI: subdirectory1IRI
createParents: true];
[_fileManager createDirectoryAtIRI: subdirectory2IRI
createParents: true];
[@"1" writeToIRI: file1IRI];
[@"2" writeToIRI: file2IRI];
[_fileManager moveItemAtPath: sourceIRI.fileSystemRepresentation
toPath: destinationIRI.fileSystemRepresentation];
OTAssertFalse([_fileManager directoryExistsAtIRI: subdirectory1IRI]);
OTAssertFalse([_fileManager directoryExistsAtIRI: subdirectory2IRI]);
OTAssertFalse([_fileManager fileExistsAtIRI: file1IRI]);
OTAssertFalse([_fileManager fileExistsAtIRI: file2IRI]);
subdirectory1IRI = [destinationIRI IRIByAppendingPathComponent: @"a"];
subdirectory2IRI = [destinationIRI IRIByAppendingPathComponent: @"b"];
file1IRI = [subdirectory1IRI IRIByAppendingPathComponent: @"1.txt"];
file2IRI = [subdirectory2IRI IRIByAppendingPathComponent: @"2.txt"];
OTAssertTrue([_fileManager directoryExistsAtIRI: subdirectory1IRI]);
OTAssertTrue([_fileManager directoryExistsAtIRI: subdirectory2IRI]);
OTAssertEqualObjects([OFString stringWithContentsOfIRI: file1IRI],
@"1");
OTAssertEqualObjects([OFString stringWithContentsOfIRI: file2IRI],
@"2");
}
- (void)testRemoveItemAtPath
{
OFIRI *subdirectoryIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"dir"];
OFIRI *fileIRI = [subdirectoryIRI
IRIByAppendingPathComponent: @"file.txt"];
[_fileManager createDirectoryAtIRI: subdirectoryIRI];
[@"file" writeToIRI: fileIRI];
OTAssertTrue([_fileManager directoryExistsAtIRI: subdirectoryIRI]);
OTAssertTrue([_fileManager fileExistsAtIRI: fileIRI]);
[_fileManager removeItemAtPath:
subdirectoryIRI.fileSystemRepresentation];
OTAssertFalse([_fileManager fileExistsAtIRI: fileIRI]);
OTAssertFalse([_fileManager directoryExistsAtIRI: subdirectoryIRI]);
}
#ifdef OF_FILE_MANAGER_SUPPORTS_LINKS
- (void)testLinkItemAtPathToPath
{
OFIRI *sourceIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"source"];
OFIRI *destinationIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"destination"];
OFFileAttributes attributes;
[@"test" writeToIRI: sourceIRI];
[_fileManager linkItemAtPath: sourceIRI.fileSystemRepresentation
toPath: destinationIRI.fileSystemRepresentation];
attributes = [_fileManager attributesOfItemAtIRI: destinationIRI];
OTAssertEqual(attributes.fileType, OFFileTypeRegular);
OTAssertEqual(attributes.fileSize, 4);
OTAssertEqualObjects([OFString stringWithContentsOfIRI: destinationIRI],
@"test");
}
#endif
#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS
- (void)testCreateSymbolicLinkAtPathWithDestinationPath
{
OFIRI *sourceIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"source"];
OFIRI *destinationIRI = [_testsDirectoryIRI
IRIByAppendingPathComponent: @"destination"];
OFFileAttributes attributes;
[@"test" writeToIRI: sourceIRI];
@try {
OFString *sourcePath = sourceIRI.fileSystemRepresentation;
OFString *destinationPath =
destinationIRI.fileSystemRepresentation;
[_fileManager createSymbolicLinkAtPath: destinationPath
withDestinationPath: sourcePath];
} @catch (OFCreateSymbolicLinkFailedException *e) {
if (e.errNo == EPERM)
OTSkip(@"No permission to create symlink.\n"
@"On Windows, only the administrator can create "
@"symbolic links.");
else
@throw e;
}
attributes = [_fileManager attributesOfItemAtIRI: destinationIRI];
OTAssertEqual(attributes.fileType, OFFileTypeSymbolicLink);
OTAssertEqualObjects([OFString stringWithContentsOfIRI: destinationIRI],
@"test");
}
#endif
@end