SDHI_driver patch (mbedOS 5.11.5)

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers fopen.cpp Source File

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 "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