Skip to content

Commit 0375d17

Browse files
authored
Shuffle around the AsyncMessageSequence tests and add some. (#2002)
Reorder some of the tests to easily only exclude the ones that need the Foundation support. Also bring over some tests that the other class has that weren't done here.
1 parent 8697014 commit 0375d17

File tree

1 file changed

+142
-107
lines changed

1 file changed

+142
-107
lines changed

Tests/SwiftProtobufTests/Test_AsyncMessageSequence.swift

Lines changed: 142 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,151 @@
1313
///
1414
// -----------------------------------------------------------------------------
1515

16-
// We are disabling these tests, because they use
17-
// APIs gated behind the trait.
18-
#if BinaryDelimitedStreams
19-
2016
import Foundation
2117
import SwiftProtobuf
2218
import XCTest
2319

2420
final class Test_AsyncMessageSequence: XCTestCase {
2521

22+
// Stream with a single zero varint
23+
func testStreamZeroVarintOnly() async throws {
24+
let seq = asyncByteStream(bytes: [0])
25+
let decoded = seq.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
26+
27+
var count = 0
28+
for try await message in decoded {
29+
XCTAssertEqual(message, SwiftProtoTesting_TestAllTypes())
30+
count += 1
31+
}
32+
XCTAssertEqual(count, 1)
33+
}
34+
35+
// Empty stream with zero bytes
36+
func testEmptyStream() async throws {
37+
let asyncBytes = asyncByteStream(bytes: [])
38+
let messages = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
39+
for try await _ in messages {
40+
XCTFail("Shouldn't have returned a value for an empty stream.")
41+
}
42+
}
43+
44+
// A stream with legal non-zero varint but no message
45+
func testNonZeroVarintNoMessage() async throws {
46+
let asyncBytes = asyncByteStream(bytes: [0x96, 0x01])
47+
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
48+
var truncatedThrown = false
49+
do {
50+
for try await _ in decoded {
51+
XCTFail("Shouldn't have returned a value for truncated stream.")
52+
}
53+
} catch {
54+
if error as! BinaryDelimited.Error == .truncated {
55+
truncatedThrown = true
56+
}
57+
}
58+
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobufError.BinaryDelimited.truncated")
59+
}
60+
61+
// The data stops before the indicated payload length.
62+
func testNotEnoughDataForMessage() async throws {
63+
let asyncBytes = asyncByteStream(bytes: [0x96, 0x01, 0x01, 0x02, 0x03])
64+
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
65+
var truncatedThrown = false
66+
do {
67+
for try await _ in decoded {
68+
XCTFail("Shouldn't have returned a value for truncated stream.")
69+
}
70+
} catch {
71+
if error as! BinaryDelimited.Error == .truncated {
72+
truncatedThrown = true
73+
}
74+
}
75+
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobufError.BinaryDelimited.truncated")
76+
}
77+
78+
// Single varint describing a 2GB message
79+
func testTooLarge() async throws {
80+
let asyncBytes = asyncByteStream(bytes: [128, 128, 128, 128, 8])
81+
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
82+
do {
83+
for try await _ in decoded {
84+
XCTFail("Shouldn't have returned a value for an invalid stream.")
85+
}
86+
} catch {
87+
XCTAssertTrue(self.isSwiftProtobufErrorEqual(error as! SwiftProtobufError, .BinaryDecoding.tooLarge()))
88+
}
89+
}
90+
91+
// Stream with truncated varint
92+
func testTruncatedVarint() async throws {
93+
let asyncBytes = asyncByteStream(bytes: [192])
94+
95+
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
96+
var truncatedThrown = false
97+
do {
98+
for try await _ in decoded {
99+
XCTFail("Shouldn't have returned a value for an empty stream.")
100+
}
101+
} catch {
102+
if error as! BinaryDelimited.Error == .truncated {
103+
truncatedThrown = true
104+
}
105+
}
106+
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobufError.BinaryDelimited.truncated")
107+
}
108+
109+
// Test with an over encoded varint value.
110+
func testOverEncodedVarint() async throws {
111+
let asyncBytes = asyncByteStream(bytes: [
112+
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x08,
113+
])
114+
115+
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
116+
do {
117+
for try await _ in decoded {
118+
XCTFail("Shouldn't have returned a value for an empty stream.")
119+
}
120+
} catch {
121+
XCTAssertTrue(
122+
self.isSwiftProtobufErrorEqual(error as! SwiftProtobufError, .BinaryStreamDecoding.malformedLength())
123+
)
124+
}
125+
}
126+
127+
// Slow test case found by oss-fuzz: 1 million zero-sized messages
128+
// A similar test with BinaryDelimited is about 4x faster, showing
129+
// that we have some room for improvement here.
130+
// (Note this currently only tests 100,000 zero-sized messages,
131+
// but the constant below is easy to edit if you want to experiment.)
132+
func testLargeExample() async throws {
133+
let messageCount = 100_000
134+
let bytes = [UInt8](repeating: 0, count: messageCount)
135+
let byteStream = asyncByteStream(bytes: bytes)
136+
let decodedStream = byteStream.binaryProtobufDelimitedMessages(
137+
of: SwiftProtoTesting_TestAllTypes.self,
138+
extensions: SwiftProtoTesting_Fuzz_FuzzTesting_Extensions
139+
)
140+
var count = 0
141+
for try await message in decodedStream {
142+
XCTAssertEqual(message, SwiftProtoTesting_TestAllTypes())
143+
count += 1
144+
}
145+
XCTAssertEqual(count, messageCount)
146+
}
147+
148+
fileprivate func asyncByteStream(bytes: [UInt8]) -> AsyncStream<UInt8> {
149+
AsyncStream(UInt8.self) { continuation in
150+
for byte in bytes {
151+
continuation.yield(byte)
152+
}
153+
continuation.finish()
154+
}
155+
}
156+
157+
// These tests all make use of other runtime apis gated against the trait, so the tests are also
158+
// gated.
159+
#if BinaryDelimitedStreams
160+
26161
// Decode a valid binary delimited stream
27162
func testValidSequence() async throws {
28163
let expected: [Int32] = Array(1...5)
@@ -98,76 +233,6 @@ final class Test_AsyncMessageSequence: XCTestCase {
98233
XCTAssertEqual(count, 5, "Expected five messages with default fields.")
99234
}
100235

101-
// Stream with a single zero varint
102-
func testStreamZeroVarintOnly() async throws {
103-
let seq = asyncByteStream(bytes: [0])
104-
let decoded = seq.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
105-
106-
var count = 0
107-
for try await message in decoded {
108-
XCTAssertEqual(message, SwiftProtoTesting_TestAllTypes())
109-
count += 1
110-
}
111-
XCTAssertEqual(count, 1)
112-
}
113-
114-
// Empty stream with zero bytes
115-
func testEmptyStream() async throws {
116-
let asyncBytes = asyncByteStream(bytes: [])
117-
let messages = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
118-
for try await _ in messages {
119-
XCTFail("Shouldn't have returned a value for an empty stream.")
120-
}
121-
}
122-
123-
// A stream with legal non-zero varint but no message
124-
func testNonZeroVarintNoMessage() async throws {
125-
let asyncBytes = asyncByteStream(bytes: [0x96, 0x01])
126-
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
127-
var truncatedThrown = false
128-
do {
129-
for try await _ in decoded {
130-
XCTFail("Shouldn't have returned a value for an empty stream.")
131-
}
132-
} catch {
133-
if error as! BinaryDelimited.Error == .truncated {
134-
truncatedThrown = true
135-
}
136-
}
137-
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobufError.BinaryStreamDecoding.truncated")
138-
}
139-
140-
// Single varint describing a 2GB message
141-
func testTooLarge() async throws {
142-
let asyncBytes = asyncByteStream(bytes: [128, 128, 128, 128, 8])
143-
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
144-
do {
145-
for try await _ in decoded {
146-
XCTFail("Shouldn't have returned a value for an invalid stream.")
147-
}
148-
} catch {
149-
XCTAssertTrue(self.isSwiftProtobufErrorEqual(error as! SwiftProtobufError, .BinaryDecoding.tooLarge()))
150-
}
151-
}
152-
153-
// Stream with truncated varint
154-
func testTruncatedVarint() async throws {
155-
let asyncBytes = asyncByteStream(bytes: [192])
156-
157-
let decoded = asyncBytes.binaryProtobufDelimitedMessages(of: SwiftProtoTesting_TestAllTypes.self)
158-
var truncatedThrown = false
159-
do {
160-
for try await _ in decoded {
161-
XCTFail("Shouldn't have returned a value for an empty stream.")
162-
}
163-
} catch {
164-
if error as! BinaryDelimited.Error == .truncated {
165-
truncatedThrown = true
166-
}
167-
}
168-
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobufError.BinaryStreamDecoding.truncated")
169-
}
170-
171236
// Stream with a valid varint and message, but the following varint is truncated
172237
func testValidMessageThenTruncatedVarint() async throws {
173238
var truncatedThrown = false
@@ -200,37 +265,7 @@ final class Test_AsyncMessageSequence: XCTestCase {
200265
truncatedThrown = true
201266
}
202267
}
203-
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobuf.BinaryStreamDecoding.truncated")
204-
}
205-
206-
// Slow test case found by oss-fuzz: 1 million zero-sized messages
207-
// A similar test with BinaryDelimited is about 4x faster, showing
208-
// that we have some room for improvement here.
209-
// (Note this currently only tests 100,000 zero-sized messages,
210-
// but the constant below is easy to edit if you want to experiment.)
211-
func testLargeExample() async throws {
212-
let messageCount = 100_000
213-
let bytes = [UInt8](repeating: 0, count: messageCount)
214-
let byteStream = asyncByteStream(bytes: bytes)
215-
let decodedStream = byteStream.binaryProtobufDelimitedMessages(
216-
of: SwiftProtoTesting_TestAllTypes.self,
217-
extensions: SwiftProtoTesting_Fuzz_FuzzTesting_Extensions
218-
)
219-
var count = 0
220-
for try await message in decodedStream {
221-
XCTAssertEqual(message, SwiftProtoTesting_TestAllTypes())
222-
count += 1
223-
}
224-
XCTAssertEqual(count, messageCount)
225-
}
226-
227-
fileprivate func asyncByteStream(bytes: [UInt8]) -> AsyncStream<UInt8> {
228-
AsyncStream(UInt8.self) { continuation in
229-
for byte in bytes {
230-
continuation.yield(byte)
231-
}
232-
continuation.finish()
233-
}
268+
XCTAssertTrue(truncatedThrown, "Should throw a SwiftProtobuf.BinaryDelimited.truncated")
234269
}
235270

236271
fileprivate func serializedMessageData(messages: [any Message]) throws -> [UInt8] {
@@ -244,6 +279,6 @@ final class Test_AsyncMessageSequence: XCTestCase {
244279
let data = Data(referencing: nsData)
245280
return [UInt8](data)
246281
}
247-
}
282+
#endif // BinaryDelimitedStreams
248283

249-
#endif
284+
}

0 commit comments

Comments
 (0)