root/test/test-shunt-simple-file.c

Revision f74aea30e4dfbad4e94ef339ae38bf0bb3800dde, 11.1 kB (checked in by hansp <hansp>, 4 years ago)

Initial revision

  • Property mode set to 100644
Line 
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
3 /* test-shunt-simple-file.c - FlowShunt simple file test.
4  *
5  * Copyright (C) 2006 Hans Petter Jansson
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * Authors: Hans Petter Jansson <hpj@copyleft.no>
23  */
24
25 #define TEST_UNIT_NAME "FlowShunt (simple file)"
26 #define TEST_TIMEOUT_S 60
27
28 /* Test variables; adjustable */
29
30 #define BUFFER_SIZE            50000000  /* Amount of data to transfer */
31 #define PACKET_MAX_SIZE        8192      /* Max transfer unit */
32 #define PACKET_MIN_SIZE        1         /* Min transfer unit */
33
34 #define TOTAL_PAUSE_TIME_MS    3000      /* Total time to spend *not* reading or writing */
35 #define PAUSE_MIN_LENGTH_MS    10        /* Min pause unit */
36 #define PAUSE_MAX_LENGTH_MS    200       /* Max pause unit */
37
38 /* Calculations to determine the probability of pausing for
39  * each packet processed. No user serviceable parts inside. */
40
41 #define PROBABILITY_MULTIPLIER 1000000  /* For fixed-point fractions */
42 #define PACKET_AVG_SIZE        (PACKET_MIN_SIZE + ((PACKET_MAX_SIZE - PACKET_MIN_SIZE) / 2))
43 #define PAUSE_AVG_LENGTH_MS    (PAUSE_MIN_LENGTH_MS + ((PAUSE_MAX_LENGTH_MS - PAUSE_MIN_LENGTH_MS) / 2))
44 #define NUM_PAUSES             (TOTAL_PAUSE_TIME_MS / PAUSE_AVG_LENGTH_MS)
45 #define TOTAL_EXPECTED_PACKETS (BUFFER_SIZE / PACKET_AVG_SIZE)
46 #define TOTAL_EXPECTED_EVENTS  (TOTAL_EXPECTED_PACKETS * 2)  /* Account for both reads and writes */
47 #define PAUSE_PROBABILITY      ((NUM_PAUSES * PROBABILITY_MULTIPLIER) / TOTAL_EXPECTED_EVENTS)
48
49 #include "test-common.c"
50
51 static guchar    *buffer;
52 static guint      src_index;
53 static guint      dest_index;
54
55 static gboolean   finished_writing;
56 static gboolean   writes_are_blocked;
57
58 static gboolean   started_reading;
59 static gboolean   finished_reading;
60 static gboolean   in_segment;
61 static gboolean   reads_are_blocked;
62
63 static FlowShunt *read_shunt;
64 static FlowShunt *write_shunt;
65
66 static guint
67 get_pause_interval_ms (void)
68 {
69   guint n;
70
71   n = g_random_int_range (0, PROBABILITY_MULTIPLIER + 1);
72   if (n < PAUSE_PROBABILITY)
73   {
74     n = g_random_int_range (PAUSE_MIN_LENGTH_MS, PAUSE_MAX_LENGTH_MS + 1);
75     return n;
76   }
77
78   return 0;
79 }
80
81 static gboolean
82 read_pause_ended (FlowShunt *shunt)
83 {
84   test_print ("Resuming reads\n");
85   reads_are_blocked = FALSE;
86   flow_shunt_unblock_reads (shunt);
87   return FALSE;
88 }
89
90 static void
91 read_from_shunt (FlowShunt *shunt, FlowPacket *packet, gpointer data)
92 {
93   guint    packet_size;
94   gpointer packet_data;
95   guint    pause_ms;
96
97   if (reads_are_blocked)
98     test_end (TEST_RESULT_FAILED, "got read while blocked");
99
100   if (data != shunt)
101     test_end (TEST_RESULT_FAILED, "read callback user_data does not match");
102
103   if (finished_reading)
104     test_end (TEST_RESULT_FAILED, "got read callback after end-of-stream");
105
106   if (!packet)
107     test_end (TEST_RESULT_FAILED, "got read with NULL packet");
108
109   packet_data = flow_packet_get_data (packet);
110   if (!packet_data)
111     test_end (TEST_RESULT_FAILED, "got NULL packet data");
112
113   if (flow_packet_get_format (packet) == FLOW_PACKET_FORMAT_OBJECT)
114   {
115     FlowDetailedEvent *detailed_event = packet_data;
116
117     if (FLOW_IS_DETAILED_EVENT (detailed_event))
118     {
119       if (flow_detailed_event_matches (detailed_event, FLOW_STREAM_DOMAIN, FLOW_STREAM_BEGIN))
120       {
121         test_print ("Read: Beginning of stream marker\n");
122
123         if (started_reading)
124           test_end (TEST_RESULT_FAILED, "got multiple beginning-of-stream markers");
125
126         started_reading = TRUE;
127       }
128       else if (flow_detailed_event_matches (detailed_event, FLOW_STREAM_DOMAIN, FLOW_STREAM_SEGMENT_BEGIN))
129       {
130         test_print ("Read: Beginning of segment marker\n");
131
132         if (!started_reading)
133           test_end (TEST_RESULT_FAILED, "segment started before stream");
134
135         if (finished_reading)
136           test_end (TEST_RESULT_FAILED, "segment started after stream end");
137
138         if (in_segment)
139           test_end (TEST_RESULT_FAILED, "got nested beginning-of-segment markers");
140
141         in_segment = TRUE;
142       }
143       else if (flow_detailed_event_matches (detailed_event, FLOW_STREAM_DOMAIN, FLOW_STREAM_END))
144       {
145         test_print ("Read: End of stream marker\n");
146
147         if (!started_reading)
148           test_end (TEST_RESULT_FAILED, "stream ended without starting");
149
150         if (finished_reading)
151           test_end (TEST_RESULT_FAILED, "got multiple end-of-stream markers");
152
153         if (in_segment)
154           test_end (TEST_RESULT_FAILED, "stream ended inside an open segment");
155
156         if (dest_index != BUFFER_SIZE)
157           test_end (TEST_RESULT_FAILED, "did not pass through all the data");
158
159         finished_reading = TRUE;
160       }
161       else if (flow_detailed_event_matches (detailed_event, FLOW_STREAM_DOMAIN, FLOW_STREAM_SEGMENT_END))
162       {
163         test_print ("Read: End of segment marker\n");
164
165         if (!started_reading)
166           test_end (TEST_RESULT_FAILED, "segment end before stream start");
167
168         if (finished_reading)
169           test_end (TEST_RESULT_FAILED, "segment end after stream end");
170
171         if (!in_segment)
172           test_end (TEST_RESULT_FAILED, "end of segment, but no segment open");
173
174         in_segment = FALSE;
175
176         /* Wait a bit before quitting, so shunts have a chance to generate invalid events */
177         g_timeout_add (1000, (GSourceFunc) test_quit_main_loop, NULL);
178       }
179     }
180     else if (!FLOW_IS_EVENT (detailed_event))
181     {
182       test_end (TEST_RESULT_FAILED, "got a weird object from read shunt");
183     }
184   }
185   else if (flow_packet_get_format (packet) == FLOW_PACKET_FORMAT_BUFFER)
186   {
187     packet_size = flow_packet_get_size (packet);
188     if (packet_size == 0)
189       test_end (TEST_RESULT_FAILED, "got zero-size buffer packet");
190
191     test_print ("Read: %d byte packet at offset %d\n", packet_size, dest_index);
192
193     if (!started_reading)
194       test_end (TEST_RESULT_FAILED, "got data before start of stream");
195
196     if (finished_reading)
197       test_end (TEST_RESULT_FAILED, "got data after end of stream");
198
199     if (!in_segment)
200       test_end (TEST_RESULT_FAILED, "got data outside segment");
201
202     if (dest_index + packet_size > BUFFER_SIZE)
203       test_end (TEST_RESULT_FAILED, "read too much data");
204
205     if (memcmp (packet_data, buffer + dest_index, packet_size))
206       test_end (TEST_RESULT_FAILED, "output data did not match input");
207
208     dest_index += packet_size;
209
210     if (dest_index == BUFFER_SIZE)
211       test_print ("Read: Complete at %d bytes\n", dest_index);
212   }
213   else
214   {
215     test_end (TEST_RESULT_FAILED, "got unknown packet format");
216   }
217
218   flow_packet_free (packet);
219
220   pause_ms = get_pause_interval_ms ();
221   if (pause_ms > 0)
222   {
223     test_print ("Blocking reads for %.2fs\n", (float) pause_ms / 1000.0);
224     reads_are_blocked = TRUE;
225     flow_shunt_block_reads (shunt);
226     g_timeout_add (pause_ms, (GSourceFunc) read_pause_ended, shunt);
227   }
228 }
229
230 static gboolean
231 write_pause_ended (FlowShunt *shunt)
232 {
233   test_print ("Resuming writes\n");
234   writes_are_blocked = FALSE;
235   flow_shunt_unblock_writes (shunt);
236   return FALSE;
237 }
238
239 static FlowPacket *
240 write_to_shunt (FlowShunt *shunt, gpointer data)
241 {
242   FlowPacket *packet;
243   guint       pause_ms;
244
245   if (writes_are_blocked)
246     test_end (TEST_RESULT_FAILED, "got write while blocked");
247
248   if (data != shunt)
249     test_end (TEST_RESULT_FAILED, "write callback user_data does not match");
250
251   if (finished_writing)
252     test_end (TEST_RESULT_FAILED, "got write callback after sending end-of-stream");
253
254   if (src_index == BUFFER_SIZE)
255   {
256     packet = flow_create_simple_event_packet (FLOW_STREAM_DOMAIN, FLOW_STREAM_END);
257     finished_writing = TRUE;
258     flow_shunt_block_writes (shunt);
259
260     test_print ("Write: End of stream marker\n");
261
262     /* Wait a bit before quitting, so shunts have a chance to generate invalid events */
263     g_timeout_add (1000, (GSourceFunc) test_quit_main_loop, NULL);
264   }
265   else
266   {
267     guint len;
268
269     len = g_random_int_range (PACKET_MIN_SIZE, PACKET_MAX_SIZE + 1);
270     if (src_index + len > BUFFER_SIZE)
271       len = BUFFER_SIZE - src_index;
272
273     packet = flow_packet_new (FLOW_PACKET_FORMAT_BUFFER, buffer + src_index, len);
274
275     test_print ("Write: %d byte packet at offset %d\n", len, src_index);
276
277     src_index += len;
278   }
279
280   if (!packet)
281     test_end (TEST_RESULT_FAILED, "failed to create a packet");
282
283   pause_ms = get_pause_interval_ms ();
284   if (pause_ms > 0)
285   {
286     test_print ("Blocking writes for %.2fs\n", (float) pause_ms / 1000.0);
287     writes_are_blocked = TRUE;
288     flow_shunt_block_writes (shunt);
289     g_timeout_add (pause_ms, (GSourceFunc) write_pause_ended, shunt);
290   }
291
292   return packet;
293 }
294
295 static FlowPacket *
296 write_segment_request_to_shunt (FlowShunt *shunt, gpointer data)
297 {
298   test_print ("Writing segment request\n");
299
300   flow_shunt_set_write_func (shunt, NULL, NULL);
301
302   return flow_packet_new_take_object (flow_segment_request_new (-1), 0);
303 }
304
305 static void
306 test_run (void)
307 {
308   gchar *test_file_name;
309   gint   i;
310
311   g_random_set_seed (time (NULL));
312
313   /* Set up a buffer with random data */
314
315   buffer = g_malloc (BUFFER_SIZE);
316
317   for (i = 0; i < BUFFER_SIZE; )
318   {
319     guchar *p = buffer + i;
320
321     if (i < BUFFER_SIZE - 4)
322     {
323       *((guint32 *) p) = g_random_int ();
324       i += 4;
325     }
326     else
327     {
328       *p = (guchar) g_random_int ();
329       i++;
330     }
331   }
332
333   test_print ("Probability of pause is %d out of %d\n", PAUSE_PROBABILITY, PROBABILITY_MULTIPLIER);
334
335   /* Create and write out scratch file */
336
337   src_index          = 0;
338   dest_index         = 0;
339   finished_reading   = FALSE;
340   finished_writing   = FALSE;
341   reads_are_blocked  = FALSE;
342   writes_are_blocked = FALSE;
343
344   test_file_name = g_strdup_printf ("test-shunt-data-%08x", g_random_int ());
345
346   write_shunt = flow_create_file (test_file_name, FLOW_WRITE_ACCESS, TRUE,
347                                   FLOW_READ_ACCESS | FLOW_WRITE_ACCESS,
348                                   FLOW_NO_ACCESS,
349                                   FLOW_NO_ACCESS);
350
351   flow_shunt_set_write_func (write_shunt, write_to_shunt, write_shunt);
352
353   test_run_main_loop ();
354
355   flow_shunt_destroy (write_shunt);
356
357   /* Read in and validate scratch file */
358
359   src_index          = 0;
360   dest_index         = 0;
361   finished_reading   = FALSE;
362   finished_writing   = FALSE;
363   reads_are_blocked  = FALSE;
364   writes_are_blocked = FALSE;
365
366   read_shunt = flow_open_file (test_file_name, FLOW_READ_ACCESS);
367   flow_shunt_set_read_func (read_shunt, read_from_shunt, read_shunt);
368   flow_shunt_set_write_func (read_shunt, write_segment_request_to_shunt, read_shunt);
369
370   test_run_main_loop ();
371
372   flow_shunt_destroy (read_shunt);
373
374   /* Cleanup */
375
376   unlink (test_file_name);
377   g_free (test_file_name);
378   g_free (buffer);
379 }
Note: See TracBrowser for help on using the browser.