diff --git a/.travis.yml b/.travis.yml index 073ed9c..3fc4d7e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: swift -osx_image: xcode10.2 +osx_image: xcode11.2 xcode_project: Logger.xcodeproj -script: xcodebuild test -project Logger.xcodeproj -scheme Logger -destination 'platform=iOS Simulator,name=iPhone XS,OS=12.2' +script: xcodebuild test -project Logger.xcodeproj -scheme Logger -destination 'platform=iOS Simulator,name=iPhone 11,OS=13.2' after_success: bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/Logger.xcodeproj/project.pbxproj b/Logger.xcodeproj/project.pbxproj index 317817a..220338c 100644 --- a/Logger.xcodeproj/project.pbxproj +++ b/Logger.xcodeproj/project.pbxproj @@ -370,7 +370,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -425,7 +425,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; diff --git a/Logger/Loggers/DiskLogger/DiskLogger.swift b/Logger/Loggers/DiskLogger/DiskLogger.swift index 9e14117..69e5320 100644 --- a/Logger/Loggers/DiskLogger/DiskLogger.swift +++ b/Logger/Loggers/DiskLogger/DiskLogger.swift @@ -46,6 +46,7 @@ protocol LogrotateFactory { } /// Logger that writes messages into the file at specified URL with log rotation support. +@available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) public final class DiskLogger: Logger { private let fileURL: URL @@ -97,7 +98,7 @@ public final class DiskLogger: Logger { try self.writeBuffer() } catch is SizeLimitedFileQuotaReached { - self.closeSizeLimitedFile() + try self.closeSizeLimitedFile() try self.rotateLogFiles() try self.openSizeLimitedFile() try self.writeBuffer() @@ -124,8 +125,8 @@ public final class DiskLogger: Logger { buffer.removeAll() } - private func closeSizeLimitedFile() { - self.sizeLimitedFile.synchronizeAndCloseFile() + private func closeSizeLimitedFile() throws { + try self.sizeLimitedFile.synchronizeAndCloseFile() self.sizeLimitedFile = nil } diff --git a/Logger/Loggers/DiskLogger/OSFileHandle.swift b/Logger/Loggers/DiskLogger/OSFileHandle.swift index dfe5bb9..34965bb 100644 --- a/Logger/Loggers/DiskLogger/OSFileHandle.swift +++ b/Logger/Loggers/DiskLogger/OSFileHandle.swift @@ -9,15 +9,45 @@ import Foundation protocol OSFileHandle { - func seekToEndOfFile() -> UInt64 - func swift_write(_ data: Data) throws - func synchronizeFile() - func closeFile() + func osSeekToEndOfFile() throws -> UInt64 + func osWrite(_ data: Data) throws + func osSynchronizeFile() throws + func osCloseFile() throws } extension FileHandle: OSFileHandle { - func swift_write(_ data: Data) throws { - try __write(data, error: ()) + func osSeekToEndOfFile() throws -> UInt64 { + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + var offsetInFile: UInt64 = 0 + try __seek(toEndReturningOffset:&offsetInFile) + return offsetInFile + } else { + fatalError() + } + } + + func osWrite(_ data: Data) throws { + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + try __write(data, error: ()) + } else { + fatalError() + } + } + + func osSynchronizeFile() throws { + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + try synchronize() + } else { + fatalError() + } + } + + func osCloseFile() throws { + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + try close() + } else { + fatalError() + } } } diff --git a/Logger/Loggers/DiskLogger/SizeLimitedFile.swift b/Logger/Loggers/DiskLogger/SizeLimitedFile.swift index d95e5f4..e7b89cb 100644 --- a/Logger/Loggers/DiskLogger/SizeLimitedFile.swift +++ b/Logger/Loggers/DiskLogger/SizeLimitedFile.swift @@ -42,7 +42,7 @@ protocol SizeLimitedFile { func write(_ data: Data) throws /// Writes all in-memory data to permanent storage and closes the file. - func synchronizeAndCloseFile() + func synchronizeAndCloseFile() throws } /// Allows writing to a file while respecting allowed size limit. @@ -61,7 +61,7 @@ final class SizeLimitedFileImpl { init(fileURL: URL, fileSizeLimit: UInt64, fileFactory: FileHandleFactory) throws { file = try fileFactory.makeInstance(forWritingTo: fileURL) self.sizeLimit = fileSizeLimit - currentSize = file.seekToEndOfFile() + currentSize = try file.osSeekToEndOfFile() } } @@ -72,12 +72,12 @@ extension SizeLimitedFileImpl: SizeLimitedFile { guard currentSize + dataSize <= sizeLimit else { throw SizeLimitedFileQuotaReached() } - try file.swift_write(data) + try file.osWrite(data) currentSize += dataSize } - func synchronizeAndCloseFile() { - file.synchronizeFile() - file.closeFile() + func synchronizeAndCloseFile() throws { + try file.osSynchronizeFile() + try file.osCloseFile() } } diff --git a/UnitTests/DiskLoggerTests.swift b/UnitTests/DiskLoggerTests.swift index 4a08210..3748884 100644 --- a/UnitTests/DiskLoggerTests.swift +++ b/UnitTests/DiskLoggerTests.swift @@ -30,89 +30,95 @@ class DiskLoggerTests: XCTestCase { let logURL = URL(fileURLWithPath: "/var/log/application.log") func testLoggingMessageToFile() { - let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") - expectation.expectedFulfillmentCount = 1 - - let fimeManager = FileManagerStub() - let sizeLimitedFileFactory = SizeLimitedFileMockFactory(writeCall: expectation) - let logrotateFactory = LogrotateMockFactory() - let logger = DiskLogger(fileURL: logURL, - fileSizeLimit: 1024, - rotations: 1, - fileManager: fimeManager, - sizeLimitedFileFactory: sizeLimitedFileFactory, - logrotateFactory: logrotateFactory) - - logger.log("message", level: .critical) - - let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) - XCTAssertEqual(result, .completed) - - XCTAssertEqual(sizeLimitedFileFactory.files.count, 1) - - // "2018-08-30 17:23:11.514 DiskLoggerTests:46 testWritingMessageToFile() a message\n" - let loggedMessage = String(decoding: sizeLimitedFileFactory.files[0].data, as: UTF8.self) - let expectedSuffix = " DiskLoggerTests:46 testLoggingMessageToFile() message\n" - - XCTAssertTrue(loggedMessage.hasSuffix(expectedSuffix)) + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") + expectation.expectedFulfillmentCount = 1 + + let fimeManager = FileManagerStub() + let sizeLimitedFileFactory = SizeLimitedFileMockFactory(writeCall: expectation) + let logrotateFactory = LogrotateMockFactory() + let logger = DiskLogger(fileURL: logURL, + fileSizeLimit: 1024, + rotations: 1, + fileManager: fimeManager, + sizeLimitedFileFactory: sizeLimitedFileFactory, + logrotateFactory: logrotateFactory) + + logger.log("message", level: .critical) + + let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) + XCTAssertEqual(result, .completed) + + XCTAssertEqual(sizeLimitedFileFactory.files.count, 1) + + // "2018-08-30 17:23:11.514 DiskLoggerTests:46 testWritingMessageToFile() a message\n" + let loggedMessage = String(decoding: sizeLimitedFileFactory.files[0].data, as: UTF8.self) + let expectedSuffix = " DiskLoggerTests:47 testLoggingMessageToFile() message\n" + + XCTAssertTrue(loggedMessage.hasSuffix(expectedSuffix)) + } } func testExceedingFileSizeLimit() { - let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") - expectation.expectedFulfillmentCount = 2 - - let fimeManager = FileManagerStub() - let sizeLimitedFileFactory = SizeLimitedFileMockFactory(writeCall: expectation) - let logrotateFactory = LogrotateMockFactory() - let logger = DiskLogger(fileURL: logURL, - fileSizeLimit: 91, - rotations: 1, - fileManager: fimeManager, - sizeLimitedFileFactory: sizeLimitedFileFactory, - logrotateFactory: logrotateFactory) - - logger.log("1st message", level: .critical) - logger.log("2st message", level: .critical) - - let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) - XCTAssertEqual(result, .completed) - - XCTAssertEqual(sizeLimitedFileFactory.files.count, 2) - - // "2018-08-31 18:29:34.748 DiskLoggerTests:75 testExceedingFileSizeLimit() 2st message\n" - let loggedMessage = String(decoding: sizeLimitedFileFactory.files[1].data, as: UTF8.self) - let expectedSuffix = " DiskLoggerTests:75 testExceedingFileSizeLimit() 2st message\n" - - XCTAssertTrue(loggedMessage.hasSuffix(expectedSuffix)) + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") + expectation.expectedFulfillmentCount = 2 + + let fimeManager = FileManagerStub() + let sizeLimitedFileFactory = SizeLimitedFileMockFactory(writeCall: expectation) + let logrotateFactory = LogrotateMockFactory() + let logger = DiskLogger(fileURL: logURL, + fileSizeLimit: 91, + rotations: 1, + fileManager: fimeManager, + sizeLimitedFileFactory: sizeLimitedFileFactory, + logrotateFactory: logrotateFactory) + + logger.log("1st message", level: .critical) + logger.log("2st message", level: .critical) + + let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) + XCTAssertEqual(result, .completed) + + XCTAssertEqual(sizeLimitedFileFactory.files.count, 2) + + // "2018-08-31 18:29:34.748 DiskLoggerTests:75 testExceedingFileSizeLimit() 2st message\n" + let loggedMessage = String(decoding: sizeLimitedFileFactory.files[1].data, as: UTF8.self) + let expectedSuffix = " DiskLoggerTests:78 testExceedingFileSizeLimit() 2st message\n" + + XCTAssertTrue(loggedMessage.hasSuffix(expectedSuffix)) + } } func testErrorDuringLogProcess() { - let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") - expectation.expectedFulfillmentCount = 2 - - let fimeManager = FileManagerStub() - let sizeLimitedFileFactory = UnwritableFileStubFactory(writeCall: expectation) - let logrotateFactory = LogrotateMockFactory() - let logger = DiskLogger(fileURL: logURL, - fileSizeLimit: 91, - rotations: 1, - fileManager: fimeManager, - sizeLimitedFileFactory: sizeLimitedFileFactory, - logrotateFactory: logrotateFactory) - - logger.log("1st message", level: .critical) - logger.log("2st message", level: .critical) - - let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) - XCTAssertEqual(result, .completed) - - XCTAssertEqual(sizeLimitedFileFactory.files.count, 1) - - // "2018-08-31 18:29:34.748 DiskLoggerTests:75 testExceedingFileSizeLimit() 2st message\n" - let loggedMessage = String(decoding: sizeLimitedFileFactory.files[0].data, as: UTF8.self) - let expectedOccurence = " WriteFailed()" - - XCTAssertTrue(loggedMessage.contains(expectedOccurence)) + if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) { + let expectation = XCTestExpectation(description: "write(_:) was called on SizeLimitedFile") + expectation.expectedFulfillmentCount = 2 + + let fimeManager = FileManagerStub() + let sizeLimitedFileFactory = UnwritableFileStubFactory(writeCall: expectation) + let logrotateFactory = LogrotateMockFactory() + let logger = DiskLogger(fileURL: logURL, + fileSizeLimit: 91, + rotations: 1, + fileManager: fimeManager, + sizeLimitedFileFactory: sizeLimitedFileFactory, + logrotateFactory: logrotateFactory) + + logger.log("1st message", level: .critical) + logger.log("2st message", level: .critical) + + let result = XCTWaiter().wait(for: [expectation], timeout: 1.0) + XCTAssertEqual(result, .completed) + + XCTAssertEqual(sizeLimitedFileFactory.files.count, 1) + + // "2018-08-31 18:29:34.748 DiskLoggerTests:75 testExceedingFileSizeLimit() 2st message\n" + let loggedMessage = String(decoding: sizeLimitedFileFactory.files[0].data, as: UTF8.self) + let expectedOccurence = " WriteFailed()" + + XCTAssertTrue(loggedMessage.contains(expectedOccurence)) + } } } diff --git a/UnitTests/SizeLimitedFileTests.swift b/UnitTests/SizeLimitedFileTests.swift index a51f3fc..83db64b 100644 --- a/UnitTests/SizeLimitedFileTests.swift +++ b/UnitTests/SizeLimitedFileTests.swift @@ -60,7 +60,7 @@ class SizeLimitedFileTests: XCTestCase { func testSynchronizingAndClosingFile() throws { let factory = FileMockFactory() let writer = try SizeLimitedFileImpl(fileURL: logURL, fileSizeLimit: 1, fileFactory: factory) - writer.synchronizeAndCloseFile() + try writer.synchronizeAndCloseFile() XCTAssertTrue(factory.mock.synchronizeFileCallCount == 1 && factory.mock.closeFileCallCount == 1) } } @@ -89,19 +89,19 @@ private class FileMock: OSFileHandle { private(set) var synchronizeFileCallCount = 0 private(set) var closeFileCallCount = 0 - func seekToEndOfFile() -> UInt64 { + func osSeekToEndOfFile() throws -> UInt64 { return 0 } - func swift_write(_ data: Data) throws { + func osWrite(_ data: Data) throws { self.writtenData.append(data) } - func synchronizeFile() { + func osSynchronizeFile() throws { synchronizeFileCallCount += 1 } - func closeFile() { + func osCloseFile() throws { closeFileCallCount += 1 } }