PX4 Firmware
PX4 Autopilot Software http://px4.io
test_file.c
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2012-2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file test_file.c
36  * File write test.
37  * @author Lorenz Meier <lm@inf.ethz.ch>
38  */
39 
40 #include <px4_platform_common/px4_config.h>
41 #include <px4_platform_common/posix.h>
42 
43 #include <sys/stat.h>
44 #include <poll.h>
45 #include <dirent.h>
46 #include <stdio.h>
47 #include <stddef.h>
48 #include <systemlib/err.h>
49 #include <perf/perf_counter.h>
50 #include <string.h>
51 
52 #include <drivers/drv_hrt.h>
53 
54 #include "tests_main.h"
55 
56 static int check_user_abort(int fd);
57 
59 {
60  /* check if user wants to abort */
61  char c;
62 
63  struct pollfd fds;
64  int ret;
65  fds.fd = 0; /* stdin */
66  fds.events = POLLIN;
67  ret = poll(&fds, 1, 0);
68 
69  if (ret > 0) {
70 
71  read(0, &c, 1);
72 
73  switch (c) {
74  case 0x03: // ctrl-c
75  case 0x1b: // esc
76  case 'c':
77  case 'q': {
78  warnx("Test aborted.");
79  fsync(fd);
80  close(fd);
81  return OK;
82  /* not reached */
83  }
84  }
85  }
86 
87  return 1;
88 }
89 
90 int
91 test_file(int argc, char *argv[])
92 {
93  const unsigned iterations = 100;
94  const unsigned alignments = 65;
95 
96  /* check if microSD card is mounted */
97  struct stat buffer;
98 
99  if (stat(PX4_STORAGEDIR "/", &buffer)) {
100  warnx("no microSD card mounted, aborting file test");
101  return 1;
102  }
103 
104  /* perform tests for a range of chunk sizes */
105  int chunk_sizes[] = {1, 5, 8, 13, 16, 32, 33, 64, 70, 128, 133, 256, 300, 512, 555, 1024, 1500};
106 
107  for (unsigned c = 0; c < (sizeof(chunk_sizes) / sizeof(chunk_sizes[0])); c++) {
108 
109  printf("\n====== FILE TEST: %u bytes chunks ======\n", chunk_sizes[c]);
110 
111  for (unsigned a = 0; a < alignments; a++) {
112 
113  printf("\n");
114  warnx("----- alignment test: %u bytes -----", a);
115 
116  uint8_t write_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64)));
117 
118  /* fill write buffer with known values */
119  for (size_t i = 0; i < sizeof(write_buf); i++) {
120  /* this will wrap, but we just need a known value with spacing */
121  write_buf[i] = i + 11;
122  }
123 
124  uint8_t read_buf[chunk_sizes[c] + alignments] __attribute__((aligned(64)));
125  hrt_abstime start, end;
126 
127  int fd = px4_open(PX4_STORAGEDIR "/testfile", O_TRUNC | O_WRONLY | O_CREAT);
128 
129  warnx("testing unaligned writes - please wait..");
130 
131  start = hrt_absolute_time();
132 
133  for (unsigned i = 0; i < iterations; i++) {
134  int wret = write(fd, write_buf + a, chunk_sizes[c]);
135 
136  if (wret != chunk_sizes[c]) {
137  warn("WRITE ERROR!");
138 
139  if ((0x3 & (uintptr_t)(write_buf + a))) {
140  warnx("memory is unaligned, align shift: %d", a);
141  }
142 
143  return 1;
144  }
145 
146  fsync(fd);
147 
148  if (!check_user_abort(fd)) {
149  return OK;
150  }
151 
152  }
153 
154  end = hrt_absolute_time();
155 
156  warnx("write took %" PRIu64 " us", (end - start));
157 
158  px4_close(fd);
159  fd = open(PX4_STORAGEDIR "/testfile", O_RDONLY);
160 
161  /* read back data for validation */
162  for (unsigned i = 0; i < iterations; i++) {
163  int rret = read(fd, read_buf, chunk_sizes[c]);
164 
165  if (rret != chunk_sizes[c]) {
166  warnx("READ ERROR!");
167  return 1;
168  }
169 
170  /* compare value */
171  bool compare_ok = true;
172 
173  for (int j = 0; j < chunk_sizes[c]; j++) {
174  if (read_buf[j] != write_buf[j + a]) {
175  warnx("COMPARISON ERROR: byte %d, align shift: %d", j, a);
176  compare_ok = false;
177  break;
178  }
179  }
180 
181  if (!compare_ok) {
182  warnx("ABORTING FURTHER COMPARISON DUE TO ERROR");
183  return 1;
184  }
185 
186  if (!check_user_abort(fd)) {
187  return OK;
188  }
189 
190  }
191 
192  /*
193  * ALIGNED WRITES AND UNALIGNED READS
194  */
195 
196  close(fd);
197  int ret = unlink(PX4_STORAGEDIR "/testfile");
198  fd = px4_open(PX4_STORAGEDIR "/testfile", O_TRUNC | O_WRONLY | O_CREAT);
199 
200  warnx("testing aligned writes - please wait.. (CTRL^C to abort)");
201 
202  for (unsigned i = 0; i < iterations; i++) {
203  int wret = write(fd, write_buf, chunk_sizes[c]);
204 
205  if (wret != chunk_sizes[c]) {
206  warnx("WRITE ERROR!");
207  return 1;
208  }
209 
210  if (!check_user_abort(fd)) {
211  return OK;
212  }
213 
214  }
215 
216  fsync(fd);
217 
218  warnx("reading data aligned..");
219 
220  px4_close(fd);
221  fd = open(PX4_STORAGEDIR "/testfile", O_RDONLY);
222 
223  bool align_read_ok = true;
224 
225  /* read back data unaligned */
226  for (unsigned i = 0; i < iterations; i++) {
227  int rret = read(fd, read_buf, chunk_sizes[c]);
228 
229  if (rret != chunk_sizes[c]) {
230  warnx("READ ERROR!");
231  return 1;
232  }
233 
234  for (int j = 0; j < chunk_sizes[c]; j++) {
235  if (read_buf[j] != write_buf[j]) {
236  warnx("COMPARISON ERROR: byte %d: %u != %u", j, (unsigned int)read_buf[j], (unsigned int)write_buf[j]);
237  align_read_ok = false;
238  break;
239  }
240 
241  if (!check_user_abort(fd)) {
242  return OK;
243  }
244  }
245 
246  if (!align_read_ok) {
247  warnx("ABORTING FURTHER COMPARISON DUE TO ERROR");
248  return 1;
249  }
250 
251  }
252 
253  warnx("align read result: %s\n", (align_read_ok) ? "OK" : "ERROR");
254 
255  warnx("reading data unaligned..");
256 
257  close(fd);
258  fd = open(PX4_STORAGEDIR "/testfile", O_RDONLY);
259 
260  bool unalign_read_ok = true;
261  int unalign_read_err_count = 0;
262 
263  memset(read_buf, 0, sizeof(read_buf));
264 
265  /* read back data unaligned */
266  for (unsigned i = 0; i < iterations; i++) {
267  int rret = read(fd, read_buf + a, chunk_sizes[c]);
268 
269  if (rret != chunk_sizes[c]) {
270  warnx("READ ERROR!");
271  return 1;
272  }
273 
274  for (int j = 0; j < chunk_sizes[c]; j++) {
275 
276  if ((read_buf + a)[j] != write_buf[j]) {
277  warnx("COMPARISON ERROR: byte %d, align shift: %d: %u != %u", j, a, (unsigned int)read_buf[j + a],
278  (unsigned int)write_buf[j]);
279  unalign_read_ok = false;
280  unalign_read_err_count++;
281 
282  if (unalign_read_err_count > 10) {
283  break;
284  }
285  }
286 
287  if (!check_user_abort(fd)) {
288  return OK;
289  }
290  }
291 
292  if (!unalign_read_ok) {
293  warnx("ABORTING FURTHER COMPARISON DUE TO ERROR");
294  return 1;
295  }
296 
297  }
298 
299  ret = unlink(PX4_STORAGEDIR "/testfile");
300  close(fd);
301 
302  if (ret) {
303  warnx("UNLINKING FILE FAILED");
304  return 1;
305  }
306  }
307  }
308 
309  /* list directory */
310  DIR *d;
311  struct dirent *dir;
312  d = opendir(PX4_STORAGEDIR);
313 
314  if (d) {
315 
316  while ((dir = readdir(d)) != NULL) {
317  //printf("%s\n", dir->d_name);
318  }
319 
320  closedir(d);
321 
322  warnx("directory listing ok (FS mounted and readable)");
323 
324  } else {
325  /* failed opening dir */
326  warnx("FAILED LISTING MICROSD ROOT DIRECTORY");
327  return 1;
328  }
329 
330  return 0;
331 }
High-resolution timer with callouts and timekeeping.
static void read(bootloader_app_shared_t *pshared)
#define warnx(...)
Definition: err.h:95
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
Tests declaration file.
struct __attribute__((__packed__)) reading_msg
Definition: leddar_one.cpp:80
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
int fd
Definition: dataman.cpp:146
static int start()
Definition: dataman.cpp:1452
static void write(bootloader_app_shared_t *pshared)
int px4_open(const char *path, int flags,...)
static int check_user_abort(int fd)
Definition: test_file.c:58
#define OK
Definition: uavcan_main.cpp:71
#define warn(...)
Definition: err.h:94
int test_file(int argc, char *argv[])
Definition: test_file.c:91
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
int px4_close(int fd)
Performance measuring tools.