@@ -4,14 +4,16 @@ import XCTest
44
55final class TestLogOutput {
66
7- private let queue = DispatchQueue ( label: " TestLogOutput " , attributes: . concurrent)
8-
7+ private let logsToConsole : Bool
98 private var _loggedMessages : [ String ] = [ ]
10-
11- var logsToConsole : Bool = true
9+ private let lock = NSLock ( )
10+
11+ init ( logsToConsole: Bool = true ) {
12+ self . logsToConsole = logsToConsole
13+ }
1214
1315 var loggedMessages : [ String ] {
14- queue . sync {
16+ lock . synchronized {
1517 return _loggedMessages
1618 }
1719 }
@@ -20,21 +22,116 @@ final class TestLogOutput {
2022 if logsToConsole {
2123 print ( message)
2224 }
23- queue . async ( flags : . barrier ) {
25+ lock . synchronized {
2426 self . _loggedMessages. append ( message)
2527 }
2628 }
2729}
2830
2931class TestLogOutPutTests : XCTestCase {
3032
31- func testLoggingFromMulitpleThreads( ) {
32- let sut = TestLogOutput ( )
33- sut. logsToConsole = false
34- testConcurrentModifications ( writeWork: { i in
35- sut. log ( " Some message \( i) " )
36- } , readWork: {
37- XCTAssertNotNil ( sut. loggedMessages)
38- } )
33+ func testLoggingFromMultipleThreads( ) {
34+ // Arrange
35+ let sut = TestLogOutput ( logsToConsole: false )
36+
37+ let queue = DispatchQueue ( label: " testLoggingFromMultipleThreads " , attributes: [ . concurrent] )
38+ let expectation = expectation ( description: " Logging from multiple threads " )
39+
40+ let iterations = 100
41+ expectation. expectedFulfillmentCount = iterations * 2
42+
43+ // Act
44+ for i in 0 ..< iterations {
45+
46+ queue. async {
47+ sut. log ( " Message \( i) " )
48+ expectation. fulfill ( )
49+ }
50+
51+ queue. async {
52+ XCTAssertNotNil ( sut. loggedMessages)
53+ expectation. fulfill ( )
54+ }
55+ }
56+
57+ wait ( for: [ expectation] , timeout: 5.0 )
58+
59+ // Assert
60+ XCTAssertEqual ( sut. loggedMessages. count, iterations)
61+ }
62+
63+ func testInitialState_LoggedMessagesIsEmpty( ) {
64+ // Arrange
65+ let sut = TestLogOutput ( logsToConsole: false )
66+
67+ // Act
68+ let messages = sut. loggedMessages
69+
70+ // Assert
71+ XCTAssertTrue ( messages. isEmpty)
72+ XCTAssertEqual ( messages. count, 0 )
73+ }
74+
75+ func testLogSingleMessage_MessageIsStored( ) {
76+ // Arrange
77+ let sut = TestLogOutput ( logsToConsole: false )
78+ let testMessage = " Test message "
79+
80+ // Act
81+ sut. log ( testMessage)
82+
83+ // Assert
84+ let messages = sut. loggedMessages
85+ XCTAssertEqual ( messages. count, 1 )
86+ XCTAssertEqual ( messages. first, testMessage)
87+ }
88+
89+ func testLogMultipleMessages_AllMessagesAreStoredInOrder( ) {
90+ // Arrange
91+ let sut = TestLogOutput ( logsToConsole: false )
92+ let testMessages = [ " First message " , " Second message " , " Third message " ]
93+
94+ // Act
95+ for message in testMessages {
96+ sut. log ( message)
97+ }
98+
99+ // Assert
100+ let messages = sut. loggedMessages
101+ XCTAssertEqual ( messages. count, testMessages. count)
102+ XCTAssertEqual ( messages, testMessages)
103+ }
104+
105+ func testLogEmptyString_EmptyStringIsStored( ) {
106+ // Arrange
107+ let sut = TestLogOutput ( logsToConsole: false )
108+ let emptyMessage = " "
109+
110+ // Act
111+ sut. log ( emptyMessage)
112+
113+ // Assert
114+ let messages = sut. loggedMessages
115+ XCTAssertEqual ( messages. count, 1 )
116+ XCTAssertEqual ( messages. first, emptyMessage)
117+ }
118+
119+ func testLogAfterMultipleReads_MessagesAreConsistent( ) {
120+ // Arrange
121+ let sut = TestLogOutput ( logsToConsole: false )
122+ let firstMessage = " First message "
123+ let secondMessage = " Second message "
124+
125+ // Act
126+ sut. log ( firstMessage)
127+ let messagesAfterFirst = sut. loggedMessages
128+ sut. log ( secondMessage)
129+ let messagesAfterSecond = sut. loggedMessages
130+
131+ // Assert
132+ XCTAssertEqual ( messagesAfterFirst. count, 1 )
133+ XCTAssertEqual ( messagesAfterFirst. first, firstMessage)
134+ XCTAssertEqual ( messagesAfterSecond. count, 2 )
135+ XCTAssertEqual ( messagesAfterSecond, [ firstMessage, secondMessage] )
39136 }
40137}
0 commit comments