Skip to content

Commit 5720178

Browse files
test: Add InvocationTests (#5553)
Add tests for the test util class Invocations. We need to ensure our test code works correctly for a deterministic test suite.
1 parent 6d9f2c8 commit 5720178

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

Sentry.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
62E2119A2DAE99FC007D7262 /* SentryAsyncSafeLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E211992DAE99FC007D7262 /* SentryAsyncSafeLog.m */; };
144144
62E300942D5202890037AA3F /* SentryExceptionCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E300932D5202830037AA3F /* SentryExceptionCodable.swift */; };
145145
62E5325B2DEEC862000B2DD5 /* TestCurrentDateProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 624729172DE5980500DFEE00 /* TestCurrentDateProviderTests.swift */; };
146+
62E75EB92E152953002EC91B /* InvocationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E75EB82E152953002EC91B /* InvocationsTests.swift */; };
146147
62EF86A12C626D39004E058B /* SentryANRTrackerV2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621AE74E2C626CF70012E730 /* SentryANRTrackerV2Tests.swift */; };
147148
62F05D2B2C0DB1F100916E3F /* SentryLogTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F05D2A2C0DB1F100916E3F /* SentryLogTestHelper.m */; };
148149
62F226B729A37C120038080D /* SentryBooleanSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F226B629A37C120038080D /* SentryBooleanSerialization.m */; };
@@ -1305,6 +1306,7 @@
13051306
62E081AA29ED4322000F69FC /* SentryBreadcrumbTestDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBreadcrumbTestDelegate.swift; sourceTree = "<group>"; };
13061307
62E211992DAE99FC007D7262 /* SentryAsyncSafeLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncSafeLog.m; sourceTree = "<group>"; };
13071308
62E300932D5202830037AA3F /* SentryExceptionCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExceptionCodable.swift; sourceTree = "<group>"; };
1309+
62E75EB82E152953002EC91B /* InvocationsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvocationsTests.swift; sourceTree = "<group>"; };
13081310
62F05D292C0DB1C800916E3F /* SentryLogTestHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryLogTestHelper.h; sourceTree = "<group>"; };
13091311
62F05D2A2C0DB1F100916E3F /* SentryLogTestHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryLogTestHelper.m; sourceTree = "<group>"; };
13101312
62F226B629A37C120038080D /* SentryBooleanSerialization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBooleanSerialization.m; sourceTree = "<group>"; };
@@ -4119,6 +4121,7 @@
41194121
D44B16712DE464A9006DBDB3 /* TestDispatchFactoryTests.swift */,
41204122
D4CBA2512DE06D1600581618 /* TestConstantTests.swift */,
41214123
D43B0E5F2DE7416600EE3759 /* TestFileManagerTests.swift */,
4124+
62E75EB82E152953002EC91B /* InvocationsTests.swift */,
41224125
);
41234126
path = SentryTestUtilsTests;
41244127
sourceTree = "<group>";
@@ -6029,6 +6032,7 @@
60296032
D43B0E602DE7416900EE3759 /* TestFileManagerTests.swift in Sources */,
60306033
D44B16722DE464AD006DBDB3 /* TestDispatchFactoryTests.swift in Sources */,
60316034
D4EE12D22DE9AC3800385BAF /* TestNSNotificationCenterWrapperTests.swift in Sources */,
6035+
62E75EB92E152953002EC91B /* InvocationsTests.swift in Sources */,
60326036
D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */,
60336037
);
60346038
runOnlyForDeploymentPostprocessing = 0;
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
@_spi(Private) import SentryTestUtils
2+
import XCTest
3+
4+
final class InvocationsTests: XCTestCase {
5+
6+
func testInitialStateIsEmpty() throws {
7+
// Arrange & Act
8+
let sut = Invocations<String>()
9+
10+
// Assert
11+
XCTAssertTrue(sut.isEmpty)
12+
XCTAssertEqual(sut.count, 0)
13+
XCTAssertTrue(sut.invocations.isEmpty)
14+
XCTAssertNil(sut.first)
15+
XCTAssertNil(sut.last)
16+
}
17+
18+
func testRecordSingleInvocation() throws {
19+
// Arrange
20+
let sut = Invocations<String>()
21+
let testValue = "test"
22+
23+
// Act
24+
sut.record(testValue)
25+
26+
// Assert
27+
XCTAssertFalse(sut.isEmpty)
28+
XCTAssertEqual(sut.count, 1)
29+
XCTAssertEqual(sut.invocations.count, 1)
30+
XCTAssertEqual(sut.first, testValue)
31+
XCTAssertEqual(sut.last, testValue)
32+
XCTAssertEqual(sut.invocations[0], testValue)
33+
}
34+
35+
func testRecordMultipleInvocations() throws {
36+
// Arrange
37+
let sut = Invocations<Int>()
38+
let values = [1, 2, 3]
39+
40+
// Act
41+
for value in values {
42+
sut.record(value)
43+
}
44+
45+
// Assert
46+
XCTAssertFalse(sut.isEmpty)
47+
XCTAssertEqual(sut.count, 3)
48+
XCTAssertEqual(sut.invocations, values)
49+
XCTAssertEqual(sut.first, 1)
50+
XCTAssertEqual(sut.last, 3)
51+
}
52+
53+
func testGetWithValidIndex() throws {
54+
// Arrange
55+
let sut = Invocations<String>()
56+
let values = ["first", "second", "third"]
57+
values.forEach { sut.record($0) }
58+
59+
// Act
60+
let result = sut.get(1)
61+
62+
// Assert
63+
XCTAssertEqual(result, "second")
64+
}
65+
66+
func testGetWithInvalidIndex() throws {
67+
// Arrange
68+
let sut = Invocations<String>()
69+
sut.record("test")
70+
71+
// Act
72+
let result = sut.get(5)
73+
74+
// Assert
75+
XCTAssertNil(result)
76+
}
77+
78+
func testGetWithNegativeIndex() throws {
79+
// Arrange
80+
let sut = Invocations<String>()
81+
sut.record("test")
82+
83+
// Act
84+
let result = sut.get(-1)
85+
86+
// Assert
87+
XCTAssertNil(result)
88+
}
89+
90+
func testGetFromEmptyInvocations() throws {
91+
// Arrange
92+
let sut = Invocations<String>()
93+
94+
// Act
95+
let result = sut.get(0)
96+
97+
// Assert
98+
XCTAssertNil(result)
99+
}
100+
101+
func testRemoveAllFromEmptyInvocations() throws {
102+
// Arrange
103+
let sut = Invocations<String>()
104+
105+
// Act
106+
sut.removeAll()
107+
108+
// Assert
109+
XCTAssertTrue(sut.isEmpty)
110+
XCTAssertEqual(sut.count, 0)
111+
XCTAssertTrue(sut.invocations.isEmpty)
112+
}
113+
114+
func testRemoveAllFromPopulatedInvocations() throws {
115+
// Arrange
116+
let sut = Invocations<String>()
117+
sut.record("test1")
118+
sut.record("test2")
119+
120+
// Act
121+
sut.removeAll()
122+
123+
// Assert
124+
XCTAssertTrue(sut.isEmpty)
125+
XCTAssertEqual(sut.count, 0)
126+
XCTAssertTrue(sut.invocations.isEmpty)
127+
XCTAssertNil(sut.first)
128+
XCTAssertNil(sut.last)
129+
}
130+
131+
func testFirstAndLastWithSingleInvocation() throws {
132+
// Arrange
133+
let sut = Invocations<String>()
134+
let testValue = "single"
135+
136+
// Act
137+
sut.record(testValue)
138+
139+
// Assert
140+
XCTAssertEqual(sut.first, testValue)
141+
XCTAssertEqual(sut.last, testValue)
142+
XCTAssertEqual(sut.first, sut.last)
143+
}
144+
145+
func testFromMultipleThreads() throws {
146+
147+
// Arrange
148+
let sut = Invocations<Int>()
149+
150+
let dispatchQueue = DispatchQueue(label: "InvocationsTests", attributes: [.concurrent, .initiallyInactive])
151+
152+
let expectation = self.expectation(description: "testFromMultipleThreads")
153+
expectation.expectedFulfillmentCount = 1_000
154+
155+
// Act
156+
for i in 0..<1_000 {
157+
dispatchQueue.async {
158+
sut.record(i)
159+
160+
XCTAssertTrue(sut.invocations.contains(i))
161+
XCTAssertNotNil(sut.invocations)
162+
XCTAssertNotNil(sut.count)
163+
XCTAssertNotNil(sut.first)
164+
XCTAssertNotNil(sut.last)
165+
XCTAssertFalse(sut.isEmpty)
166+
167+
expectation.fulfill()
168+
}
169+
}
170+
171+
dispatchQueue.activate()
172+
wait(for: [expectation], timeout: 5.0)
173+
174+
// Assert
175+
XCTAssertEqual(sut.invocations.count, 1_000)
176+
}
177+
178+
func testRemoveAllAfterAddingRecords() throws {
179+
180+
// Arrange
181+
let sut = Invocations<Void>()
182+
183+
let dispatchQueue = DispatchQueue(label: "InvocationsTests", attributes: [.concurrent, .initiallyInactive])
184+
185+
let expectation = self.expectation(description: "testFromMultipleThreads")
186+
expectation.expectedFulfillmentCount = 1_000
187+
188+
// Act
189+
for _ in 0..<1_000 {
190+
dispatchQueue.async {
191+
// Act
192+
for _ in 0..<10 {
193+
sut.record(Void())
194+
}
195+
196+
sut.removeAll()
197+
198+
expectation.fulfill()
199+
}
200+
}
201+
202+
dispatchQueue.activate()
203+
204+
wait(for: [expectation], timeout: 5.0)
205+
206+
// Assert
207+
XCTAssertTrue(sut.invocations.isEmpty)
208+
}
209+
}

0 commit comments

Comments
 (0)