Revision control

1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
* License, v. 2.0. If a copy of the MPL was not distributed with this
3
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
import Foundation
6
import XCTest
7
import XCGLogger
8
@testable import Shared
9
10
class RollingFileLoggerTests: XCTestCase {
11
var logger: RollingFileLogger!
12
var logDir: String = ""
13
var sizeLimit: Int = 5000
14
15
fileprivate lazy var formatter: DateFormatter = {
16
let formatter = DateFormatter()
17
formatter.dateFormat = "yyyyMMdd'T'HHmmssZ"
18
return formatter
19
}()
20
21
override func setUp() {
22
super.setUp()
23
logDir = (NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first!) + "/Logs"
24
do {
25
try FileManager.default.createDirectory(atPath: logDir, withIntermediateDirectories: false, attributes: nil)
26
} catch _ {
27
}
28
logger = RollingFileLogger(filenameRoot: "test", logDirectoryPath: logDir, sizeLimit: Int64(sizeLimit))
29
}
30
31
func testNewLogCreatesLogFileWithTimestamp() {
32
let date = Date()
33
let expected = "test.\(formatter.string(from: date)).log"
34
let expectedPath = "\(logDir)/\(expected)"
35
logger.newLogWithDate(date)
36
XCTAssertTrue(FileManager.default.fileExists(atPath: expectedPath), "Log file should exist")
37
38
let testMessage = "Logging some text"
39
logger.info(testMessage)
40
let logData = try? Data(contentsOf: URL(fileURLWithPath: expectedPath))
41
XCTAssertNotNil(logData, "Log data should not be nil")
42
let logString = NSString(data: logData!, encoding: String.Encoding.utf8.rawValue)
43
XCTAssertTrue(logString!.contains(testMessage), "Log should contain our test message that we wrote")
44
}
45
46
func testNewLogDeletesPreviousLogIfItsTooLarge() {
47
let manager = FileManager.default
48
let dirURL = URL(fileURLWithPath: logDir)
49
let prefix = "test"
50
let expectedPath = createNewLogFileWithSize(sizeLimit + 1)
51
sleep(1) // Wait a second to ensure written file is closed before checking its size
52
53
let directorySize = try! manager.getAllocatedSizeOfDirectoryAtURL(dirURL, forFilesPrefixedWith: prefix)
54
55
// Pre-condition: Folder needs to be larger than the size limit
56
XCTAssertGreaterThan(directorySize, Int64(sizeLimit), "Log folder should be larger than size limit")
57
58
let exceedsSmaller = try! manager.allocatedSizeOfDirectoryAtURL(dirURL, forFilesPrefixedWith: prefix, isLargerThanBytes: directorySize - 1)
59
let doesNotExceedLarger = try! manager.allocatedSizeOfDirectoryAtURL(dirURL, forFilesPrefixedWith: prefix, isLargerThanBytes: Int64(sizeLimit + 2))
60
XCTAssertTrue(exceedsSmaller)
61
XCTAssertTrue(doesNotExceedLarger)
62
63
let newDate = Date().addingTimeInterval(60*60) // Create a log file using a date an hour ahead
64
let newExpected = "\(prefix).\(formatter.string(from: newDate)).log"
65
let newExpectedPath = "\(logDir)/\(newExpected)"
66
logger.newLogWithDate(newDate)
67
68
XCTAssertTrue(manager.fileExists(atPath: newExpectedPath), "New log file should exist")
69
XCTAssertTrue(manager.fileExists(atPath: expectedPath), "Old log file exists until pruned")
70
logger.deleteOldLogsDownToSizeLimit()
71
XCTAssertFalse(manager.fileExists(atPath: expectedPath), "Old log file should NOT exist")
72
}
73
74
func testNewLogDeletesOldestLogFileToMakeRoomForNewFile() {
75
let manager = FileManager.default
76
let dirURL = URL(fileURLWithPath: logDir)
77
let prefix = "test"
78
79
// Create 5 log files with spread out over 5 hours and reorder paths so oldest is first
80
let logFilePaths = [0, 1, 2, 3, 4].map { self.createNewLogFileWithSize(200, withDate: Date().addingTimeInterval(60 * 60 * $0)) }
81
.sorted { $0 < $1 }
82
83
let directorySize = try! manager.getAllocatedSizeOfDirectoryAtURL(dirURL, forFilesPrefixedWith: prefix)
84
85
// Pre-condition: Folder needs to be larger than the size limit
86
XCTAssertGreaterThan(directorySize, Int64(sizeLimit), "Log folder should be larger than size limit")
87
88
let newDate = Date().addingTimeInterval(60*60*5) // Create a log file using a date an hour ahead
89
let newExpected = "\(prefix).\(formatter.string(from: newDate)).log"
90
let newExpectedPath = "\(logDir)/\(newExpected)"
91
logger.newLogWithDate(newDate)
92
93
XCTAssertTrue(manager.fileExists(atPath: newExpectedPath), "New log file should exist")
94
XCTAssertTrue(manager.fileExists(atPath: logFilePaths.first!), "Old log file exists until pruned")
95
logger.deleteOldLogsDownToSizeLimit()
96
XCTAssertFalse(manager.fileExists(atPath: logFilePaths.first!), "Oldest log file should NOT exist")
97
}
98
99
/**
100
Create a log file using the test logger and returns the path to that log file
101
102
- parameter size: Size to make the log file
103
104
- returns: Path to log file
105
*/
106
fileprivate func createNewLogFileWithSize(_ size: Int, withDate date: Date = Date()) -> String {
107
let expected = "test.\(formatter.string(from: date)).log"
108
let expectedPath = "\(logDir)/\(expected)"
109
logger.newLogWithDate(date)
110
XCTAssertTrue(FileManager.default.fileExists(atPath: expectedPath), "Log file should exist")
111
112
let logFileHandle = FileHandle(forWritingAtPath: expectedPath)
113
XCTAssertNotNil(logFileHandle, "File should exist")
114
let garbageBytes = malloc(size)
115
let blankData = Data(bytes: garbageBytes!, count: size)
116
logFileHandle!.write(blankData)
117
logFileHandle!.closeFile()
118
return expectedPath
119
}
120
}