1313///
1414// -----------------------------------------------------------------------------
1515
16- // We are disabling these tests, because they use
17- // APIs gated behind the trait.
18- #if BinaryDelimitedStreams
19-
2016import Foundation
2117import SwiftProtobuf
2218import XCTest
2319
2420final 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