Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
fopen.cpp
00001 /* 00002 * mbed Microcontroller Library 00003 * Copyright (c) 2006-2016 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /** @file fopen.cpp Test cases to POSIX file fopen() interface. 00019 * 00020 * Please consult the documentation under the test-case functions for 00021 * a description of the individual test case. 00022 */ 00023 00024 #include "mbed.h" 00025 #include "mbed_config.h" 00026 #include "SDBlockDevice.h" 00027 #include "FATFileSystem.h" 00028 #include "fsfat_debug.h" 00029 #include "fsfat_test.h" 00030 #include "utest/utest.h" 00031 #include "unity/unity.h" 00032 #include "greentea-client/test_env.h" 00033 00034 #include <stdio.h> 00035 #include <string.h> 00036 #include <stdlib.h> /*rand()*/ 00037 #include <inttypes.h> 00038 #include <errno.h> 00039 /* mbed_retarget.h is included after errno.h so symbols are mapped to 00040 * consistent values for all toolchains */ 00041 #include "platform/mbed_retarget.h" 00042 00043 using namespace utest::v1; 00044 00045 /// @cond FSFAT_DOXYGEN_DISABLE 00046 #ifdef FSFAT_DEBUG 00047 #define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 3000 00048 #else 00049 #define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 1000 00050 #endif 00051 /// @endcond 00052 00053 00054 /* DEVICE_SPI 00055 * This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support. 00056 * 00057 * MBED_CONF_APP_FSFAT_SDCARD_INSTALLED 00058 * For testing purposes, an SDCard must be installed on the target for the test cases in this file to succeed. 00059 * If the target has an SD card installed then the MBED_CONF_APP_FSFAT_SDCARD_INSTALLED will be generated 00060 * from the mbed_app.json, which includes the line 00061 * { 00062 * "config": { 00063 * "UART_RX": "D0", 00064 * <<< lines removed >>> 00065 * "DEVICE_SPI": 1, 00066 * "FSFAT_SDCARD_INSTALLED": 1 00067 * }, 00068 * <<< lines removed >>> 00069 */ 00070 00071 #if !(DEVICE_SPI && ( defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) || (MBED_CONF_SD_FSFAT_SDCARD_INSTALLED))) 00072 #error [NOT_SUPPORTED] DEVICE_SPI need to be enabled for this test. SDcard need to be installed for this test. 00073 #else 00074 static char fsfat_fopen_utest_msg_g[FSFAT_UTEST_MSG_BUF_SIZE]; 00075 #define FSFAT_FOPEN_TEST_MOUNT_PT_NAME "sd" 00076 #define FSFAT_FOPEN_TEST_MOUNT_PT_PATH "/" FSFAT_FOPEN_TEST_MOUNT_PT_NAME 00077 #define FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1 64 00078 #define FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH 20 00079 static const char *sd_badfile_path = "/sd/badfile.txt"; 00080 static const char *sd_testfile_path = "/sd/test.txt"; 00081 00082 SDBlockDevice sd(MBED_CONF_SD_SPI_MOSI, MBED_CONF_SD_SPI_MISO, MBED_CONF_SD_SPI_CLK, MBED_CONF_SD_SPI_CS); 00083 FATFileSystem fs("sd", &sd); 00084 00085 #define FSFAT_FOPEN_TEST_00 fsfat_fopen_test_00 00086 #define FSFAT_FOPEN_TEST_01 fsfat_fopen_test_01 00087 #define FSFAT_FOPEN_TEST_02 fsfat_fopen_test_02 00088 #define FSFAT_FOPEN_TEST_03 fsfat_fopen_test_03 00089 #define FSFAT_FOPEN_TEST_04 fsfat_fopen_test_04 00090 #define FSFAT_FOPEN_TEST_05 fsfat_fopen_test_05 00091 #define FSFAT_FOPEN_TEST_06 fsfat_fopen_test_06 00092 #define FSFAT_FOPEN_TEST_07 fsfat_fopen_test_07 00093 #define FSFAT_FOPEN_TEST_08 fsfat_fopen_test_08 00094 #define FSFAT_FOPEN_TEST_09 fsfat_fopen_test_09 00095 #define FSFAT_FOPEN_TEST_10 fsfat_fopen_test_10 00096 #define FSFAT_FOPEN_TEST_11 fsfat_fopen_test_11 00097 #define FSFAT_FOPEN_TEST_12 fsfat_fopen_test_12 00098 #define FSFAT_FOPEN_TEST_13 fsfat_fopen_test_13 00099 #define FSFAT_FOPEN_TEST_14 fsfat_fopen_test_14 00100 #define FSFAT_FOPEN_TEST_15 fsfat_fopen_test_15 00101 #define FSFAT_FOPEN_TEST_16 fsfat_fopen_test_16 00102 #define FSFAT_FOPEN_TEST_17 fsfat_fopen_test_17 00103 #define FSFAT_FOPEN_TEST_18 fsfat_fopen_test_18 00104 #define FSFAT_FOPEN_TEST_19 fsfat_fopen_test_19 00105 #define FSFAT_FOPEN_TEST_20 fsfat_fopen_test_20 00106 #define FSFAT_FOPEN_TEST_21 fsfat_fopen_test_21 00107 #define FSFAT_FOPEN_TEST_22 fsfat_fopen_test_22 00108 #define FSFAT_FOPEN_TEST_23 fsfat_fopen_test_23 00109 #define FSFAT_FOPEN_TEST_24 fsfat_fopen_test_24 00110 #define FSFAT_FOPEN_TEST_25 fsfat_fopen_test_25 00111 #define FSFAT_FOPEN_TEST_26 fsfat_fopen_test_26 00112 #define FSFAT_FOPEN_TEST_27 fsfat_fopen_test_27 00113 #define FSFAT_FOPEN_TEST_28 fsfat_fopen_test_28 00114 #define FSFAT_FOPEN_TEST_29 fsfat_fopen_test_29 00115 #define FSFAT_FOPEN_TEST_30 fsfat_fopen_test_30 00116 00117 00118 /* support functions */ 00119 00120 /* 00121 * open tests that focus on testing fopen() 00122 * fsfat_handle_t fopen(const char* filename, char* data, size_t* len, fsfat_key_desc_t* kdesc) 00123 */ 00124 00125 /* file data for test_01 */ 00126 static fsfat_kv_data_t fsfat_fopen_test_01_kv_data[] = { 00127 { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"}, 00128 { NULL, NULL}, 00129 }; 00130 00131 00132 /** @brief 00133 * Split a file path into its component parts, setting '/' characters to '\0', and returning 00134 * pointers to the file path components in the parts array. For example, if 00135 * filepath = "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt" then 00136 * *parts[0] = "sd" 00137 * *parts[1] = "fopentst" 00138 * *parts[2] = "hello" 00139 * *parts[3] = "world" 00140 * *parts[4] = "animal" 00141 * *parts[5] = "wobbly" 00142 * *parts[6] = "dog" 00143 * *parts[7] = "foot" 00144 * *parts[8] = "frontlft.txt" 00145 * parts[9] = NULL 00146 * 00147 * ARGUMENTS 00148 * @param filepath IN file path string to split into component parts. Expected to start with '/' 00149 * @param parts IN OUT array to hold pointers to parts 00150 * @param num IN number of components available in parts 00151 * 00152 * @return On success, this returns the number of components in the filepath Returns number of compoee 00153 */ 00154 static int32_t fsfat_filepath_split(char *filepath, char *parts[], uint32_t num) 00155 { 00156 uint32_t i = 0; 00157 int32_t ret = -1; 00158 char *z = filepath; 00159 00160 while (i < num && *z != '\0') { 00161 if (*z == '/') { 00162 *z = '\0'; 00163 parts[i] = ++z; 00164 i++; 00165 } else { 00166 z++; 00167 } 00168 } 00169 if (*z == '\0' && i > 0) { 00170 ret = (int32_t) i; 00171 } 00172 return ret; 00173 } 00174 00175 00176 /** @brief 00177 * remove all directories and file in the given filepath 00178 * 00179 * ARGUMENTS 00180 * @param filepath IN file path string to split into component parts. Expected to start with '/' 00181 * 00182 * @return On success, this returns 0, otherwise < 0 is returned; 00183 */ 00184 int32_t fsfat_filepath_remove_all(char *filepath) 00185 { 00186 int32_t ret = -1; 00187 int32_t len = 0; 00188 char *fpathbuf = NULL; 00189 char *pos = NULL; 00190 00191 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00192 len = strlen(filepath); 00193 fpathbuf = (char *) malloc(len + 1); 00194 if (fpathbuf == NULL) { 00195 FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); 00196 return ret; 00197 } 00198 memset(fpathbuf, 0, len + 1); 00199 memcpy(fpathbuf, filepath, len); 00200 00201 /* delete the leaf node first, and then successively parent directories. */ 00202 pos = fpathbuf + strlen(fpathbuf); 00203 while (pos != fpathbuf) { 00204 /* If the remaining file path is the mount point path then finish as the mount point cannot be removed */ 00205 if (strlen(fpathbuf) == strlen(FSFAT_FOPEN_TEST_MOUNT_PT_PATH)) { 00206 if (strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) { 00207 break; 00208 } 00209 } 00210 ret = remove(fpathbuf); 00211 pos = strrchr(fpathbuf, '/'); 00212 *pos = '\0'; 00213 } 00214 if (fpathbuf) { 00215 free(fpathbuf); 00216 } 00217 return ret; 00218 } 00219 00220 00221 /** @brief 00222 * make all directories in the given filepath. Do not create the file if present at end of filepath 00223 * 00224 * ARGUMENTS 00225 * @param filepath IN file path containing directories and file 00226 * @param do_asserts IN set to true if function should assert on errors 00227 * 00228 * @return On success, this returns 0, otherwise < 0 is returned; 00229 */ 00230 static int32_t fsfat_filepath_make_dirs(char *filepath, bool do_asserts) 00231 { 00232 int32_t i = 0; 00233 int32_t num_parts = 0; 00234 int32_t len = 0; 00235 int32_t ret = -1; 00236 char *fpathbuf = NULL; 00237 char *buf = NULL; 00238 int pos = 0; 00239 char *parts[FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH]; 00240 00241 FSFAT_DBGLOG("%s:entered\n", __func__); 00242 /* find the dirs to create*/ 00243 memset(parts, 0, sizeof(parts)); 00244 len = strlen(filepath); 00245 fpathbuf = (char *) malloc(len + 1); 00246 if (fpathbuf == NULL) { 00247 FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); 00248 return ret; 00249 } 00250 memset(fpathbuf, 0, len + 1); 00251 memcpy(fpathbuf, filepath, len); 00252 num_parts = fsfat_filepath_split(fpathbuf, parts, FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH); 00253 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00254 "%s:Error: failed to split filepath (filename=\"%s\", num_parts=%d)\n", __func__, filepath, (int) num_parts); 00255 TEST_ASSERT_MESSAGE(num_parts > 0, fsfat_fopen_utest_msg_g); 00256 00257 /* Now create the directories on the directory path. 00258 * Skip creating dir for "/sd" which must be present */ 00259 buf = (char *) malloc(strlen(filepath) + 1); 00260 memset(buf, 0, strlen(filepath) + 1); 00261 pos = sprintf(buf, "/%s", parts[0]); 00262 for (i = 1; i < num_parts - 1; i++) { 00263 pos += sprintf(buf + pos, "/%s", parts[i]); 00264 FSFAT_DBGLOG("mkdir(%s)\n", buf); 00265 ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 00266 if (do_asserts == true) { 00267 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00268 "%s:Error: failed to create directory (filepath2=\"%s\", ret=%d, errno=%d)\n", __func__, buf, (int) ret, errno); 00269 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00270 } 00271 } 00272 00273 if (buf) { 00274 free(buf); 00275 } 00276 if (fpathbuf) { 00277 free(fpathbuf); 00278 } 00279 return ret; 00280 } 00281 00282 /** @brief 00283 * First and last test must format the SD card to FAT FS format: 00284 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00285 */ 00286 control_t fsfat_fopen_test_00(const size_t call_count) 00287 { 00288 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00289 (void) call_count; 00290 int32_t ret = -1; 00291 00292 fs.unmount(); 00293 ret = fs.format(&sd); 00294 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00295 "%s:Error: failed to format sdcard (ret=%d)\n", __func__, (int) ret); 00296 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00297 fs.mount(&sd); 00298 00299 return CaseNext; 00300 } 00301 00302 00303 /* FIX ME: errno not set correctly when error occurs. This indicates a problem with the implementation. */ 00304 00305 /** @brief 00306 * Basic fopen test which does the following: 00307 * - creates file and writes some data to the value blob. 00308 * - closes the newly created file. 00309 * - opens the file (r-only) 00310 * - reads the file data and checks its the same as the previously created data. 00311 * - closes the opened file 00312 * 00313 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00314 */ 00315 static control_t fsfat_fopen_test_01(const size_t call_count) 00316 { 00317 char *read_buf; 00318 int32_t ret = 0; 00319 size_t len = 0; 00320 fsfat_kv_data_t *node; 00321 FILE *fp = NULL; 00322 00323 FSFAT_DBGLOG("%s:entered\n", __func__); 00324 (void) call_count; 00325 node = fsfat_fopen_test_01_kv_data; 00326 00327 /* remove file and directory from a previous failed test run, if present */ 00328 fsfat_filepath_remove_all((char *) node->filename); 00329 00330 /* create dirs */ 00331 ret = fsfat_filepath_make_dirs((char *) node->filename, true); 00332 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00333 "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); 00334 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00335 00336 FSFAT_DBGLOG("%s:About to create new file (filename=\"%s\", data=\"%s\")\n", __func__, node->filename, node->value); 00337 fp = fopen(node->filename, "w+"); 00338 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00339 "%s:Error: failed to create file (filename=\"%s\", data=\"%s\")(ret=%d, errno=%d)\n", __func__, node->filename, 00340 node->value, (int) ret, errno); 00341 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00342 00343 FSFAT_DBGLOG("%s:length of file=%d (filename=\"%s\", data=\"%s\")\n", __func__, (int) len, node->filename, node->value); 00344 len = strlen(node->value); 00345 ret = fwrite((const void *) node->value, len, 1, fp); 00346 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00347 "%s:Error: failed to write file (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, 00348 (int) ret); 00349 TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); 00350 00351 FSFAT_DBGLOG("Created file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); 00352 ret = fclose(fp); 00353 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00354 "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); 00355 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00356 00357 /* now open the newly created key */ 00358 fp = NULL; 00359 fp = fopen(node->filename, "r"); 00360 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00361 "%s:Error: failed to open file for reading (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, 00362 node->value, (int) ret); 00363 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00364 00365 len = strlen(node->value) + 1; 00366 read_buf = (char *) malloc(len); 00367 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00368 "%s:Error: failed to allocated read buffer \n", __func__); 00369 TEST_ASSERT_MESSAGE(read_buf != NULL, fsfat_fopen_utest_msg_g); 00370 00371 FSFAT_DBGLOG("Opened file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); 00372 memset(read_buf, 0, len); 00373 ret = fread((void *) read_buf, len, 1, fp); 00374 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00375 "%s:Error: failed to read file (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, node->filename, 00376 node->value, read_buf, (int) ret); 00377 /* FIX ME: fread should return the number of items read, not 0 when an item is read successfully. 00378 * This indicates a problem with the implementation, as the correct data is read. The correct assert should be: 00379 * TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); 00380 * The following assert is curerntly used until the implementation is fixed 00381 */ 00382 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00383 00384 /* check read data is as expected */ 00385 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00386 "%s:Error: read value data (%s) != expected value data (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", 00387 __func__, read_buf, node->filename, node->value, read_buf, (int) ret); 00388 TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, fsfat_fopen_utest_msg_g); 00389 00390 if (read_buf) { 00391 free(read_buf); 00392 } 00393 ret = fclose(fp); 00394 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00395 "%s:Error: fclose() call failed (ret=%d, errno=%d).\n", __func__, (int) ret, errno); 00396 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00397 return CaseNext; 00398 } 00399 00400 static fsfat_kv_data_t fsfat_fopen_test_02_data[] = { 00401 FSFAT_INIT_1_TABLE_MID_NODE, 00402 { NULL, NULL}, 00403 }; 00404 00405 /** 00406 * @brief test to fopen() a pre-existing key and try to write it, which should fail 00407 * as by default pre-existing keys are opened read-only 00408 * 00409 * Basic open test which does the following: 00410 * - creates file with default rw perms and writes some data to the value blob. 00411 * - closes the newly created file. 00412 * - opens the file with the default permissions (read-only) 00413 * - tries to write the file data which should fail because file was not opened with write flag set. 00414 * - closes the opened key 00415 * 00416 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00417 */ 00418 control_t fsfat_fopen_test_02(const size_t call_count) 00419 { 00420 int32_t ret = -1; 00421 size_t len = 0; 00422 FILE *fp = NULL; 00423 00424 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00425 (void) call_count; 00426 len = strlen(fsfat_fopen_test_02_data[0].value); 00427 ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); 00428 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00429 "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); 00430 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00431 00432 /* by default, owner of key opens with read-only permissions*/ 00433 fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); 00434 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00435 "%s:Error: failed to open file (filename=\"%s\", ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); 00436 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00437 00438 len = strlen(fsfat_fopen_test_02_data[0].value); 00439 ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); 00440 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00441 "%s:Error: call to fwrite() succeeded when should have failed for read-only file (filename=\"%s\")(ret=%d).\n", 00442 __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); 00443 TEST_ASSERT_MESSAGE(ret <= 0, fsfat_fopen_utest_msg_g); 00444 00445 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", 00446 __func__); 00447 TEST_ASSERT_MESSAGE(fclose(fp) == 0, fsfat_fopen_utest_msg_g); 00448 00449 return CaseNext; 00450 } 00451 00452 00453 /** 00454 * @brief test to fopen() a pre-existing file and try to write it, which should succeed 00455 * because the key was opened read-write permissions explicitly 00456 * 00457 * Basic open test which does the following: 00458 * - creates file with default rw perms and writes some data to the value blob. 00459 * - closes the newly created file. 00460 * - opens the file with the rw permissions (non default) 00461 * - tries to write the file data which should succeeds because file was opened with write flag set. 00462 * - closes the opened key 00463 * 00464 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00465 */ 00466 control_t fsfat_fopen_test_03(const size_t call_count) 00467 { 00468 int32_t ret = -1; 00469 size_t len = 0; 00470 FILE *fp = NULL; 00471 00472 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00473 (void) call_count; 00474 len = strlen(fsfat_fopen_test_02_data[0].value); 00475 ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); 00476 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00477 "%s:Error: failed to create file in store (ret=%d).\n", __func__, (int) ret); 00478 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00479 00480 /* opens with read-write permissions*/ 00481 fp = fopen(fsfat_fopen_test_02_data[0].filename, "w+"); 00482 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00483 "%s:Error: failed to open file (filename=\"%s\")(ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); 00484 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00485 00486 len = strlen(fsfat_fopen_test_02_data[0].value); 00487 ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); 00488 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00489 "%s:Error: call to fwrite() failed when should have succeeded (filename=\"%s\", ret=%d).\n", __func__, 00490 fsfat_fopen_test_02_data[0].filename, (int) ret); 00491 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00492 00493 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", 00494 __func__); 00495 TEST_ASSERT_MESSAGE(fclose(fp) >= 0, fsfat_fopen_utest_msg_g); 00496 00497 /* clean-up */ 00498 ret = remove(fsfat_fopen_test_02_data[0].filename); 00499 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00500 "%s:Error: unable to delete file (filename=%s, ret=%d) .\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); 00501 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00502 00503 return CaseNext; 00504 } 00505 00506 00507 /** @brief test to call fopen() with a filename string that exceeds the maximum length 00508 * - chanFS supports the exFAT format which should support 255 char filenames 00509 * - check that filenames of this length can be created 00510 * 00511 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00512 */ 00513 control_t fsfat_fopen_test_04(const size_t call_count) 00514 { 00515 char filename_good[FSFAT_FILENAME_MAX_LENGTH + 1]; 00516 char filename_bad[FSFAT_FILENAME_MAX_LENGTH + 2]; 00517 int32_t ret = -1; 00518 size_t len = 0; 00519 00520 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00521 (void) call_count; 00522 00523 memset(filename_good, 0, FSFAT_FILENAME_MAX_LENGTH + 1); 00524 memset(filename_bad, 0, FSFAT_FILENAME_MAX_LENGTH + 2); 00525 ret = fsfat_test_filename_gen(filename_good, FSFAT_FILENAME_MAX_LENGTH); 00526 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00527 "%s:Error: unable to generate filename_good.\n", __func__); 00528 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00529 00530 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00531 "%s:Error: filename_good is not the correct length (filename_good=%s, len=%d, expected=%d).\n", __func__, filename_good, 00532 (int) strlen(filename_good), (int) FSFAT_FILENAME_MAX_LENGTH); 00533 TEST_ASSERT_MESSAGE(strlen(filename_good) == FSFAT_FILENAME_MAX_LENGTH, fsfat_fopen_utest_msg_g); 00534 00535 ret = fsfat_test_filename_gen(filename_bad, FSFAT_FILENAME_MAX_LENGTH + 1); 00536 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00537 "%s:Error: unable to generate filename_bad.\n", __func__); 00538 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00539 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00540 "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), 00541 (int) FSFAT_FILENAME_MAX_LENGTH + 1); 00542 TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSFAT_FILENAME_MAX_LENGTH + 1, fsfat_fopen_utest_msg_g); 00543 00544 len = strlen(filename_good); 00545 ret = fsfat_test_create(filename_good, filename_good, len); 00546 /* FIXME: 00547 * The current implementation can create file with a filename with 9 chars (more than the 8 restriction of FAT32 Short File Names). 00548 * However, the exFAT 255 char filesnames is not supported and hence the following is commented out. Find out what is 00549 * the supported max filename length and change this testcase according. 00550 * 00551 * FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (filename=%s, ret=%d).\n", __func__, filename_good, (int) ret); 00552 * TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00553 */ 00554 00555 len = strlen(filename_bad); 00556 ret = fsfat_test_create(filename_bad, filename_bad, len); 00557 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00558 "%s:Error: created file in store for filename_bad when should have failed (filename=%s, ret=%d).\n", __func__, 00559 filename_bad, (int) ret); 00560 TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); 00561 return CaseNext; 00562 } 00563 00564 00565 /// @cond FSFAT_DOXYGEN_DISABLE 00566 typedef struct fsfat_fopen_kv_name_ascii_node { 00567 uint32_t code; 00568 uint32_t f_allowed : 1; 00569 } fsfat_fopen_kv_name_ascii_node; 00570 /// @endcond 00571 00572 static const uint32_t fsfat_fopen_kv_name_ascii_table_code_sentinel_g = 256; 00573 00574 /*@brief table recording ascii character codes permitted in kv names */ 00575 static fsfat_fopen_kv_name_ascii_node fsfat_fopen_kv_name_ascii_table[] = { 00576 {0, true}, /* code 0-33 allowed*/ 00577 {34, false}, /* '"' not allowed */ 00578 {35, true}, /* allowed */ 00579 {42, false}, /* '*' not allowed */ 00580 {43, true}, /* allowed */ 00581 {47, false}, /* '/' not allowed */ 00582 {48, true}, /* allowed */ 00583 {58, false}, /* ':' not allowed */ 00584 {59, true}, /* allowed */ 00585 {60, false}, /* '<' not allowed */ 00586 {61, true}, /* allowed */ 00587 {62, false}, /* '?', '>' not allowed */ 00588 {64, true}, /* allowed */ 00589 {92, false}, /* '\' not allowed */ 00590 {93, true}, /* allowed */ 00591 {124, false}, /* '!' not allowed */ 00592 {125, true}, /* allowed */ 00593 {127, false}, /* DEL not allowed */ 00594 {128, true}, /* allowed */ 00595 {fsfat_fopen_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */ 00596 }; 00597 00598 00599 /// @cond FSFAT_DOXYGEN_DISABLE 00600 enum fsfat_fopen_kv_name_pos { 00601 fsfat_fopen_kv_name_pos_start = 0x0, 00602 fsfat_fopen_kv_name_pos_mid, 00603 fsfat_fopen_kv_name_pos_end, 00604 fsfat_fopen_kv_name_pos_max 00605 }; 00606 /// @endcond 00607 00608 /** @brief test to call fopen() with filename that in includes illegal characters 00609 * - the character(s) can be at the beginning of the filename 00610 * - the character(s) can be at the end of the filename 00611 * - the character(s) can be somewhere within the filename string 00612 * - a max-length string of random characters (legal and illegal) 00613 * - a max-length string of random illegal characters only 00614 * 00615 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00616 */ 00617 control_t fsfat_fopen_test_05(const size_t call_count) 00618 { 00619 bool f_allowed = false; 00620 const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; 00621 const char *basename = "goodfile"; 00622 const char *extname = "txt"; 00623 const size_t basename_len = strlen(basename); 00624 const size_t filename_len = strlen(mnt_pt) + strlen(basename) + strlen(extname) + 00625 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ 00626 char filename[FSFAT_BUF_MAX_LENGTH]; 00627 size_t len = 0; 00628 uint32_t j = 0; 00629 int32_t ret = 0; 00630 fsfat_fopen_kv_name_ascii_node *node = NULL; 00631 uint32_t pos; 00632 00633 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00634 (void) call_count; 00635 00636 #ifdef FSFAT_DEBUG 00637 /* symbol only used why debug is enabled */ 00638 const char *pos_str = NULL; 00639 #endif 00640 00641 /* create bad keyname strings with invalid character code at start of keyname */ 00642 node = fsfat_fopen_kv_name_ascii_table; 00643 memset(filename, 0, FSFAT_BUF_MAX_LENGTH); 00644 while (node->code != fsfat_fopen_kv_name_ascii_table_code_sentinel_g) { 00645 /* loop over range */ 00646 for (j = node->code; j < (node + 1)->code; j++) { 00647 if ((j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { 00648 FSFAT_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j); 00649 continue; 00650 } 00651 00652 /* set the start, mid, last character of the name to the test char code */ 00653 for (pos = (uint32_t) fsfat_fopen_kv_name_pos_start; pos < (uint32_t) fsfat_fopen_kv_name_pos_max; pos++) { 00654 len = snprintf(filename, filename_len + 1, "%s/%s.%s", mnt_pt, basename, extname); 00655 /* overwrite a char at the pos start, mid, end of the filename with an ascii char code (both illegal and legal)*/ 00656 switch (pos) { 00657 case fsfat_fopen_kv_name_pos_start: 00658 filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/ 00659 break; 00660 case fsfat_fopen_kv_name_pos_mid: 00661 /* create bad keyname strings with invalid character code in the middle of keyname */ 00662 filename[5 + basename_len / 2] = (char) j; 00663 break; 00664 case fsfat_fopen_kv_name_pos_end: 00665 /* create bad keyname strings with invalid character code at end of keyname */ 00666 filename[5 + basename_len - 1] = (char) j; 00667 break; 00668 default: 00669 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00670 "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos); 00671 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00672 break; 00673 } 00674 00675 #ifdef FSFAT_DEBUG 00676 /* processing only required when debug trace enabled */ 00677 switch (pos) { 00678 case fsfat_fopen_kv_name_pos_start: 00679 pos_str = "start"; 00680 break; 00681 case fsfat_fopen_kv_name_pos_mid: 00682 pos_str = "middle"; 00683 break; 00684 case fsfat_fopen_kv_name_pos_end: 00685 pos_str = "end"; 00686 break; 00687 default: 00688 break; 00689 } 00690 #endif 00691 ret = fsfat_test_create(filename, (const char *) filename, len); 00692 00693 /* special cases */ 00694 switch (j) { 00695 //case 0 : 00696 //case 46 : 00697 // switch(pos) 00698 // { 00699 // /* for code = 0 (null terminator). permitted at mid and end of string */ 00700 // /* for code = 46 ('.'). permitted at mid and end of string but not at start */ 00701 // case fsfat_fopen_kv_name_pos_start: 00702 // f_allowed = false; 00703 // break; 00704 // case fsfat_fopen_kv_name_pos_mid: 00705 // case fsfat_fopen_kv_name_pos_end: 00706 // default: 00707 // f_allowed = true; 00708 // break; 00709 // } 00710 // break; 00711 default: 00712 f_allowed = node->f_allowed; 00713 break; 00714 } 00715 if (f_allowed == true) { 00716 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00717 "%s:Error: failed to create file in store when filename contains valid characters (code=%d, ret=%d).\n", __func__, 00718 (int) j, (int) ret); 00719 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00720 /* revert FSFAT_LOG for more trace */ 00721 FSFAT_DBGLOG("Successfully created a file with valid keyname containing ascii character code %d (%c) at the %s of the keyname.\n", 00722 (int) j, (int) j, pos_str); 00723 FSFAT_LOG("%c", '.'); 00724 00725 ret = fsfat_test_delete(filename); 00726 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00727 "%s:Error: failed to delete file previously created (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); 00728 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 00729 } else { 00730 /*node->f_allowed == false => not allowed to create kv name with ascii code */ 00731 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00732 "%s:Error: created file in store when filename contains an invalid character (code=%d, ret=%d).\n", __func__, (int) j, 00733 (int) ret); 00734 TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); 00735 /* revert FSFAT_LOG for more trace */ 00736 FSFAT_DBGLOG("Successfully failed to create a file with an invalid keyname containing ascii character code %d at the %s of the keyname.\n", 00737 (int) j, pos_str); 00738 FSFAT_LOG("%c", '.'); 00739 } 00740 } 00741 } 00742 node++; 00743 } 00744 00745 FSFAT_LOG("%c", '\n'); 00746 return CaseNext; 00747 } 00748 00749 00750 static const char fsfat_fopen_ascii_illegal_buf_g[] = "\"�'*+,./:;<=>?[\\]|"; 00751 00752 /** @brief test to call fopen() with filename that in includes 00753 * illegal characters 00754 * - a max-length string of random illegal characters only 00755 * 00756 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00757 */ 00758 control_t fsfat_fopen_test_06(const size_t call_count) 00759 { 00760 const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; 00761 const char *extname = "txt"; 00762 const size_t filename_len = strlen(mnt_pt) + FSFAT_MAX_FILE_BASENAME + strlen(extname) + 00763 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ 00764 char filename[FSFAT_BUF_MAX_LENGTH]; 00765 int32_t i = 0; 00766 int32_t j = 0; 00767 uint32_t pos = 0; 00768 uint32_t len = 0; 00769 int32_t ret = -1; 00770 size_t buf_data_max = 0; 00771 00772 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00773 (void) call_count; 00774 00775 memset(filename, 0, FSFAT_BUF_MAX_LENGTH); 00776 /* create bad keyname strings with invalid character code at start of keyname */ 00777 buf_data_max = strlen(fsfat_fopen_ascii_illegal_buf_g); 00778 00779 /* generate a number of illegal filenames */ 00780 for (j = 0; i < FSFAT_MAX_FILE_BASENAME; j++) { 00781 /* generate a kv name of illegal chars*/ 00782 len = snprintf(filename, filename_len + 1, "%s/", mnt_pt); 00783 for (i = 0; i < FSFAT_MAX_FILE_BASENAME; i++) { 00784 pos = rand() % (buf_data_max + 1); 00785 len += snprintf(filename + len, filename_len + 1, "%c", fsfat_fopen_ascii_illegal_buf_g[pos]); 00786 00787 } 00788 len += snprintf(filename + len, filename_len + 1, ".%s", extname); 00789 ret = fsfat_test_create(filename, filename, len); 00790 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00791 "%s:Error: created file when filename contains invalid characters (filename=%s, ret=%d).\n", __func__, filename, 00792 (int) ret); 00793 TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); 00794 } 00795 return CaseNext; 00796 } 00797 00798 00799 /** @brief test for errno reporting on a failed fopen()call 00800 * 00801 * This test does the following: 00802 * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. 00803 * - checks that errno is not 0 as there is an error. 00804 * - checks that ferror() returns 1 indicating an error exists. 00805 * 00806 * Note: see NOTE_1 below. 00807 * 00808 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00809 */ 00810 control_t fsfat_fopen_test_07(const size_t call_count) 00811 { 00812 FILE *f = NULL; 00813 int ret = -1; 00814 int errno_val = 0; 00815 const char *filename = sd_badfile_path; 00816 00817 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00818 (void) call_count; 00819 00820 errno = 0; 00821 /* this is expect to fail as the file doesnt exist */ 00822 f = fopen(filename, "r"); 00823 00824 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00825 "%s:Error: opened non-existent file for reading (filename=%s, f=%p).\n", __func__, filename, f); 00826 TEST_ASSERT_MESSAGE(f == NULL, fsfat_fopen_utest_msg_g); 00827 00828 /* check errno is set correctly */ 00829 #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) 00830 /* Store errno so the current value set is not changed by new function call */ 00831 errno_val = errno; 00832 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00833 "%s:Error: errno has unexpected value (errno != 0 expected) (filename=%s, errno=%d).\n", __func__, filename, errno); 00834 TEST_ASSERT_MESSAGE(errno_val != 0, fsfat_fopen_utest_msg_g); 00835 #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ 00836 return CaseNext; 00837 } 00838 00839 00840 /** @brief test for operation of clearerr() and ferror() 00841 * 00842 * The test does the following: 00843 * - opens and then closes a file, but keeps a copy of the FILE pointer fp. 00844 * - set errno to 0. 00845 * - write to the close file with fwrite(fp) which should return 0 (no writes) and set the errno. 00846 * - check the error condition is set with ferror(). 00847 * - clear the error with clearerr(). 00848 * - check the error condition is reset with ferror(). 00849 * 00850 * NOTE_1: GCC/ARMCC support for setting errno 00851 * - Documentation (e.g. fwrite() man page) does not explicity say fwrite() sets errno 00852 * (e.g. for an fwrite() on a read-only file). 00853 * - GCC libc fwrite() appears to set errno as expected. 00854 * - ARMCC & IAR libc fwrite() appears not to set errno. 00855 * 00856 * The following ARMCC documents are silent on whether fwrite() sets errno: 00857 * - "ARM C and C++ Libraries and Floating-Point Support". 00858 * - "RL-ARM User Guide fwrite() section". 00859 * 00860 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00861 */ 00862 control_t fsfat_fopen_test_08(const size_t call_count) 00863 { 00864 FILE *fp = NULL; 00865 int ret = -1; 00866 int ret_ferror = -1; 00867 const char *filename = sd_testfile_path; 00868 00869 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00870 (void) call_count; 00871 00872 errno = 0; 00873 fp = fopen(filename, "w+"); 00874 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00875 "%s:Error: failed to open file (filename=%s, f=%p).\n", __func__, filename, fp); 00876 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00877 00878 /* close the fp but then try to read or write it */ 00879 ret = fclose(fp); 00880 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00881 "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); 00882 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00883 00884 /* open file */ 00885 errno = 0; 00886 fp = fopen(filename, "r"); 00887 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00888 "%s:Error: failed to open file for reading (filename=\"%s\", ret=%d)\n", __func__, filename, (int) ret); 00889 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00890 00891 /* Perform fwrite() operation that will fail. */ 00892 errno = 0; 00893 ret = fwrite("42!", 4, 1, fp); 00894 00895 ret_ferror = ferror(fp); 00896 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00897 "%s:Error: ferror() failed to report error (filename=%s, ret_ferror=%d).\n", __func__, filename, (int) ret_ferror); 00898 TEST_ASSERT_MESSAGE(ret_ferror != 0, fsfat_fopen_utest_msg_g); 00899 00900 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00901 "%s:Error: fwrite successfully wrote to read-only file (filename=%s, ret=%d).\n", __func__, filename, (int) ret); 00902 /* the fwrite() should fail and return 0. */ 00903 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00904 00905 #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) 00906 /* check that errno is set. ARMCC appears not to set errno for fwrite() failure. */ 00907 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00908 "%s:Error: unexpected zero value for errno (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); 00909 TEST_ASSERT_MESSAGE(errno != 0, fsfat_fopen_utest_msg_g); 00910 00911 /* check that errno is set to the expected value (this may change differ for different libc's) */ 00912 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00913 "%s:Error: errno != EBADF (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); 00914 TEST_ASSERT_MESSAGE(errno == EBADF, fsfat_fopen_utest_msg_g); 00915 #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ 00916 00917 /* check clearerr() return clears the error */ 00918 clearerr(fp); 00919 ret = ferror(fp); 00920 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00921 "%s:Error: ferror() did not return zero value when error has been cleared (filename=%s, ret=%d).\n", __func__, filename, 00922 (int) ret); 00923 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00924 00925 fclose(fp); 00926 return CaseNext; 00927 } 00928 00929 00930 /** @brief test for operation of ftell() 00931 * 00932 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00933 */ 00934 control_t fsfat_fopen_test_09(const size_t call_count) 00935 { 00936 FILE *fp = NULL; 00937 int ret = -1; 00938 int32_t len = 0; 00939 00940 FSFAT_FENTRYLOG("%s:entered\n", __func__); 00941 (void) call_count; 00942 00943 /* create a file of a certain length */ 00944 len = strlen(fsfat_fopen_test_02_data[0].value); 00945 ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); 00946 00947 errno = 0; 00948 /* Open the file for reading so the file is not truncated to 0 length. */ 00949 fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); 00950 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00951 "%s:Error: failed to open file (filename=%s, fp=%p, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, fp, 00952 errno); 00953 TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); 00954 00955 errno = 0; 00956 ret = fseek(fp, 0, SEEK_END); 00957 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00958 "%s:Error: fseek() failed to SEEK_END (filename=%s, ret=%d, errno=%d).\n", __func__, 00959 fsfat_fopen_test_02_data[0].filename, (int) ret, errno); 00960 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00961 00962 errno = 0; 00963 ret = ftell(fp); 00964 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00965 "%s:Error: ftell() failed to report correct offset value (filename=%s, ret=%d, errno=%d).\n", __func__, 00966 fsfat_fopen_test_02_data[0].filename, (int) ret, errno); 00967 TEST_ASSERT_MESSAGE(ret == len, fsfat_fopen_utest_msg_g); 00968 00969 errno = 0; 00970 ret = fclose(fp); 00971 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 00972 "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); 00973 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 00974 00975 return CaseNext; 00976 } 00977 00978 00979 /* file data for test_10 */ 00980 static fsfat_kv_data_t fsfat_fopen_test_10_kv_data[] = { 00981 { "/sd/test_10/testfile.txt", "test_data"}, 00982 { NULL, NULL}, 00983 }; 00984 00985 /** @brief test for operation of remove() 00986 * 00987 * Performs the following tests: 00988 * 1. test remove() on a file that exists. This should succeed. 00989 * 2. test remove() on a dir that exists. This should succeed. 00990 * 3. test remove() on a file that doesnt exist. This should fail. check errno set. 00991 * 4. test remove() on a dir that doesnt exist. This should fail. check errno set. 00992 * 00993 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 00994 */ 00995 control_t fsfat_fopen_test_10(const size_t call_count) 00996 { 00997 char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; 00998 char *pos = NULL; 00999 int32_t ret = -1; 01000 size_t len = 0; 01001 fsfat_kv_data_t *node = fsfat_fopen_test_10_kv_data; 01002 01003 FSFAT_FENTRYLOG("%s:entered\n", __func__); 01004 (void) call_count; 01005 01006 TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01007 01008 /* start from a known state i.e. directory to be created in not present */ 01009 fsfat_filepath_remove_all((char *) node->filename); 01010 01011 /* (1) */ 01012 errno = 0; 01013 ret = fsfat_filepath_make_dirs((char *) node->filename, false); 01014 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01015 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); 01016 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01017 01018 len = strlen(node->value); 01019 ret = fsfat_test_create(node->filename, (char *) node->value, len); 01020 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01021 "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); 01022 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 01023 01024 ret = remove(node->filename); 01025 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01026 "%s:Error: delete file operation failed (filename=%s, ret=%d) .\n", __func__, node->filename, (int) ret); 01027 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01028 01029 /* (3) */ 01030 ret = remove(node->filename); 01031 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01032 "%s:Error: deleted a file that doesn't exist (filename=%s, ret=%d, errno=%d) .\n", __func__, node->filename, (int) ret, 01033 errno); 01034 TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); 01035 01036 /* (2) */ 01037 memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01038 memcpy(buf, node->filename, strlen(node->filename)); 01039 pos = strrchr(buf, '/'); 01040 *pos = '\0'; 01041 ret = remove(buf); 01042 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01043 "%s:Error: delete directory operation failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, 01044 errno); 01045 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01046 01047 /* (4) */ 01048 ret = remove(buf); 01049 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01050 "%s:Error: deleted a directory that doesn't exist (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, 01051 errno); 01052 TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); 01053 01054 return CaseNext; 01055 } 01056 01057 01058 /* file data for test_11 */ 01059 static fsfat_kv_data_t fsfat_fopen_test_11_kv_data[] = { 01060 { "/sd/test_11/step0.txt", "test_data"}, 01061 { "/sd/test_11/step1.txt", "test_data"}, 01062 { "/sd/test_11/subdir/step3.txt", "test_data"}, 01063 { NULL, NULL}, 01064 }; 01065 01066 /** @brief test for operation of rename() 01067 * 01068 * This test does the following: 01069 * 1) test rename() on a file that exists to a new filename within the same directory. 01070 * 2) test rename() on a file that exists to a new filename within a different directory. 01071 * 01072 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01073 */ 01074 control_t fsfat_fopen_test_11(const size_t call_count) 01075 { 01076 int32_t ret = -1; 01077 size_t len = 0; 01078 fsfat_kv_data_t *node = fsfat_fopen_test_11_kv_data; 01079 01080 FSFAT_FENTRYLOG("%s:entered\n", __func__); 01081 (void) call_count; 01082 01083 TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01084 01085 /* start from a known state i.e. directory to be created in not present, files not present */ 01086 while (node->filename != NULL) { 01087 fsfat_filepath_remove_all((char *) node->filename); 01088 node++; 01089 } 01090 01091 /* create file and directories ready for rename() tests */ 01092 errno = 0; 01093 node = fsfat_fopen_test_11_kv_data; 01094 ret = fsfat_filepath_make_dirs((char *) node->filename, false); 01095 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01096 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); 01097 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01098 01099 len = strlen(node->value); 01100 ret = fsfat_test_create(node->filename, (char *) node->value, len); 01101 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01102 "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); 01103 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 01104 01105 errno = 0; 01106 node = &fsfat_fopen_test_11_kv_data[2]; 01107 ret = fsfat_filepath_make_dirs((char *) node->filename, false); 01108 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01109 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); 01110 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01111 01112 /* (1) */ 01113 ret = rename(fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename); 01114 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01115 "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, 01116 fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename, (int) ret, errno); 01117 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01118 01119 /* (2) */ 01120 ret = rename(fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename); 01121 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01122 "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, 01123 fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename, (int) ret, errno); 01124 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01125 01126 return CaseNext; 01127 } 01128 01129 01130 /* file data for test_12 */ 01131 static fsfat_kv_data_t fsfat_fopen_test_12_kv_data[] = { 01132 { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"}, 01133 { "/sd/test_12/testfil2.txt", "testfil2.txt"}, 01134 { "/sd/test_12/testfil3.txt", "testfil3.txt"}, 01135 { "/sd/test_12/testfil4.txt", "testfil4.txt"}, 01136 { "/sd/test_12/testfil5.txt", "testfil5.txt"}, 01137 { NULL, NULL}, 01138 }; 01139 01140 /** @brief test for operation of readdir(). 01141 * 01142 * Note, rewinddir(), telldir() and seekdir() dont appear to work reliably. 01143 * opendir() not available on ARM/IAR toolchains. 01144 * 01145 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01146 */ 01147 control_t fsfat_fopen_test_12(const size_t call_count) 01148 { 01149 char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; 01150 char *pos = NULL; 01151 int32_t count = 0; 01152 int32_t ret = -1; 01153 size_t len = 0; 01154 DIR *dir; 01155 struct dirent *dp; 01156 fsfat_kv_data_t *node = fsfat_fopen_test_12_kv_data; 01157 01158 FSFAT_FENTRYLOG("%s:entered\n", __func__); 01159 (void) call_count; 01160 01161 #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) 01162 01163 /* start from a known state i.e. directory to be created in not present */ 01164 while (node->filename != NULL) { 01165 fsfat_filepath_remove_all((char *) node->filename); 01166 node++; 01167 } 01168 01169 /* create a file */ 01170 node = fsfat_fopen_test_12_kv_data; 01171 errno = 0; 01172 ret = fsfat_filepath_make_dirs((char *) node->filename, false); 01173 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01174 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); 01175 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01176 01177 node = fsfat_fopen_test_12_kv_data; 01178 while (node->filename != NULL) { 01179 len = strlen(node->value); 01180 ret = fsfat_test_create(node->filename, (char *) node->value, len); 01181 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01182 "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); 01183 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 01184 node++; 01185 } 01186 01187 node = fsfat_fopen_test_12_kv_data; 01188 memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01189 memcpy(buf, node->filename, strlen(node->filename)); 01190 pos = strrchr(buf, '/'); 01191 *pos = '\0'; 01192 dir = opendir(buf); 01193 01194 while ((dp = readdir(dir)) != NULL) { 01195 FSFAT_DBGLOG("%s: filename: \"%s\"\n", __func__, dp->d_name); 01196 TEST_ASSERT_MESSAGE(dp != 0, "Error: readdir() failed\n"); 01197 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01198 "%s:Error: unexpected object name (name=%s, expected=%s).\n", __func__, dp->d_name, 01199 fsfat_fopen_test_12_kv_data[count].value); 01200 TEST_ASSERT_MESSAGE(strncmp(dp->d_name, fsfat_fopen_test_12_kv_data[count].value, 01201 strlen(fsfat_fopen_test_12_kv_data[count].value)) == 0, fsfat_fopen_utest_msg_g); 01202 count++; 01203 } 01204 closedir(dir); 01205 01206 /* cleanup */ 01207 node = fsfat_fopen_test_12_kv_data; 01208 while (node->filename != NULL) { 01209 fsfat_filepath_remove_all((char *) node->filename); 01210 node++; 01211 } 01212 #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ 01213 return CaseNext; 01214 } 01215 01216 01217 /* file data for test_13 */ 01218 static fsfat_kv_data_t fsfat_fopen_test_13_kv_data[] = { 01219 /* a file is included in the filepath even though its not created by the test, 01220 * as the fsfat_filepath_make_dirs() works with it present. */ 01221 { "/sd/test_13/dummy.txt", "testdir"}, 01222 { NULL, NULL}, 01223 }; 01224 /** @brief test for operation of mkdir()/remove() 01225 * 01226 * This test checks that: 01227 * - The mkdir() function successfully creates a directory that is not already present. 01228 * - The mkdir() function returns EEXIST when trying to create a directory thats already present. 01229 * - The remove() function successfully removes a directory that is present. 01230 * 01231 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01232 */ 01233 control_t fsfat_fopen_test_13(const size_t call_count) 01234 { 01235 int32_t ret = 0; 01236 01237 FSFAT_DBGLOG("%s:entered\n", __func__); 01238 (void) call_count; 01239 01240 /* start from a known state i.e. directory to be created in not present */ 01241 fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); 01242 01243 errno = 0; 01244 ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); 01245 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01246 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, 01247 (int) ret, errno); 01248 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01249 01250 /* check that get a suitable error when try to create it again.*/ 01251 errno = 0; 01252 ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); 01253 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01254 "%s:Error: permitted to create directory when already exists (dirname=%s, ret=%d, errno=%d)\n", __func__, 01255 fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); 01256 TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); 01257 01258 /* check errno is as expected */ 01259 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01260 "%s:Error: errno != EEXIST (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, 01261 (int) ret, errno); 01262 TEST_ASSERT_MESSAGE(errno == EEXIST, fsfat_fopen_utest_msg_g); 01263 01264 ret = fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); 01265 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01266 "%s:Error: failed to remove directory (dirname=%s, ret=%d, errno=%d)\n", __func__, 01267 fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); 01268 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01269 01270 return CaseNext; 01271 } 01272 01273 /* file data for test_14 */ 01274 static fsfat_kv_data_t fsfat_fopen_test_14_kv_data[] = { 01275 /* a file is included in the filepath even though its not created by the test, 01276 * as the fsfat_filepath_make_dirs() works with it present. */ 01277 { "/sd/test_14/testfile.txt", "testdata"}, 01278 { NULL, NULL}, 01279 }; 01280 01281 /** @brief test for operation of stat() 01282 * 01283 * stat() is currently no supported by ARMCC and IAR toolchains libc. 01284 * 01285 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01286 */ 01287 control_t fsfat_fopen_test_14(const size_t call_count) 01288 { 01289 #if ! defined(__ARMCC_VERSION) && defined(__GNUC__) 01290 01291 char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; 01292 char *pos = NULL; 01293 int32_t ret = -1; 01294 size_t len = 0; 01295 struct stat file_stat; 01296 fsfat_kv_data_t *node = fsfat_fopen_test_14_kv_data; 01297 01298 FSFAT_FENTRYLOG("%s:entered\n", __func__); 01299 (void) call_count; 01300 01301 TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01302 01303 /* start from a known state i.e. directory to be created in not present */ 01304 fsfat_filepath_remove_all((char *) node->filename); 01305 01306 /* Create file in a directory. */ 01307 errno = 0; 01308 ret = fsfat_filepath_make_dirs((char *) node->filename, false); 01309 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01310 "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); 01311 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01312 01313 len = strlen(node->value); 01314 ret = fsfat_test_create(node->filename, (char *) node->value, len); 01315 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01316 "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); 01317 TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); 01318 01319 /* Test stat() on the file returns the correct attribute set */ 01320 memset(&file_stat, 0, sizeof(file_stat)); 01321 ret = stat(node->filename, &file_stat); 01322 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01323 "%s:Error: stat() operation on file failed (filename=%s, ret=%d, errno=%d).\n", __func__, node->filename, (int) ret, 01324 errno); 01325 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01326 01327 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01328 "%s:Error: expected st_mode S_IFREG flag not set (filename=%s).\n", __func__, node->filename); 01329 TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) == S_IFREG, fsfat_fopen_utest_msg_g); 01330 01331 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01332 "%s:Error: unexpected st_mode S_IFDIR flag set (filename=%s).\n", __func__, node->filename); 01333 TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) != S_IFDIR, fsfat_fopen_utest_msg_g); 01334 01335 /* Test stat() on the directory returns the correct attribute set */ 01336 memset(&file_stat, 0, sizeof(file_stat)); 01337 memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); 01338 memcpy(buf, node->filename, strlen(node->filename)); 01339 pos = strrchr(buf, '/'); 01340 *pos = '\0'; 01341 ret = stat(buf, &file_stat); 01342 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01343 "%s:Error: stat() operation on directory failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, 01344 errno); 01345 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01346 01347 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01348 "%s:Error: unexpected st_mode S_IFREG flag set (directory name=%s).\n", __func__, buf); 01349 TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) != S_IFREG, fsfat_fopen_utest_msg_g); 01350 01351 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01352 "%s:Error: expected st_mode S_IFDIR flag not set (directory name=%s).\n", __func__, buf); 01353 TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) == S_IFDIR, fsfat_fopen_utest_msg_g); 01354 01355 /* clean up after successful test */ 01356 fsfat_filepath_remove_all((char *) node->filename); 01357 01358 #endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ 01359 return CaseNext; 01360 } 01361 01362 /** @brief test for operation of SDFileSystem::format() 01363 * 01364 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01365 */ 01366 control_t fsfat_fopen_test_15(const size_t call_count) 01367 { 01368 01369 FSFAT_FENTRYLOG("%s:entered\n", __func__); 01370 (void) call_count; 01371 int32_t ret = -1; 01372 01373 /* the allocation_unit of 0 means chanFS will use the default for the card (varies according to capacity). */ 01374 fs.unmount(); 01375 ret = fs.format(&sd); 01376 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01377 "%s:Error: failed to format sdcard (ret=%d)\n", __func__, (int) ret); 01378 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01379 fs.mount(&sd); 01380 return CaseNext; 01381 } 01382 01383 01384 /* @brief test utility function to create a file of a given size. 01385 * 01386 * A reference data table is used of so that the data file can be later be 01387 * checked with fsfat_test_check_data_file(). 01388 * 01389 * @param filename name of the file including path 01390 * @param data data to store in file 01391 * @param len number of bytes of data present in the data buffer. 01392 */ 01393 int32_t fsfat_test_create_data_file(const char *filename, size_t len) 01394 { 01395 int32_t ret = -1; 01396 FILE *fp = NULL; 01397 size_t write_len = 0; 01398 size_t written_len = 0; 01399 int32_t exp = 0; 01400 const int32_t exp_max = 8; /* so as not to exceed FSFAT_TEST_BYTE_DATA_TABLE_SIZE/2 */ 01401 01402 FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); 01403 TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); 01404 fp = fopen(filename, "a"); 01405 if (fp == NULL) { 01406 return ret; 01407 } 01408 01409 while (written_len < len) { 01410 /* write fsfat_test_byte_data_table or part thereof, in 9 writes of sizes 01411 * 1, 2, 4, 8, 16, 32, 64, 128, 1, totalling 256 bytes len permitting. */ 01412 for (exp = 0; (exp <= exp_max) && (written_len < len); exp++) { 01413 write_len = 0x1 << (exp % exp_max); 01414 write_len = len - written_len > write_len ? write_len : len - written_len; 01415 ret = fwrite((const void *) &fsfat_test_byte_data_table[written_len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, 01416 fp); 01417 written_len += write_len; 01418 if (ret != 1) { 01419 FSFAT_DBGLOG("%s:Error: fwrite() failed (ret=%d)\n", __func__, (int) ret); 01420 ret = -1; 01421 goto out0; 01422 } 01423 } 01424 } 01425 if (written_len == len) { 01426 ret = 0; 01427 } else { 01428 ret = -1; 01429 } 01430 out0: 01431 fclose(fp); 01432 return ret; 01433 } 01434 01435 01436 /* @brief test utility function to check the data in the specified file is correct. 01437 * 01438 * The data read from the file is check that it agrees with the data written by 01439 * fsfat_test_create_data_file(). 01440 * 01441 * @param filename name of the file including path 01442 * @param data data to store in file 01443 * @param len number of bytes of data present in the data buffer. 01444 */ 01445 int32_t fsfat_test_check_data_file(const char *filename, size_t len) 01446 { 01447 int32_t ret = -1; 01448 FILE *fp = NULL; 01449 size_t read_len = 0; 01450 uint8_t buf[FSFAT_TEST_BYTE_DATA_TABLE_SIZE]; 01451 01452 FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); 01453 TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); 01454 fp = fopen(filename, "r"); 01455 if (fp == NULL) { 01456 return ret; 01457 } 01458 01459 while (read_len < len) { 01460 ret = fread((void *) buf, FSFAT_TEST_BYTE_DATA_TABLE_SIZE, 1, fp); 01461 read_len += FSFAT_TEST_BYTE_DATA_TABLE_SIZE; 01462 if (ret == 0) { 01463 /* end of read*/ 01464 FSFAT_DBGLOG("%s:unable to read data\n", __func__); 01465 break; 01466 } 01467 if (memcmp(buf, fsfat_test_byte_data_table, FSFAT_TEST_BYTE_DATA_TABLE_SIZE) != 0) { 01468 FSFAT_DBGLOG("%s:Error: read data not as expected (0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x\n", 01469 __func__, 01470 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], 01471 buf[14], buf[15]); 01472 ret = -1; 01473 goto out0; 01474 } 01475 } 01476 if (read_len == len) { 01477 ret = 0; 01478 } 01479 out0: 01480 fclose(fp); 01481 return ret; 01482 } 01483 01484 /* file data for test_16 */ 01485 static fsfat_kv_data_t fsfat_fopen_test_16_kv_data[] = { 01486 { "/sd/tst16_0/testfil0.txt", "dummy_data"}, 01487 { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"}, 01488 { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"}, 01489 { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"}, 01490 { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"}, 01491 { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"}, 01492 { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"}, 01493 { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"}, 01494 { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"}, 01495 { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"}, 01496 { NULL, NULL}, 01497 }; 01498 01499 01500 /** @brief stress test to write data to fs 01501 * 01502 * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. 01503 */ 01504 control_t fsfat_fopen_test_16(const size_t call_count) 01505 { 01506 int32_t ret = 0; 01507 fsfat_kv_data_t *node = fsfat_fopen_test_16_kv_data; 01508 const int32_t num_blocks = 100; /* each file ~25kB */ 01509 01510 FSFAT_DBGLOG("%s:entered\n", __func__); 01511 (void) call_count; 01512 01513 /* remove file and directory from a previous failed test run, if present */ 01514 while (node->filename != NULL) { 01515 fsfat_filepath_remove_all((char *) node->filename); 01516 node++; 01517 } 01518 01519 /* create dirs */ 01520 node = fsfat_fopen_test_16_kv_data; 01521 while (node->filename != NULL) { 01522 ret = fsfat_filepath_make_dirs((char *) node->filename, true); 01523 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01524 "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); 01525 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01526 node++; 01527 } 01528 01529 /* create the data files */ 01530 node = fsfat_fopen_test_16_kv_data; 01531 while (node->filename != NULL) { 01532 ret = fsfat_test_create_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); 01533 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01534 "%s:Error: failed to create data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); 01535 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01536 node++; 01537 } 01538 01539 /* read the data back and check its as expected */ 01540 node = fsfat_fopen_test_16_kv_data; 01541 while (node->filename != NULL) { 01542 ret = fsfat_test_check_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); 01543 FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, 01544 "%s:Error: failed to check data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); 01545 TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); 01546 node++; 01547 } 01548 01549 /* clean up */ 01550 node = fsfat_fopen_test_16_kv_data; 01551 while (node->filename != NULL) { 01552 fsfat_filepath_remove_all((char *) node->filename); 01553 node++; 01554 } 01555 return CaseNext; 01556 } 01557 01558 /// @cond FSFAT_DOXYGEN_DISABLE 01559 utest::v1::status_t greentea_setup(const size_t number_of_cases) 01560 { 01561 GREENTEA_SETUP(FSFAT_FOPEN_GREENTEA_TIMEOUT_S, "default_auto"); 01562 return greentea_test_setup_handler(number_of_cases); 01563 } 01564 01565 Case cases[] = { 01566 /* 1 2 3 4 5 6 7 */ 01567 /* 1234567890123456789012345678901234567890123456789012345678901234567890 */ 01568 Case("FSFAT_FOPEN_TEST_00: format sd card to FAT FS.", FSFAT_FOPEN_TEST_00), 01569 Case("FSFAT_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSFAT_FOPEN_TEST_01), 01570 Case("FSFAT_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSFAT_FOPEN_TEST_02), 01571 Case("FSFAT_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSFAT_FOPEN_TEST_03), 01572 Case("FSFAT_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSFAT_FOPEN_TEST_04), 01573 #ifdef FOPEN_EXTENDED_TESTING 01574 Case("FSFAT_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSFAT_FOPEN_TEST_05), 01575 #endif 01576 Case("FSFAT_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSFAT_FOPEN_TEST_06), 01577 Case("FSFAT_FOPEN_TEST_07: fopen()/errno handling.", FSFAT_FOPEN_TEST_07), 01578 Case("FSFAT_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSFAT_FOPEN_TEST_08), 01579 Case("FSFAT_FOPEN_TEST_09: ftell() handling.", FSFAT_FOPEN_TEST_09), 01580 Case("FSFAT_FOPEN_TEST_10: remove() test.", FSFAT_FOPEN_TEST_10), 01581 Case("FSFAT_FOPEN_TEST_11: rename().", FSFAT_FOPEN_TEST_11), 01582 Case("FSFAT_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSFAT_FOPEN_TEST_12), 01583 Case("FSFAT_FOPEN_TEST_13: mkdir() test.", FSFAT_FOPEN_TEST_13), 01584 Case("FSFAT_FOPEN_TEST_14: stat() test.", FSFAT_FOPEN_TEST_14), 01585 Case("FSFAT_FOPEN_TEST_15: format() test.", FSFAT_FOPEN_TEST_15), 01586 Case("FSFAT_FOPEN_TEST_16: write/check n x 25kB data files.", FSFAT_FOPEN_TEST_16), 01587 }; 01588 01589 01590 /* Declare your test specification with a custom setup handler */ 01591 Specification specification(greentea_setup, cases); 01592 01593 int main() 01594 { 01595 return !Harness::run(specification); 01596 } 01597 /// @endcond 01598 #endif // !(DEVICE_SPI && ( defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) || (MBED_CONF_SD_FSFAT_SDCARD_INSTALLED)))
Generated on Tue Jul 12 2022 13:54:23 by
