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