test_compression.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /*! \file
3  * \brief Test of \c cmpr_send() and \c cmpr_recv() implementation
4  *
5  * Copyright (c) 2015-2020 by the developers. See the LICENSE file for details.
6  */
7 
8 
9 /* ========================================================================== */
10 /* Include headers */
11 
12 #include "posix.h" /* Include this first because of feature test macros */
13 
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include "config.h"
18 
19 #include "compression.h"
20 #include "fileutils.h"
21 #include "inet.h"
22 #include "test.h"
23 #include "test_compression.h"
24 
25 
26 /* ========================================================================== */
27 /*! \addtogroup TEST */
28 /*! @{ */
29 
30 
31 #if !CFG_CMPR_DISABLE
32 
33 
34 /*! \brief Use real network connection to echo daemon instead of regular file */
35 # define TEST_CMPR_USE_NETWORK 0
36 
37 
38 # if !TEST_CMPR_USE_NETWORK
39 
40 
41 /* ========================================================================== */
42 /* Emulation of \c posix_send() */
43 
44 static ssize_t test_send(int sd, const void* buf, size_t len, int flags)
45 {
46  return(posix_write(sd, buf, len));
47 }
48 
49 
50 /* ========================================================================== */
51 /* Emulation \c posix_recv() */
52 
53 static ssize_t test_recv(int sd, void* buf, size_t len, int flags)
54 {
55  posix_ssize_t res = -1;
56 
57  if(flags)
58  {
59  posix_errno = POSIX_EINVAL;
60  print_error("test_recv(): Flags not supported");
61  }
62  else { res = posix_read(sd, buf, len); }
63 
64  return(res);
65 }
66 
67 
68 # endif /* TEST_CMPR_USE_NETWORK */
69 
70 
71 /* ========================================================================== */
72 /*! \brief Test \c cmpr_send() and \c cmpr_recv() implementation
73  *
74  * The following cases are tested:
75  * - Loopback test with DEFLATE algorithm
76  *
77  * \return
78  * - \c EXIT_SUCCESS on success
79  * - \c EXIT_FAILURE on error
80  */
81 
83 {
84 # define BUF_LEN (size_t) 1023 /* Maximum length of strings */
85 # define TS_NUM (size_t) 6 /* Number of test strings */
86  static const char* ts[TS_NUM] =
87  {
88  "CAPABILITIES",
89 
90  "ARTICLE 123",
91 
92  "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRlc3Qgc3RyaW5nCg==",
93 
94  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
95  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
96  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
97 
98  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
99  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
100  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
101  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
102  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
103  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
104  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
105  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
106  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
107  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
108  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
109  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
110  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
111  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
112  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
113  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
114  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
115  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
116  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
117  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB",
118 
119  ""
120  };
121  int res = POSIX_EXIT_SUCCESS;
122 # if TEST_CMPR_USE_NETWORK
123  const char* echo_host = "localhost";
124  int af = POSIX_AF_UNSPEC;
125 # else /* TEST_CMPR_USE_NETWORK */
126  const char* pathname = "/tmp/flnews_loopb";
127  int testfile_open = 0;
128  posix_off_t rv3;
129 # endif /* TEST_CMPR_USE_NETWORK */
130  int sd = -1;
131  char buf[BUF_LEN + (size_t) 1];
132  size_t i;
133  const char* loc;
134  int rv;
135  posix_ssize_t rv2;
136  void* cs = NULL;
137  size_t len;
138 
139 # if TEST_CMPR_USE_NETWORK
140  /* Use echo service as loopback facility */
141  rv = inet_connect(&sd, &af, echo_host, "echo");
142  if(rv)
143  {
144  print_error("This test requires an echo daemon running on localhost");
145  res = POSIX_EXIT_FAILURE;
146  }
147 # else /* TEST_CMPR_USE_NETWORK */
148  /* Use regular file as loopback facility */
149  rv = fu_open_file(pathname, &sd,
150  POSIX_O_RDWR | POSIX_O_CREAT | POSIX_O_TRUNC,
151  TEST_PERM);
152  if(!rv)
153  {
154  rv = fu_lock_file(sd);
155  if(rv) { fu_close_file(&sd, NULL); }
156  }
157  if(rv)
158  {
159  print_error("Creating or locking test file failed");
160  res = POSIX_EXIT_FAILURE;
161  }
162  else { testfile_open = 1; }
163 # endif /* TEST_CMPR_USE_NETWORK */
164 
165  /* Create compressed data stream */
166  if(POSIX_EXIT_SUCCESS == res)
167  {
170  posix_send, posix_recv);
171 # else /* TEST_CMPR_USE_NETWORK */
172  test_send, test_recv);
173 # endif /* TEST_CMPR_USE_NETWORK */
174  if(NULL == cs) { res = POSIX_EXIT_FAILURE; }
175  }
176 
177  /* Loopback test */
178  if(POSIX_EXIT_SUCCESS == res)
179  {
180  for(i = 0; i < TS_NUM; ++i)
181  {
182  len = strlen(ts[i]);
183  ++len; /* Transfer string with NUL termination */
184  if(BUF_LEN < len)
185  {
186  print_error("Length of test string too long");
187  res = POSIX_EXIT_FAILURE;
188  break;
189  }
190 # if !TEST_CMPR_USE_NETWORK
191 # if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
192  /* Truncate test file */
193  rv = posix_ftruncate(sd, (posix_off_t) 0);
194  if(rv)
195  {
196  print_error("Truncation of test file failed");
197  res = POSIX_EXIT_FAILURE;
198  break;
199  }
200 # endif /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */
201  /* Reset offset of test file to zero */
202  rv3 = posix_lseek(sd, (posix_off_t) 0, POSIX_SEEK_SET);
203  if((posix_off_t) -1 == rv3)
204  {
205  print_error("Seek in test file failed");
206  res = POSIX_EXIT_FAILURE;
207  break;
208  }
209 # endif /* ! TEST_CMPR_USE_NETWORK */
210  /* Send */
211  rv2 = cmpr_send(cs, ts[i], len);
212  if(0 >= rv2)
213  {
214  res = POSIX_EXIT_FAILURE;
215  break;
216  }
217  /* Flush */
218  rv = cmpr_flush(cs);
219  if(rv)
220  {
221  res = POSIX_EXIT_FAILURE;
222  break;
223  }
224 # if !TEST_CMPR_USE_NETWORK
225  /* Rewind test file offset to zero */
226  rv3 = posix_lseek(sd, (posix_off_t) 0, POSIX_SEEK_SET);
227  if((posix_off_t) -1 == rv3)
228  {
229  print_error("Seek in test file failed");
230  res = POSIX_EXIT_FAILURE;
231  break;
232  }
233 # endif /* ! TEST_CMPR_USE_NETWORK */
234  /* Receive */
235  rv2 = cmpr_recv(cs, buf, len, 0);
236  if(0 >= rv2)
237  {
238  res = POSIX_EXIT_FAILURE;
239  break;
240  }
241  /* Compare */
242  if(strcmp(ts[i], buf))
243  {
244  print_error("Result is not correct");
245  /* For debugging */
246 # if CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI
247  loc = posix_setlocale(POSIX_LC_CTYPE, "");
248 # else /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */
249  loc = NULL;
250 # endif /* CFG_USE_POSIX_API >= 200112 || CFG_USE_XSI */
251  if(NULL == loc)
252  {
253  print_error("Setting locale for debug messages failed");
254  }
255  else
256  {
257  /* Print Unicode data only if terminal use Unicode locale */
258  if(NULL == strstr(loc, "UTF") && NULL == strstr(loc, "utf"))
259  {
260  print_error(
261  "Debug messages can't be printed with current locale");
262  }
263  else
264  {
265  fprintf(stderr, TEST_TAB "Data sent : \"%s\"\n", ts[i]);
266  fprintf(stderr, TEST_TAB "Data received: \"%s\"\n", buf);
267  }
268  }
269  res = POSIX_EXIT_FAILURE;
270  break;
271  }
272  }
273  }
274 
275 # if TEST_CMPR_USE_NETWORK
276  /* Close loopback connection */
277  if(-1 != sd) { inet_close(&sd); }
278 # else /* TEST_CMPR_USE_NETWORK */
279  /* Close and delete loopback regular file */
280  if(testfile_open)
281  {
282  fu_close_file(&sd, NULL);
283  (void) fu_unlink_file(pathname);
284  }
285 # endif /* TEST_CMPR_USE_NETWORK */
286 
287  /* Destroy compressed data stream */
289 
290  return(res);
291 }
292 
293 
294 #endif /* !CFG_CMPR_DISABLE */
295 
296 
297 /*! @} */
298 
299 /* EOF */
TEST_TAB
#define TEST_TAB
Tabulator to indent messages from test programs.
Definition: test.h:13
cmpr_recv
posix_ssize_t cmpr_recv(void *stream, void *buf, size_t len, int peek)
Receive data.
Definition: compression.c:443
TEST_CMPR_USE_NETWORK
#define TEST_CMPR_USE_NETWORK
Use real network connection to echo daemon instead of regular file.
Definition: test_compression.c:35
fu_lock_file
int fu_lock_file(int filedesc)
Lock file for writing.
Definition: fileutils.c:328
TEST_PERM
#define TEST_PERM
Permissions for test files.
Definition: test.h:16
cmpr_flush
int cmpr_flush(void *stream)
Flush TX direction.
Definition: compression.c:384
inet_close
void inet_close(int *)
Close connection and destroy socket.
Definition: inet.c:524
fu_unlink_file
int fu_unlink_file(const char *pathname)
Unlink file.
Definition: fileutils.c:355
cmpr_stream_destructor
void cmpr_stream_destructor(void *stream)
Destroy compressed data stream object allocated by compression module.
Definition: compression.c:768
cmpr_stream_constructor
struct cmpr_stream * cmpr_stream_constructor(unsigned int alg, int sd, ssize_t(*tx_send)(int, const void *, size_t, int), ssize_t(*rx_recv)(int, void *, size_t, int))
Compressed data stream object constructor.
Definition: compression.c:615
CMPR_ALG_DEFLATE
#define CMPR_ALG_DEFLATE
DEFLATE according to RFC 1951.
Definition: compression.h:23
cmpr_send
posix_ssize_t cmpr_send(void *stream, const void *buf, size_t len)
Send data.
Definition: compression.c:362
test_compression
int test_compression(void)
Test cmpr_send() and cmpr_recv() implementation.
Definition: test_compression.c:82
fu_close_file
void fu_close_file(int *filedesc, FILE **stream)
Close file (and potentially associated I/O stream)
Definition: fileutils.c:290
fu_open_file
int fu_open_file(const char *pathname, int *filedesc, int mode, posix_mode_t perm)
Open file.
Definition: fileutils.c:243
inet_connect
int inet_connect(int *, int *, const char *, const char *)
Establish stream oriented connection.
Definition: inet.c:254
print_error
void print_error(const char *)
Print error message.
Definition: main.cxx:276

Generated at 2024-04-27 using  doxygen