Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
atomic_usage.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017-2017 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 00023 00024 /** 00025 * This file contains code which performs various atomic operations using 00026 * littlefs. It is intended for use in tests and test applications to 00027 * validate that the defined behavior below is being met. 00028 * 00029 * # Defined behavior 00030 * - A file rename is atomic (Note - rename can be used to replace a file) 00031 * - Atomic file rename tested by setup/perform/check_file_rename 00032 * - Atomic file replace tested by setup/perform/check_file_rename_replace 00033 * - A directory rename is atomic (Note - rename can be used to replace an empty directory) 00034 * - Tested by setup/perform/check_directory_rename 00035 * - Directory create is atomic 00036 * - Directory delete is atomic 00037 * - File create is atomic 00038 * - File delete is atomic 00039 * - File contents are atomically written on close 00040 * - Tested by setup/perform/check_file_change_contents 00041 */ 00042 00043 00044 #include "mbed.h" 00045 #include "greentea-client/test_env.h" 00046 #include "unity.h" 00047 #include "utest.h" 00048 #include <stdlib.h> 00049 #include <errno.h> 00050 00051 #include "ObservingBlockDevice.h" 00052 #include "ExhaustibleBlockDevice.h" 00053 #include "FileSystem.h" 00054 00055 #include "atomic_usage.h" 00056 00057 // test configuration 00058 #ifndef MBED_TEST_FILESYSTEM 00059 #define MBED_TEST_FILESYSTEM LittleFileSystem 00060 #endif 00061 00062 #ifndef MBED_TEST_FILESYSTEM_DECL 00063 #define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") 00064 #endif 00065 00066 00067 // declarations 00068 #define STRINGIZE(x) STRINGIZE2(x) 00069 #define STRINGIZE2(x) #x 00070 #define INCLUDE(x) STRINGIZE(x.h) 00071 00072 #include INCLUDE(MBED_TEST_FILESYSTEM) 00073 00074 00075 #define DEBUG(...) 00076 #define DEBUG_CHECK(...) 00077 #define BUFFER_SIZE 64 00078 // Version is written to a file and is used 00079 // to determine if a reformat is required 00080 #define ATOMIC_USAGE_VERSION 1 00081 00082 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) 00083 00084 #define TEST_ASSERT_OR_EXIT(condition) \ 00085 TEST_ASSERT(condition); if (!(condition)) {error("Assert failed");} 00086 00087 #define TEST_ASSERT_EQUAL_OR_EXIT(expected, actual) \ 00088 TEST_ASSERT_EQUAL(expected, actual); if ((int64_t)(expected) != (int64_t)(actual)) {error("Assert failed");} 00089 00090 using namespace utest::v1; 00091 00092 typedef void (*test_function_t)(FileSystem *fs); 00093 typedef bool (*test_function_bool_t)(FileSystem *fs); 00094 00095 struct TestEntry { 00096 const char *name; 00097 test_function_t setup; 00098 test_function_bool_t perform; 00099 test_function_t check; 00100 }; 00101 00102 /** 00103 * Write data to the file while checking for error conditions 00104 * 00105 * @param file File to write to 00106 * @param data Data to write 00107 * @param size Size of data to write 00108 * @return true if flash has been exhausted, false otherwise 00109 */ 00110 static bool file_write(File *file, uint8_t *data, uint32_t size) 00111 { 00112 int res = file->write(data, size); 00113 if (-ENOSPC == res) { 00114 return true; 00115 } 00116 TEST_ASSERT_EQUAL_OR_EXIT(size, res); 00117 return false; 00118 } 00119 00120 /** 00121 * Write padding data of the given size 00122 * 00123 * @param file Pointer to the file to write to 00124 * @param padding Value to pad 00125 * @param size Size to pad 00126 * @return true if flash has been exhausted, false otherwise 00127 */ 00128 static bool file_pad(File *file, char padding, uint32_t size) 00129 { 00130 uint8_t buf[BUFFER_SIZE]; 00131 memset(buf, padding, sizeof(buf)); 00132 00133 while (size > 0) { 00134 uint32_t write_size = sizeof(buf) <= size ? sizeof(buf) : size; 00135 if (file_write(file, buf, write_size)) { 00136 return true; 00137 } 00138 size -= write_size; 00139 } 00140 00141 return false; 00142 } 00143 00144 /* 00145 * Similar to fscanf but uses and mbed file 00146 * 00147 * @param file File to scan from 00148 * @param format Format string of values to read 00149 * @return the number of arguments read 00150 */ 00151 static int file_scanf(File *file, const char *format, ...) 00152 { 00153 uint8_t buf[BUFFER_SIZE]; 00154 va_list args; 00155 memset(buf, 0, sizeof(buf)); 00156 00157 int res = file->read(buf, sizeof(buf) - 1); 00158 TEST_ASSERT_OR_EXIT(res >= 0); 00159 00160 va_start (args, format); 00161 int count = vsscanf((char*)buf, format, args); 00162 va_end (args); 00163 TEST_ASSERT_OR_EXIT(count >= 0); 00164 00165 return count; 00166 } 00167 00168 /* 00169 * Similar to fprintf but uses and mbed file 00170 * 00171 * @param file File to print to 00172 * @param format Format string of values to write 00173 * @return size written to file or -1 on out of space 00174 */ 00175 static int file_printf(File *file, const char *format, ...) 00176 { 00177 uint8_t buf[BUFFER_SIZE]; 00178 va_list args; 00179 va_start (args, format); 00180 int size = vsprintf((char*)buf, format, args); 00181 va_end (args); 00182 TEST_ASSERT_OR_EXIT((size >= 0) && (size <= (int)sizeof(buf))); 00183 00184 if (file_write(file, buf, size)) { 00185 return -1; 00186 } 00187 00188 return size; 00189 } 00190 00191 00192 static const char FILE_RENAME_A[] = "file_to_rename_a.txt"; 00193 static const char FILE_RENAME_B[] = "file_to_rename_b.txt"; 00194 static const char FILE_RENAME_CONTENTS[] = "Test contents for the file to be renamed"; 00195 static const int FILE_RENAME_LEN = strlen(FILE_RENAME_CONTENTS); 00196 00197 /** 00198 * Setup for the file rename test 00199 * 00200 * Create file FILE_RENAME_A with contents FILE_RENAME_CONTENTS. 00201 */ 00202 static void setup_file_rename(FileSystem *fs) 00203 { 00204 DEBUG("setup_file_rename()\n"); 00205 00206 File file; 00207 00208 int res = file.open(fs, FILE_RENAME_A, O_WRONLY | O_CREAT); 00209 DEBUG(" open result %i\n", res); 00210 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00211 00212 res = file.write(FILE_RENAME_CONTENTS, FILE_RENAME_LEN); 00213 DEBUG(" write result %i\n", res); 00214 TEST_ASSERT_EQUAL_OR_EXIT(FILE_RENAME_LEN, res); 00215 } 00216 00217 /** 00218 * Change the file name to either FILE_RENAME_A or FILE_RENAME_B 00219 */ 00220 static bool perform_file_rename(FileSystem *fs) 00221 { 00222 DEBUG("perform_file_rename()\n"); 00223 00224 struct stat st; 00225 int res = fs->stat(FILE_RENAME_A, &st); 00226 const char *src = (res == 0) ? FILE_RENAME_A : FILE_RENAME_B; 00227 const char *dst = (res == 0) ? FILE_RENAME_B : FILE_RENAME_A; 00228 00229 DEBUG(" stat result %i\n", res); 00230 TEST_ASSERT_OR_EXIT((res == -ENOENT) || (res == 0)); 00231 00232 DEBUG(" Renaming %s to %s\n", src, dst); 00233 res = fs->rename(src, dst); 00234 if (-ENOSPC == res) { 00235 return true; 00236 } 00237 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00238 return false; 00239 } 00240 00241 /** 00242 * Check that the file rename is in a good state 00243 * 00244 * Check that there is only one file and that file contains the correct 00245 * contents. 00246 * 00247 * Allowed states: 00248 * - File FILE_RENAME_A exists with contents and FILE_RENAME_B does not 00249 * - File FILE_RENAME_B exists with contents and FILE_RENAME_A does not 00250 * 00251 */ 00252 static void check_file_rename(FileSystem *fs) 00253 { 00254 00255 int files = 0; 00256 int valids = 0; 00257 const char * const filenames[] = {FILE_RENAME_A, FILE_RENAME_B}; 00258 00259 for (int i = 0; i < 2; i++) { 00260 File file; 00261 if (file.open(fs, filenames[i], O_RDONLY) == 0) { 00262 uint8_t buf[BUFFER_SIZE]; 00263 files++; 00264 memset(buf, 0, sizeof(buf)); 00265 int res = file.read(buf, FILE_RENAME_LEN); 00266 if (res != FILE_RENAME_LEN) { 00267 break; 00268 } 00269 if (memcmp(buf, FILE_RENAME_CONTENTS, FILE_RENAME_LEN) != 0) { 00270 break; 00271 } 00272 valids++; 00273 } 00274 } 00275 00276 TEST_ASSERT_EQUAL_OR_EXIT(1, files); 00277 TEST_ASSERT_EQUAL_OR_EXIT(1, valids); 00278 } 00279 00280 00281 static const char FILE_RENAME_REPLACE[] = "rename_replace_file.txt"; 00282 static const char FILE_RENAME_REPLACE_NEW[] = "new_rename_replace_file.txt"; 00283 static const char FILE_RENAME_REPLACE_FMT[] = "file replace count: %lu\n"; 00284 00285 /** 00286 * Create the file FILE_RENAME_REPLACE with initial contents 00287 * 00288 * Create an write an initial count of 0 to the file. 00289 */ 00290 static void setup_file_rename_replace(FileSystem *fs) 00291 { 00292 DEBUG("setup_file_rename_replace()\n"); 00293 File file; 00294 00295 // Write out initial count 00296 00297 int res = file.open(fs, FILE_RENAME_REPLACE, O_WRONLY | O_CREAT); 00298 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00299 00300 uint32_t count = 0; 00301 uint8_t buf[BUFFER_SIZE]; 00302 memset(buf, 0, sizeof(buf)); 00303 const int length = sprintf((char*)buf, FILE_RENAME_REPLACE_FMT, count); 00304 TEST_ASSERT_OR_EXIT(length > 0); 00305 00306 res = file.write(buf, length); 00307 DEBUG(" write result %i\n", res); 00308 TEST_ASSERT_EQUAL_OR_EXIT(length, res); 00309 } 00310 00311 /** 00312 * Atomically increment the count in FILE_RENAME_REPLACE using a rename 00313 */ 00314 bool perform_file_rename_replace(FileSystem *fs) 00315 { 00316 DEBUG("perform_file_rename_replace()\n"); 00317 File file; 00318 00319 // Read in previous count 00320 00321 int res = file.open(fs, FILE_RENAME_REPLACE, O_RDONLY); 00322 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00323 00324 uint64_t count; 00325 int args_read = file_scanf(&file, FILE_RENAME_REPLACE_FMT, &count); 00326 TEST_ASSERT_EQUAL_OR_EXIT(1, args_read); 00327 00328 res = file.close(); 00329 if (-ENOSPC == res) { 00330 return true; 00331 } 00332 TEST_ASSERT_EQUAL(0, res); 00333 00334 // Write out new count 00335 00336 count++; 00337 00338 res = file.open(fs, FILE_RENAME_REPLACE_NEW, O_WRONLY | O_CREAT); 00339 if (-ENOSPC == res) { 00340 return true; 00341 } 00342 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00343 00344 if (file_printf(&file, FILE_RENAME_REPLACE_FMT, count) <= 0) { 00345 return true; 00346 } 00347 00348 res = file.close(); 00349 if (-ENOSPC == res) { 00350 return true; 00351 } 00352 TEST_ASSERT_EQUAL(0, res); 00353 00354 // Rename file 00355 00356 res = fs->rename(FILE_RENAME_REPLACE_NEW, FILE_RENAME_REPLACE); 00357 if (-ENOSPC == res) { 00358 return true; 00359 } 00360 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00361 DEBUG(" count %llu -> %llu\n", count - 1, count); 00362 00363 return false; 00364 } 00365 00366 /** 00367 * Check that FILE_RENAME_REPLACE always has a valid count 00368 * 00369 * Allowed states: 00370 * - FILE_RENAME_REPLACE exists with valid contents 00371 */ 00372 static void check_file_rename_replace(FileSystem *fs) 00373 { 00374 DEBUG_CHECK("check_file_rename_replace()\n"); 00375 File file; 00376 00377 // Read in previous count 00378 00379 int res = file.open(fs, FILE_RENAME_REPLACE, O_RDONLY); 00380 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00381 00382 uint64_t count; 00383 int args_read = file_scanf(&file, FILE_RENAME_REPLACE_FMT, &count); 00384 TEST_ASSERT_EQUAL_OR_EXIT(1, args_read); 00385 DEBUG_CHECK(" count %llu\n", count); 00386 } 00387 00388 00389 static const char DIRECTORY_RENAME_A[] = "dir_a"; 00390 static const char DIRECTORY_RENAME_B[] = "dir_b"; 00391 00392 /** 00393 * Create DIRECTORY_RENAME_A with initial contents 00394 */ 00395 static void setup_directory_rename(FileSystem *fs) 00396 { 00397 DEBUG("setup_directory_rename()\n"); 00398 00399 int res = fs->mkdir(DIRECTORY_RENAME_A, 0777); 00400 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00401 } 00402 00403 /* 00404 * Change the directory name from either DIRECTORY_RENAME_A or DIRECTORY_RENAME_B to the other 00405 */ 00406 static bool perform_directory_rename(FileSystem *fs) 00407 { 00408 DEBUG("perform_directory_rename()\n"); 00409 00410 struct stat st; 00411 int res = fs->stat(DIRECTORY_RENAME_A, &st); 00412 const char *src = (res == 0) ? DIRECTORY_RENAME_A : DIRECTORY_RENAME_B; 00413 const char *dst = (res == 0) ? DIRECTORY_RENAME_B : DIRECTORY_RENAME_A; 00414 00415 DEBUG(" stat result %i\n", res); 00416 TEST_ASSERT_OR_EXIT((res == -ENOENT) || (res == 0)); 00417 00418 DEBUG(" Renaming %s to %s\n", src, dst); 00419 res = fs->rename(src, dst); 00420 if (-ENOSPC == res) { 00421 return true; 00422 } 00423 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00424 return false; 00425 } 00426 00427 /* 00428 * Change the directory name from either DIRECTORY_RENAME_A or DIRECTORY_RENAME_B to the other 00429 * 00430 * Allowed states: 00431 * - DIRECTORY_RENAME_A exists with valid contents and DIRECTORY_RENAME_B does not exist 00432 * - DIRECTORY_RENAME_B exists with valid contents and DIRECTORY_RENAME_A does not exist 00433 */ 00434 static void check_directory_rename(FileSystem *fs) 00435 { 00436 DEBUG_CHECK("check_directory_rename()\n"); 00437 00438 static const char *directory_names[] = { 00439 DIRECTORY_RENAME_A, 00440 DIRECTORY_RENAME_B 00441 }; 00442 00443 size_t directories = 0; 00444 for (size_t i = 0; i < ARRAY_LENGTH(directory_names); i++) { 00445 Dir dir; 00446 int res = dir.open(fs, directory_names[i]); 00447 TEST_ASSERT_OR_EXIT((res == -ENOENT) || (res == 0)); 00448 if (res == 0) { 00449 directories++; 00450 } 00451 } 00452 TEST_ASSERT_EQUAL_OR_EXIT(1, directories); 00453 } 00454 00455 00456 static const char CHANGE_CONTENTS_NAME[] = "file_changing_contents.txt"; 00457 static const char CHANGE_CONTENTS_FILL = ' '; 00458 static const uint32_t BLOCK_SIZE = 512; 00459 00460 /** 00461 * Create file CHANGE_CONTENTS_NAME with initial contents 00462 * 00463 * File contains three blocks of data each which start 00464 * with a count. 00465 */ 00466 static void setup_file_change_contents(FileSystem *fs) 00467 { 00468 DEBUG("setup_file_change_contents()\n"); 00469 00470 File file; 00471 int res = file.open(fs, CHANGE_CONTENTS_NAME, O_WRONLY | O_CREAT); 00472 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00473 00474 for (int count = 1; count <= 3; count++) { 00475 int size = file_printf(&file, "%lu\n", count); 00476 TEST_ASSERT_OR_EXIT(size >= 0); 00477 00478 bool dead = file_pad(&file, CHANGE_CONTENTS_FILL, BLOCK_SIZE - size); 00479 TEST_ASSERT_EQUAL_OR_EXIT(false, dead); 00480 } 00481 } 00482 00483 /** 00484 * Atomically increment the counts in the file CHANGE_CONTENTS_NAME 00485 * 00486 * Read in the current counts, increment them and then write them 00487 * back in non-sequential order. 00488 */ 00489 static bool perform_file_change_contents(FileSystem *fs) 00490 { 00491 DEBUG("perform_file_change_contents()\n"); 00492 File file; 00493 00494 int res = file.open(fs, CHANGE_CONTENTS_NAME, O_RDWR); 00495 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00496 00497 // Read in values 00498 uint32_t values[3]; 00499 for (int i = 0; i < 3; i++) { 00500 file.seek(i * BLOCK_SIZE); 00501 int args_read = file_scanf(&file, "%lu\n", &values[i]); 00502 TEST_ASSERT_EQUAL_OR_EXIT(1, args_read); 00503 } 00504 00505 // Increment values 00506 for (int i = 0; i < 3; i++) { 00507 values[i]++; 00508 } 00509 00510 // Write values out of order 00511 int i; 00512 i = 0; 00513 file.seek(i * BLOCK_SIZE); 00514 if (file_printf(&file, "%lu\n", values[i]) <= 0) { 00515 return true; 00516 } 00517 DEBUG(" value[%i]: %lu -> %lu\n", i, values[i] - 1, values[i]); 00518 00519 i = 2; 00520 file.seek(i * BLOCK_SIZE); 00521 if (file_printf(&file, "%lu\n", values[i]) <= 0) { 00522 return true; 00523 } 00524 DEBUG(" value[%i]: %lu -> %lu\n", i, values[i] - 1, values[i]); 00525 00526 i = 1; 00527 file.seek(i * BLOCK_SIZE); 00528 if (file_printf(&file, "%lu\n", values[i]) <= 0) { 00529 return true; 00530 } 00531 DEBUG(" value[%i]: %lu -> %lu\n", i, values[i] - 1, values[i]); 00532 00533 res = file.close(); 00534 if (-ENOSPC == res) { 00535 return true; 00536 } 00537 TEST_ASSERT_EQUAL(0, res); 00538 00539 return false; 00540 } 00541 00542 /* 00543 * Change the directory name from either DIRECTORY_RENAME_A or DIRECTORY_RENAME_B to the other 00544 * 00545 * Allowed states: 00546 * - CHANGE_CONTENTS_NAME exists and contains 3 counts which are in order 00547 */ 00548 static void check_file_change_contents(FileSystem *fs) 00549 { 00550 DEBUG_CHECK("check_file_change_contents()\n"); 00551 File file; 00552 00553 int res = file.open(fs, CHANGE_CONTENTS_NAME, O_RDONLY); 00554 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00555 00556 // Read in values 00557 uint32_t values[3]; 00558 for (int i = 0; i < 3; i++) { 00559 file.seek(i * BLOCK_SIZE); 00560 int args_read = file_scanf(&file, "%lu\n", &values[i]); 00561 TEST_ASSERT_EQUAL_OR_EXIT(1, args_read); 00562 DEBUG_CHECK(" value[%i]: %lu\n", i, values[i]); 00563 } 00564 00565 TEST_ASSERT_EQUAL_OR_EXIT(values[0] + 1, values[1]); 00566 TEST_ASSERT_EQUAL_OR_EXIT(values[1] + 1, values[2]); 00567 } 00568 00569 00570 static const TestEntry atomic_test_entries[] = { 00571 {"File rename", setup_file_rename, perform_file_rename, check_file_rename}, 00572 {"File rename replace", setup_file_rename_replace, perform_file_rename_replace, check_file_rename_replace}, 00573 {"Directory rename", setup_directory_rename, perform_directory_rename, check_directory_rename}, 00574 {"File change contents", setup_file_change_contents, perform_file_change_contents, check_file_change_contents}, 00575 }; 00576 00577 static const char FILE_SETUP_COMPLETE[] = "setup_complete.txt"; 00578 static const char FILE_SETUP_COMPLETE_FMT[] = "Test version: %lu\n"; 00579 00580 static bool format_required(BlockDevice *bd) 00581 { 00582 MBED_TEST_FILESYSTEM_DECL; 00583 00584 if (fs.mount(bd) != 0) { 00585 return true; 00586 } 00587 00588 // Check if setup complete file exists 00589 File file; 00590 int res = file.open(&fs, FILE_SETUP_COMPLETE, O_RDONLY); 00591 if (res != 0) { 00592 return true; 00593 } 00594 00595 // Read contents of setup complete file 00596 uint8_t buf[BUFFER_SIZE]; 00597 memset(buf, 0, sizeof(buf)); 00598 int size_read = file.read(buf, sizeof(buf) - 1); 00599 if (size_read <= 0) { 00600 return true; 00601 } 00602 00603 // Get the test version 00604 uint32_t version = 0; 00605 res = sscanf((char*)buf, FILE_SETUP_COMPLETE_FMT, &version); 00606 if (res != 1) { 00607 return true; 00608 } 00609 00610 if (ATOMIC_USAGE_VERSION != version) { 00611 return true; 00612 } 00613 00614 // Setup file exists and is the correct version 00615 return false; 00616 } 00617 00618 static void format(BlockDevice *bd) 00619 { 00620 MBED_TEST_FILESYSTEM_DECL; 00621 00622 int res = fs.format(bd); 00623 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00624 00625 res = fs.mount(bd); 00626 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00627 00628 for (size_t i = 0; i < ARRAY_LENGTH(atomic_test_entries); i++) { 00629 atomic_test_entries[i].setup(&fs); 00630 } 00631 00632 File file; 00633 res = file.open(&fs, FILE_SETUP_COMPLETE, O_CREAT | O_WRONLY); 00634 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00635 00636 int size = file_printf(&file, FILE_SETUP_COMPLETE_FMT, (uint32_t)ATOMIC_USAGE_VERSION); 00637 TEST_ASSERT_OR_EXIT(size >= 0); 00638 } 00639 00640 static int64_t get_cycle_count(FileSystem *fs) 00641 { 00642 File file; 00643 00644 int res = file.open(fs, FILE_RENAME_REPLACE, O_RDONLY); 00645 TEST_ASSERT_EQUAL_OR_EXIT(0, res); 00646 00647 uint64_t count = 0; 00648 int args_read = file_scanf(&file, FILE_RENAME_REPLACE_FMT, &count); 00649 TEST_ASSERT_EQUAL_OR_EXIT(1, args_read); 00650 00651 file.close(); 00652 00653 return (int64_t)count; 00654 } 00655 00656 bool setup_atomic_operations(BlockDevice *bd, bool force_rebuild) 00657 { 00658 if (force_rebuild || format_required(bd)) { 00659 format(bd); 00660 TEST_ASSERT_EQUAL_OR_EXIT(false, format_required(bd)); 00661 return true; 00662 } 00663 return false; 00664 } 00665 00666 int64_t perform_atomic_operations(BlockDevice *bd) 00667 { 00668 MBED_TEST_FILESYSTEM_DECL; 00669 bool out_of_space = false; 00670 00671 fs.mount(bd); 00672 00673 for (size_t i = 0; i < ARRAY_LENGTH(atomic_test_entries); i++) { 00674 out_of_space |= atomic_test_entries[i].perform(&fs); 00675 } 00676 00677 int64_t cycle_count = get_cycle_count(&fs); 00678 00679 fs.unmount(); 00680 00681 if (out_of_space) { 00682 return -1; 00683 } else { 00684 return cycle_count; 00685 } 00686 } 00687 00688 void check_atomic_operations(BlockDevice *bd) 00689 { 00690 MBED_TEST_FILESYSTEM_DECL; 00691 fs.mount(bd); 00692 00693 for (size_t i = 0; i < ARRAY_LENGTH(atomic_test_entries); i++) { 00694 atomic_test_entries[i].check(&fs); 00695 } 00696 00697 fs.unmount(); 00698 }
Generated on Fri Jul 22 2022 04:53:45 by
 1.7.2
 1.7.2 
    