Skip to content

Commit 31a3847

Browse files
Ox11carlescufi
authored andcommitted
test: fs: fat_fs_api: Add tests for reentrant zephyr support
This commit adds tests for the FatFs FF_FS_REENTRANT option. Signed-off-by: Nicola Ochsenbein <[email protected]>
1 parent eba7372 commit 31a3847

File tree

9 files changed

+201
-12
lines changed

9 files changed

+201
-12
lines changed

tests/subsys/fs/fat_fs_api/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ target_sources(app PRIVATE
1818
target_sources_ifdef(CONFIG_FLASH app PRIVATE
1919
../common/test_fs_mkfs.c
2020
src/test_fat_mkfs.c)
21+
target_sources_ifdef(CONFIG_FS_FATFS_REENTRANT app PRIVATE
22+
src/test_fat_file_reentrant.c)

tests/subsys/fs/fat_fs_api/src/common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/*
22
* Copyright (c) 2016 Intel Corporation.
3+
* Copyright (c) 2023 Husqvarna AB
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
67

78
#include "test_fat.h"
89

10+
/* FatFs work area */
11+
FATFS fat_fs;
912
struct fs_file_t filep;
1013
const char test_str[] = "hello world!";
1114

tests/subsys/fs/fat_fs_api/src/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2016 Intel Corporation.
3+
* Copyright (c) 2023 Husqvarna AB
34
*
45
* SPDX-License-Identifier: Apache-2.0
56
*/
@@ -18,6 +19,9 @@ static void *fat_fs_basic_setup(void)
1819
test_fat_fs();
1920
test_fat_rename();
2021
test_fs_open_flags();
22+
#ifdef CONFIG_FS_FATFS_REENTRANT
23+
test_fat_file_reentrant();
24+
#endif /* CONFIG_FS_FATFS_REENTRANT */
2125
test_fat_unmount();
2226

2327
return NULL;

tests/subsys/fs/fat_fs_api/src/test_fat.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
/*
22
* Copyright (c) 2016 Intel Corporation.
33
* Copyright (c) 2020 Nordic Semiconductor ASA
4+
* Copyright (c) 2023 Husqvarna AB
45
*
56
* SPDX-License-Identifier: Apache-2.0
67
*/
78

89
#include <zephyr/kernel.h>
910
#include <zephyr/ztest.h>
1011
#include <zephyr/fs/fs.h>
12+
#include <ff.h>
1113

1214
#ifdef CONFIG_DISK_DRIVER_RAM
1315
#define DISK_NAME CONFIG_DISK_RAM_VOLUME_NAME
@@ -27,12 +29,14 @@
2729
"/testlongfilenamethatsmuchlongerthan8.3chars.text"
2830
#else
2931
#define TEST_FILE FATFS_MNTP"/testfile.txt"
30-
#endif /* IS_ENABLED(CONFIG_FS_FATFS_LFN) */
32+
#endif /* CONFIG_FS_FATFS_LFN */
3133
#define TEST_DIR FATFS_MNTP"/testdir"
3234
#define TEST_DIR_FILE FATFS_MNTP"/testdir/testfile.txt"
3335

3436
extern struct fs_file_t filep;
3537
extern const char test_str[];
38+
/* FatFs work area */
39+
extern FATFS fat_fs;
3640

3741
int check_file_dir_exists(const char *path);
3842

@@ -42,3 +46,6 @@ void test_fat_file(void);
4246
void test_fat_dir(void);
4347
void test_fat_fs(void);
4448
void test_fat_rename(void);
49+
#ifdef CONFIG_FS_FATFS_REENTRANT
50+
void test_fat_file_reentrant(void);
51+
#endif /* CONFIG_FS_FATFS_REENTRANT */
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/*
2+
* Copyright (c) 2023 Husqvarna AB
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "test_fat.h"
8+
9+
#ifdef CONFIG_FS_FATFS_REENTRANT
10+
11+
#define REENTRANT_TEST_STACK_SIZE 500
12+
#define SEMAPHORE_OP_SUCCESS 0
13+
#define TEST_FILE2 FATFS_MNTP"/tfile2.txt"
14+
15+
void tlock_mutex(void *p1, void *p2, void *p3);
16+
void tfile2_access(void *p1, void *p2, void *p3);
17+
18+
K_THREAD_STACK_DEFINE(tlock_mutex_stack_area, REENTRANT_TEST_STACK_SIZE);
19+
K_THREAD_STACK_DEFINE(tfile2_access_stack_area, REENTRANT_TEST_STACK_SIZE);
20+
struct k_thread tlock_mutex_data;
21+
struct k_thread tfile2_access_data;
22+
struct k_sem mutex_unlocked_sem;
23+
struct k_sem run_non_thread_sem;
24+
25+
static int test_reentrant_access(void)
26+
{
27+
int res;
28+
29+
TC_PRINT("\nReentrant tests:\n");
30+
zassert_ok(k_sem_init(&mutex_unlocked_sem, 0, 1), NULL);
31+
zassert_ok(k_sem_init(&run_non_thread_sem, 0, 1), NULL);
32+
33+
/* Start mutex locking thread */
34+
k_tid_t tid = k_thread_create(&tlock_mutex_data, tlock_mutex_stack_area,
35+
K_THREAD_STACK_SIZEOF(tlock_mutex_stack_area),
36+
tlock_mutex,
37+
NULL, NULL, NULL,
38+
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
39+
40+
/* Make sure thread was able to lock mutex */
41+
k_sem_take(&run_non_thread_sem, K_FOREVER);
42+
43+
/* File open should wait here, as the fs is locked. Therefore, automatic switch back to
44+
* thread
45+
*/
46+
TC_PRINT("Open file\n");
47+
res = fs_open(&filep, TEST_FILE, FS_O_CREATE | FS_O_RDWR);
48+
zassert_ok(res, "Err: File could not be opened [%d]\n", res);
49+
TC_PRINT("File opened\n");
50+
51+
/* Check if mutex thread really unlocked the mutexes */
52+
zassert_equal(SEMAPHORE_OP_SUCCESS, k_sem_take(&mutex_unlocked_sem, K_NO_WAIT),
53+
"File open with locked mutex");
54+
55+
/* Cleanup */
56+
res = fs_close(&filep);
57+
zassert_ok(res, "Error closing file [%d]\n", res);
58+
res = fs_unlink(TEST_FILE);
59+
zassert_ok(res, "Error deleting file [%d]\n", res);
60+
61+
k_thread_join(tid, K_FOREVER);
62+
63+
return res;
64+
}
65+
66+
static int test_reentrant_parallel_file_access(void)
67+
{
68+
int res;
69+
70+
TC_PRINT("\nParallel reentrant-safe file access test:\n");
71+
72+
TC_PRINT("Open file 1\n");
73+
res = fs_open(&filep, TEST_FILE, FS_O_CREATE | FS_O_RDWR);
74+
zassert_ok(res, "Err: File 1 could not be opened [%d]\n", res);
75+
TC_PRINT("File 1 opened 1\n");
76+
77+
/* Start 2nd file acces thread */
78+
k_tid_t tid = k_thread_create(&tfile2_access_data, tfile2_access_stack_area,
79+
K_THREAD_STACK_SIZEOF(tfile2_access_stack_area),
80+
tfile2_access,
81+
NULL, NULL, NULL,
82+
K_PRIO_PREEMPT(0), 0, K_NO_WAIT);
83+
84+
/* Wait for thread to finish accessing file 2 */
85+
k_thread_join(tid, K_FOREVER);
86+
87+
/* Check existence of file 2 */
88+
struct fs_file_t filep2;
89+
90+
fs_file_t_init(&filep2);
91+
92+
TC_PRINT("Check file 2 existence\n");
93+
res = fs_open(&filep2, TEST_FILE2, FA_OPEN_EXISTING | FA_READ);
94+
zassert_ok(res, "Err: File 2 does not exist [%d]\n", res);
95+
96+
/* Cleanup */
97+
res = fs_close(&filep2);
98+
zassert_ok(res, "Error closing file 2 [%d]\n", res);
99+
res = fs_unlink(TEST_FILE2);
100+
zassert_ok(res, "Error deleting file 2 [%d]\n", res);
101+
res = fs_close(&filep);
102+
zassert_ok(res, "Error closing file 1 [%d]\n", res);
103+
res = fs_unlink(TEST_FILE);
104+
zassert_ok(res, "Error deleting file 1 [%d]\n", res);
105+
106+
return res;
107+
}
108+
109+
void release_dirty_mutex(void)
110+
{
111+
ff_mutex_give(fat_fs.ldrv);
112+
}
113+
114+
int request_dirty_mutex(void)
115+
{
116+
return ff_mutex_take(fat_fs.ldrv);
117+
}
118+
119+
void tlock_mutex(void *p1, void *p2, void *p3)
120+
{
121+
TC_PRINT("Mutex thread: Started, locking fs\n");
122+
request_dirty_mutex();
123+
TC_PRINT("Mutex thread: Lock acquired, yield to switch back to try to open file\n");
124+
k_sem_give(&run_non_thread_sem);
125+
k_yield();
126+
127+
TC_PRINT("Mutex thread: Got back to thread, release mutex now and give semaphore to check "
128+
"if file opened\n");
129+
k_sem_give(&mutex_unlocked_sem);
130+
release_dirty_mutex();
131+
132+
TC_PRINT("Mutex thread: Lock released, thread terminating\n");
133+
}
134+
135+
void tfile2_access(void *p1, void *p2, void *p3)
136+
{
137+
int res;
138+
ssize_t brw;
139+
struct fs_file_t filep2;
140+
141+
TC_PRINT("File 2 access thread started\n");
142+
143+
/* Init fp for 2nd File for parallel access test */
144+
fs_file_t_init(&filep2);
145+
146+
/* open 2nd file */
147+
TC_PRINT("Open file 2\n");
148+
res = fs_open(&filep2, TEST_FILE2, FS_O_CREATE | FS_O_RDWR);
149+
zassert_ok(res, "Err: File 2 could not be opened [%d]\n", res);
150+
TC_PRINT("File 2 opened 2\n");
151+
152+
/* Verify fs_write() not locked */
153+
brw = fs_write(&filep2, (char *)test_str, strlen(test_str));
154+
if (brw < 0) {
155+
TC_PRINT("Failed writing to file [%zd]\n", brw);
156+
fs_close(&filep2);
157+
return;
158+
}
159+
160+
if (brw < strlen(test_str)) {
161+
TC_PRINT("Unable to complete write. Volume full.\n");
162+
TC_PRINT("Number of bytes written: [%zd]\n", brw);
163+
fs_close(&filep2);
164+
return;
165+
}
166+
167+
/* Close file and switch back to test context*/
168+
res = fs_close(&filep2);
169+
zassert_ok(res, "Error closing file [%d]\n", res);
170+
171+
TC_PRINT("File 2 access thread successfully wrote to file 2\n");
172+
}
173+
174+
void test_fat_file_reentrant(void)
175+
{
176+
zassert_true(test_reentrant_access() == TC_PASS, NULL);
177+
zassert_true(test_reentrant_parallel_file_access() == TC_PASS, NULL);
178+
}
179+
#endif /* CONFIG_FS_FATFS_REENTRANT */

tests/subsys/fs/fat_fs_api/src/test_fat_mkfs.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
#include <zephyr/storage/disk_access.h>
1414
#endif
1515

16-
/* FatFs work area */
17-
static FATFS fat_fs;
18-
1916
/* mounting info */
2017
static struct fs_mount_t fatfs_mnt = {
2118
.type = FS_FATFS,

tests/subsys/fs/fat_fs_api/src/test_fat_mount.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77

88

99
#include "test_fat.h"
10-
#include <ff.h>
11-
12-
/* FatFs work area */
13-
static FATFS fat_fs;
1410

1511
/* mounting info */
1612
static struct fs_mount_t fatfs_mnt = {

tests/subsys/fs/fat_fs_api/src/test_fat_rd_only_mount.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@
66

77

88
#include "test_fat.h"
9-
#include <ff.h>
10-
11-
/* FatFs work area */
12-
static FATFS fat_fs;
139

1410
/* mounting info */
1511
static struct fs_mount_t fatfs_mnt = {

tests/subsys/fs/fat_fs_api/testcase.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,8 @@ tests:
1414
filesystem.fat.ram.api:
1515
platform_allow: native_posix
1616
extra_args: CONF_FILE="prj_native_posix_ram.conf"
17+
filesystem.fat.api.reentrant:
18+
platform_allow: native_posix
19+
extra_configs:
20+
- CONFIG_FS_FATFS_REENTRANT=y
21+
- CONFIG_MULTITHREADING=y

0 commit comments

Comments
 (0)