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