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