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