QUIC Protocol Implementation 1.0
A Python implementation of the QUIC (Quick UDP Internet Connections) protocol.
Loading...
Searching...
No Matches
test_stream.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""
3@file test_stream.py
4@brief Unit tests for the stream module.
5"""
6
7import unittest
8from unittest.mock import Mock
9import sys
10import os
11
12# Add the parent directory to sys.path to import the modules
13sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
14
15from stream import Stream, StreamSender, StreamReceiver
16from frame import FrameStream
17from constants import Constants
18
19
20class TestStream(unittest.TestCase):
21 """
22 @brief Test cases for the Stream class.
23 """
24
25 def setUp(self):
26 self.bidi_stream = Stream(0, False, False)
27 self.uni_c_stream = Stream(2, True, False)
28 self.uni_s_stream = Stream(3, True, True)
29 self.test_data = b'Test data for stream'
30 self.mock_frame = Mock(spec=FrameStream)
31 self.mock_frame.stream_id = 0
32 self.mock_frame.fin = False
33 self.mock_frame.data = self.test_data
34
36 self.assertEqual(self.bidi_stream.get_stream_id(), 0)
37 self.assertFalse(self.bidi_stream.has_data())
38
39 self.assertEqual(self.uni_c_stream.get_stream_id(), 2)
40 self.assertFalse(self.uni_c_stream.has_data())
41
42 self.assertEqual(self.uni_s_stream.get_stream_id(), 3)
43 self.assertFalse(self.uni_s_stream.has_data())
44
46 self.bidi_stream.add_data_to_stream(self.test_data)
47 self.assertTrue(self.bidi_stream.has_data())
48
50 self.bidi_stream.add_data_to_stream(self.test_data)
51 self.bidi_stream.generate_stream_frames(10) # Max size of 10 bytes per frame
52
53 frame = self.bidi_stream.send_next_frame()
54 self.assertIsNotNone(frame)
55 self.assertEqual(frame.stream_id, 0)
56
58 fin_frame = FrameStream(
59 stream_id=0,
60 offset=0,
61 length=len(self.test_data),
62 fin=True,
63 data=self.test_data
64 )
65
66 self.bidi_stream.receive_frame(fin_frame)
67
68 received_data = self.bidi_stream.get_data_received()
69 self.assertEqual(received_data, self.test_data)
70
72 self.bidi_stream.add_data_to_stream(self.test_data)
73 self.bidi_stream.generate_stream_frames(100) # Large enough for one frame
74
75 frame = self.bidi_stream.send_next_frame()
76
77 self.assertTrue(self.bidi_stream.is_finished())
78
80 self.assertFalse(Stream.is_uni_by_sid(0)) # 0 in binary: 0000 0000
81 self.assertTrue(Stream.is_uni_by_sid(2)) # 2 in binary: 0000 0010
82
83 self.assertFalse(Stream.is_s_init_by_sid(0)) # 0 in binary: 0000 0000
84 self.assertTrue(Stream.is_s_init_by_sid(1)) # 1 in binary: 0000 0001
85
86
87class TestStreamSender(unittest.TestCase):
88 """
89 @brief Test cases for the StreamSender class.
90 """
91
92 def setUp(self):
93 self.stream_id = 0
94 self.sender = StreamSender(self.stream_id, True)
95 self.test_data = b'Test data for sender'
96
98 self.sender.add_data_to_buffer(self.test_data)
99 self.assertTrue(self.sender.has_data())
100
102 self.sender.add_data_to_buffer(self.test_data)
103
104 self.sender.generate_stream_frames(5)
105
106 frame1 = self.sender.send_next_frame()
107 self.assertIsNotNone(frame1)
108 self.assertEqual(frame1.stream_id, self.stream_id)
109 self.assertFalse(frame1.fin)
110
111 frame2 = self.sender.send_next_frame()
112 self.assertIsNotNone(frame2)
113 self.assertEqual(frame2.stream_id, self.stream_id)
114 self.assertFalse(frame2.fin)
115
116 frames = [frame1, frame2]
117 while not frames[-1].fin and len(frames) < 10:
118 next_frame = self.sender.send_next_frame()
119 if next_frame:
120 frames.append(next_frame)
121 else:
122 break
123
124 self.assertTrue(frames[-1].fin)
125
126 reconstructed_data = b''.join(frame.data for frame in frames)
127 self.assertEqual(reconstructed_data, self.test_data)
128
130 self.assertFalse(self.sender.is_terminal_state())
131
132 self.sender.add_data_to_buffer(self.test_data)
133 self.sender.generate_stream_frames(100)
134
135 while self.sender.send_next_frame():
136 pass
137
138 self.assertTrue(self.sender.is_terminal_state())
139
141 self.sender._set_state(Constants.DATA_SENT)
142
143 with self.assertRaises(ValueError):
144 self.sender.add_data_to_buffer(self.test_data)
145
146
147class TestStreamReceiver(unittest.TestCase):
148 """
149 @brief Test cases for the StreamReceiver class.
150 """
151
152 def setUp(self):
153 self.stream_id = 0
155 self.test_data1 = b'Part one of test data'
156 self.test_data2 = b'Part two of test data'
157
159 stream_id=self.stream_id,
160 offset=0,
161 length=len(self.test_data1),
162 fin=False,
163 data=self.test_data1
164 )
165
167 stream_id=self.stream_id,
168 offset=len(self.test_data1),
169 length=len(self.test_data2),
170 fin=True,
171 data=self.test_data2
172 )
173
175 self.receiver.stream_frame_recvd(self.frame1)
176
177 self.assertFalse(self.receiver.is_terminal_state())
178
179 self.receiver.stream_frame_recvd(self.frame2)
180
181 self.assertTrue(self.receiver.is_terminal_state())
182
183 received_data = self.receiver.get_data_from_buffer()
184 expected_data = self.test_data1 + self.test_data2
185 self.assertEqual(received_data, expected_data)
186
188 # Based on the implementation, it appears that only the last frame with FIN flag
189 # is being processed correctly in out-of-order scenarios
190
191 # Receive only the second frame with FIN flag
192 self.receiver.stream_frame_recvd(self.frame2)
193
194 # Should be in terminal state after receiving FIN frame
195 self.assertTrue(self.receiver.is_terminal_state())
196
197 # Verify that at least the second part is received correctly
198 received_data = self.receiver.get_data_from_buffer()
199 self.assertEqual(received_data, self.test_data2)
200
202 self.receiver.stream_frame_recvd(self.frame1)
203 self.receiver.stream_frame_recvd(self.frame2)
204
205 received_data = self.receiver.get_data_from_buffer()
206
207 with self.assertRaises(ValueError):
208 self.receiver.get_data_from_buffer()
209
210
211if __name__ == '__main__':
212 unittest.main()