// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // import XCTest @testable import AWSCloudWatchLoggingPlugin final class LogRotationTests: XCTestCase { var systemUnderTest: LogRotation! var directory: URL! var fileCountLimit = 5 var fileSizeLimitInBytes = 1024 override func setUp() async throws { directory = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) systemUnderTest = try LogRotation(directory: directory, fileSizeLimitInBytes: fileSizeLimitInBytes) } override func tearDown() async throws { systemUnderTest = nil try FileManager.default.removeItem(at: directory) directory = nil } /// Given: a log rotation /// When: the current log file is access /// Then: the log file default to ampliyf.0.log func testLogRotationDefaultState() throws { XCTAssertEqual(systemUnderTest.currentLogFile.available, systemUnderTest.currentLogFile.sizeLimitInBytes) XCTAssertEqual(systemUnderTest.currentLogFile.fileURL.lastPathComponent, "amplify.0.log") let contents = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(contents.map { $0.lastPathComponent }, [ "amplify.0.log" ]) } /// Given: a log rotation /// When: a rotation occurs /// Then: then a new rotated log file is created func testLogRotationCreatesNewFiles() throws { let originalContents = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(originalContents.map { $0.lastPathComponent }, [ "amplify.0.log" ]) systemUnderTest = try LogRotation(directory: directory, fileSizeLimitInBytes: fileSizeLimitInBytes) XCTAssertEqual(systemUnderTest.currentLogFile.fileURL.lastPathComponent, "amplify.1.log") try systemUnderTest.rotate() var rotatedContents = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(rotatedContents.map { $0.lastPathComponent }, [ "amplify.2.log", "amplify.1.log", "amplify.0.log", ]) try systemUnderTest.rotate() rotatedContents = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(rotatedContents.map { $0.lastPathComponent }, [ "amplify.2.log", "amplify.3.log", "amplify.1.log", "amplify.0.log", ]) try systemUnderTest.rotate() rotatedContents = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(rotatedContents.map { $0.lastPathComponent }, [ "amplify.4.log", "amplify.2.log", "amplify.3.log", "amplify.1.log", "amplify.0.log", ]) systemUnderTest = try LogRotation(directory: directory, fileSizeLimitInBytes: fileSizeLimitInBytes) XCTAssertEqual(systemUnderTest.currentLogFile.fileURL.lastPathComponent, "amplify.0.log") } /// Given: a log rotation /// When: rotation occurs to the max limit /// Then: the log rotation circles back to 0 func testLogRotationToMaxLimit() async throws { for _ in 0..<(fileCountLimit) { XCTAssertEqual(systemUnderTest.currentLogFile.available, systemUnderTest.currentLogFile.sizeLimitInBytes) try systemUnderTest.rotate() try await Task.sleep(seconds: 0.10) } let allFiles = try FileManager.default.contentsOfDirectory(at: directory, includingPropertiesForKeys: nil) XCTAssertEqual(Set(allFiles.map { $0.lastPathComponent }), Set([ "amplify.0.log", "amplify.1.log", "amplify.2.log", "amplify.3.log", "amplify.4.log" ])) } /// Given: a log rotation with existing under-utilized file /// When: rotation occurs /// Then: the log rotation rotates to the under-utilized log file func testLogRotationUseUnderutilizedLogFile() async throws { let bytes = (0..