SDHI_driver patch (mbedOS 5.11.5)
Embed:
(wiki syntax)
Show/hide line numbers
fopen.cpp
Go to the documentation of this file.
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