test_spiffs.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <sys/mman.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <dirent.h>
  9. #include <limits.h>
  10. #include <unistd.h>
  11. #include "esp_partition.h"
  12. #include "spiffs.h"
  13. #include "spiffs_nucleus.h"
  14. #include "spiffs_api.h"
  15. #include "catch.hpp"
  16. extern "C" void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
  17. static void init_spiffs(spiffs *fs, uint32_t max_files)
  18. {
  19. spiffs_config cfg;
  20. s32_t spiffs_res;
  21. const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "storage");
  22. REQUIRE(partition);
  23. // Configure objects needed by SPIFFS
  24. esp_spiffs_t *user_data = (esp_spiffs_t*) calloc(1, sizeof(*user_data));
  25. user_data->partition = partition;
  26. fs->user_data = (void*)user_data;
  27. cfg.hal_erase_f = spiffs_api_erase;
  28. cfg.hal_read_f = spiffs_api_read;
  29. cfg.hal_write_f = spiffs_api_write;
  30. cfg.log_block_size = CONFIG_WL_SECTOR_SIZE;
  31. cfg.log_page_size = CONFIG_SPIFFS_PAGE_SIZE;
  32. cfg.phys_addr = 0;
  33. cfg.phys_erase_block = CONFIG_WL_SECTOR_SIZE;
  34. cfg.phys_size = partition->size;
  35. uint32_t work_sz = cfg.log_page_size * 2;
  36. uint8_t *work = (uint8_t*) malloc(work_sz);
  37. uint32_t fds_sz = max_files * sizeof(spiffs_fd);
  38. uint8_t *fds = (uint8_t*) malloc(fds_sz);
  39. #if CONFIG_SPIFFS_CACHE
  40. uint32_t cache_sz = sizeof(spiffs_cache) + max_files * (sizeof(spiffs_cache_page)
  41. + cfg.log_page_size);
  42. uint8_t *cache = (uint8_t*) malloc(cache_sz);
  43. #else
  44. uint32_t cache_sz = 0;
  45. uint8_t cache = NULL;
  46. #endif
  47. // Special mounting procedure: mount, format, mount as per
  48. // https://github.com/pellepl/spiffs/wiki/Using-spiffs
  49. spiffs_res = SPIFFS_mount(fs, &cfg, work, fds, fds_sz,
  50. cache, cache_sz, spiffs_api_check);
  51. if (spiffs_res == SPIFFS_ERR_NOT_A_FS) {
  52. spiffs_res = SPIFFS_format(fs);
  53. REQUIRE(spiffs_res >= SPIFFS_OK);
  54. spiffs_res = SPIFFS_mount(fs, &cfg, work, fds, fds_sz,
  55. cache, cache_sz, spiffs_api_check);
  56. }
  57. REQUIRE(spiffs_res >= SPIFFS_OK);
  58. }
  59. static void deinit_spiffs(spiffs *fs)
  60. {
  61. SPIFFS_unmount(fs);
  62. free(fs->work);
  63. free(fs->user_data);
  64. free(fs->fd_space);
  65. #if CONFIG_SPIFFS_CACHE
  66. free(fs->cache);
  67. #endif
  68. }
  69. static void check_spiffs_files(spiffs *fs, const char *base_path, char* cur_path)
  70. {
  71. DIR *dir;
  72. struct dirent *entry;
  73. size_t len = strlen(cur_path);
  74. if (len == 0) {
  75. strcpy(cur_path, base_path);
  76. len = strlen(base_path);
  77. }
  78. dir = opendir(cur_path);
  79. REQUIRE(dir != 0);
  80. while ((entry = readdir(dir)) != NULL) {
  81. char *name = entry->d_name;
  82. char path[PATH_MAX] = { 0 };
  83. // Read the file from host FS
  84. strcpy(path, cur_path);
  85. strcat(path, "/");
  86. strcat(path, name);
  87. struct stat sb;
  88. stat(path, &sb);
  89. if (S_ISDIR(sb.st_mode)) {
  90. if (!strcmp(name, ".") || !strcmp(name, ".."))
  91. continue;
  92. cur_path[len] = '/';
  93. strcpy(cur_path + len + 1, name);
  94. check_spiffs_files(fs, base_path, cur_path);
  95. cur_path[len] = '\0';
  96. } else {
  97. FILE* f = fopen(path , "r");
  98. REQUIRE(f);
  99. fseek(f, 0, SEEK_END);
  100. long sz = ftell(f);
  101. fseek(f, 0, SEEK_SET);
  102. char *f_contents = (char*) malloc(sz);
  103. fread(f_contents, 1, sz, f);
  104. fclose(f);
  105. s32_t spiffs_res;
  106. // Read the file from SPIFFS
  107. char *spiffs_path = path + strlen(base_path);
  108. spiffs_res = SPIFFS_open(fs, spiffs_path, SPIFFS_RDONLY, 0);
  109. REQUIRE(spiffs_res > SPIFFS_OK);
  110. spiffs_file fd = spiffs_res;
  111. spiffs_stat stat;
  112. spiffs_res = SPIFFS_stat(fs, spiffs_path, &stat);
  113. char *spiffs_f_contents = (char*) malloc(stat.size);
  114. spiffs_res = SPIFFS_read(fs, fd, spiffs_f_contents, stat.size);
  115. REQUIRE(spiffs_res == stat.size);
  116. // Compare the contents
  117. REQUIRE(sz == stat.size);
  118. bool same = memcmp(f_contents, spiffs_f_contents, sz) == 0;
  119. REQUIRE(same);
  120. free(f_contents);
  121. free(spiffs_f_contents);
  122. }
  123. }
  124. closedir(dir);
  125. }
  126. TEST_CASE("format disk, open file, write and read file", "[spiffs]")
  127. {
  128. _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
  129. spiffs fs;
  130. s32_t spiffs_res;
  131. init_spiffs(&fs, 5);
  132. // Open test file
  133. spiffs_res = SPIFFS_open(&fs, "test.txt", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0);
  134. REQUIRE(spiffs_res >= SPIFFS_OK);
  135. // Generate data
  136. spiffs_file file = spiffs_res;
  137. uint32_t data_size = 100000;
  138. char *data = (char*) malloc(data_size);
  139. char *read = (char*) malloc(data_size);
  140. for(uint32_t i = 0; i < data_size; i += sizeof(i))
  141. {
  142. *((uint32_t*)(data + i)) = i;
  143. }
  144. // Write data to file
  145. spiffs_res = SPIFFS_write(&fs, file, (void*)data, data_size);
  146. REQUIRE(spiffs_res >= SPIFFS_OK);
  147. REQUIRE(spiffs_res == data_size);
  148. // Set the file object pointer to the beginning
  149. spiffs_res = SPIFFS_lseek(&fs, file, 0, SPIFFS_SEEK_SET);
  150. REQUIRE(spiffs_res >= SPIFFS_OK);
  151. // Read the file
  152. spiffs_res = SPIFFS_read(&fs, file, (void*)read, data_size);
  153. REQUIRE(spiffs_res >= SPIFFS_OK);
  154. REQUIRE(spiffs_res == data_size);
  155. // Close the test file
  156. spiffs_res = SPIFFS_close(&fs, file);
  157. REQUIRE(spiffs_res >= SPIFFS_OK);
  158. REQUIRE(memcmp(data, read, data_size) == 0);
  159. deinit_spiffs(&fs);
  160. free(read);
  161. free(data);
  162. }
  163. TEST_CASE("can read spiffs image", "[spiffs]")
  164. {
  165. _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
  166. spiffs fs;
  167. s32_t spiffs_res;
  168. const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, "storage");
  169. // Write the contents of the image file to partition
  170. FILE* img_file = fopen("image.bin", "r");
  171. REQUIRE(img_file);
  172. fseek(img_file, 0, SEEK_END);
  173. long img_size = ftell(img_file);
  174. fseek(img_file, 0, SEEK_SET);
  175. char *img = (char*) malloc(img_size);
  176. fread(img, 1, img_size, img_file);
  177. fclose(img_file);
  178. REQUIRE(partition->size == img_size);
  179. esp_partition_erase_range(partition, 0, partition->size);
  180. esp_partition_write(partition, 0, img, img_size);
  181. free(img);
  182. // Mount the spiffs partition and init filesystem, using the contents of
  183. // the image file
  184. init_spiffs(&fs, 1024);
  185. // Check spiffs consistency
  186. spiffs_res = SPIFFS_check(&fs);
  187. REQUIRE(spiffs_res == SPIFFS_OK);
  188. char path_buf[PATH_MAX];
  189. // The image is created from the spiffs source directory. Compare the files in that
  190. // directory to the files read from the SPIFFS image.
  191. check_spiffs_files(&fs, "../spiffs", path_buf);
  192. deinit_spiffs(&fs);
  193. }