4343#include "examples/echoserver/echoserver.h"
4444#include "examples/sftpclient/sftpclient.h"
4545
46- static const char * cmds [] = {
47- "mkdir a" ,
48- "cd a" ,
49- "pwd" ,
50- "ls" ,
51- #ifdef WOLFSSH_ZEPHYR
52- "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure.ac" ,
53- #else
54- "put configure.ac" ,
55- #endif
56- "ls" ,
57- #ifdef WOLFSSH_ZEPHYR
58- "get configure.ac " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get" ,
59- #else
60- "get configure.ac test-get" ,
61- #endif
62- "rm configure.ac" ,
63- "cd ../" ,
64- "ls" ,
65- "rename test-get test-get-2" ,
66- "rmdir a" ,
67- "ls" ,
68- "chmod 600 test-get-2" ,
69- "rm test-get-2" ,
70- "ls -s" ,
71- "exit"
72- };
73- static int commandIdx = 0 ;
46+ /*
47+ * Each test command is paired with an optional check function that
48+ * validates the output it produces. This eliminates the fragile
49+ * index-based coupling between the command array and the validator.
50+ */
51+ typedef int (* SftpTestCheck )(void );
52+
53+ typedef struct {
54+ const char * cmd ;
55+ SftpTestCheck check ; /* validates output from THIS cmd, or NULL */
56+ } SftpTestCmd ;
57+
58+ /* Test buffer */
7459static char inBuf [1024 ] = {0 };
7560
76- /* return 0 on success */
77- static int Expected ( int command )
61+ /* check that pwd output ends in /a */
62+ static int checkPwdInA ( void )
7863{
7964 int i ;
65+ int len ;
8066
81- switch (command ) {
82- case 3 : /* pwd */
83- /* working directory should not contain a '.' at the end */
84- for (i = 0 ; i < (int )sizeof (inBuf ); i ++ ) {
85- if (inBuf [i ] == '\n' ) {
86- inBuf [i ] = '\0' ;
87- break ;
88- }
89- }
90-
91- if (inBuf [WSTRLEN (inBuf ) - 2 ] != '/' ) {
92- printf ("unexpected pwd of %s\n looking for '/'\n" , inBuf );
93- return -1 ;
94- }
95- if (inBuf [WSTRLEN (inBuf ) - 1 ] != 'a' ) {
96- printf ("unexpected pwd of %s\n looking for 'a'\n" , inBuf );
97- return -1 ;
98- }
67+ for (i = 0 ; i < (int )sizeof (inBuf ); i ++ ) {
68+ if (inBuf [i ] == '\n' ) {
69+ inBuf [i ] = '\0' ;
9970 break ;
71+ }
72+ }
10073
101- case 4 :
102- {
74+ len = (int )WSTRLEN (inBuf );
75+ if (len < 2 ) {
76+ printf ("pwd output too short: %s\n" , inBuf );
77+ return -1 ;
78+ }
79+ if (inBuf [len - 2 ] != '/' ) {
80+ printf ("unexpected pwd of %s, looking for '/'\n" , inBuf );
81+ return -1 ;
82+ }
83+ if (inBuf [len - 1 ] != 'a' ) {
84+ printf ("unexpected pwd of %s, looking for 'a'\n" , inBuf );
85+ return -1 ;
86+ }
87+ return 0 ;
88+ }
89+
90+ /* check that ls of empty dir shows only . and .. */
91+ static int checkLsEmpty (void )
92+ {
10393#ifdef WOLFSSH_ZEPHYR
104- /* No . and .. in zephyr fs API */
105- char expt1 [] = "wolfSSH sftp> " ;
106- char expt2 [] = "wolfSSH sftp> " ;
94+ /* No . and .. in zephyr fs API */
95+ char expt1 [] = "wolfSSH sftp> " ;
96+ char expt2 [] = "wolfSSH sftp> " ;
10797#else
108- char expt1 [] = ".\n..\nwolfSSH sftp> " ;
109- char expt2 [] = "..\n.\nwolfSSH sftp> " ;
98+ char expt1 [] = ".\n..\nwolfSSH sftp> " ;
99+ char expt2 [] = "..\n.\nwolfSSH sftp> " ;
110100#endif
111- if (WMEMCMP (expt1 , inBuf , sizeof (expt1 )) != 0 &&
112- WMEMCMP (expt2 , inBuf , sizeof (expt2 )) != 0 ) {
113- printf ("unexpected ls\n" );
114- printf ("\texpected \n%s\n\tor\n%s\n\tbut got\n%s\n" , expt1 ,
115- expt2 , inBuf );
116- return -1 ;
117- }
118- else
119- return 0 ;
120-
121- }
122-
123- case 6 :
124- if (WSTRNSTR (inBuf , "configure.ac" , sizeof (inBuf )) == NULL ) {
125- fprintf (stderr , "configure.ac not found in %s\n" , inBuf );
126- return 1 ;
127- }
128- else {
129- return 0 ;
130- }
101+ if (WMEMCMP (expt1 , inBuf , sizeof (expt1 )) != 0 &&
102+ WMEMCMP (expt2 , inBuf , sizeof (expt2 )) != 0 ) {
103+ printf ("unexpected ls\n" );
104+ printf ("\texpected \n%s\n\tor\n%s\n\tbut got\n%s\n" ,
105+ expt1 , expt2 , inBuf );
106+ return -1 ;
107+ }
108+ return 0 ;
109+ }
131110
132- case 10 :
133- return (WSTRNSTR (inBuf , "test-get" , sizeof (inBuf )) == NULL );
111+ /* check that ls output contains a specific file */
112+ static int checkLsHasConfigureAc (void )
113+ {
114+ if (WSTRNSTR (inBuf , "configure.ac" , sizeof (inBuf )) == NULL ) {
115+ fprintf (stderr , "configure.ac not found in %s\n" , inBuf );
116+ return 1 ;
117+ }
118+ return 0 ;
119+ }
134120
135- case 13 :
136- return (WSTRNSTR (inBuf , "test-get-2" , sizeof (inBuf )) == NULL );
121+ static int checkLsHasTestGet (void )
122+ {
123+ return (WSTRNSTR (inBuf , "test-get" ,
124+ sizeof (inBuf )) == NULL ) ? 1 : 0 ;
125+ }
137126
138- case 16 :
139- return (WSTRNSTR (inBuf , "size in bytes" , sizeof (inBuf )) == NULL );
127+ static int checkLsHasTestGet2 (void )
128+ {
129+ return (WSTRNSTR (inBuf , "test-get-2" ,
130+ sizeof (inBuf )) == NULL ) ? 1 : 0 ;
131+ }
140132
141- default :
142- break ;
143- }
144- WMEMSET (inBuf , 0 , sizeof (inBuf ));
145- return 0 ;
133+ static int checkLsSize (void )
134+ {
135+ return (WSTRNSTR (inBuf , "size in bytes" ,
136+ sizeof (inBuf )) == NULL ) ? 1 : 0 ;
146137}
147138
139+ static const SftpTestCmd cmds [] = {
140+ /* If a prior run was interrupted, files and directories
141+ * created during the test may still exist in the working
142+ * directory, causing mkdir to fail and ls checks to see
143+ * unexpected entries. Remove them here before starting.
144+ * These run as SFTP commands rather than local syscalls
145+ * so they are portable across all platforms (Windows,
146+ * Zephyr, POSIX). Failures are silently ignored since
147+ * the files may not exist. */
148+ { "rm a/configure.ac" , NULL },
149+ { "rmdir a" , NULL },
150+ { "rm test-get" , NULL },
151+ { "rm test-get-2" , NULL },
152+
153+ /* --- test sequence starts here --- */
154+ { "mkdir a" , NULL },
155+ { "cd a" , NULL },
156+ { "pwd" , checkPwdInA },
157+ { "ls" , checkLsEmpty },
158+ #ifdef WOLFSSH_ZEPHYR
159+ { "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure.ac" , NULL },
160+ #else
161+ { "put configure.ac" , NULL },
162+ #endif
163+ { "ls" , checkLsHasConfigureAc },
164+ #ifdef WOLFSSH_ZEPHYR
165+ { "get configure.ac "
166+ CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get" , NULL },
167+ #else
168+ { "get configure.ac test-get" , NULL },
169+ #endif
170+ { "rm configure.ac" , NULL },
171+ { "cd ../" , NULL },
172+ { "ls" , checkLsHasTestGet },
173+ { "rename test-get test-get-2" , NULL },
174+ { "rmdir a" , NULL },
175+ { "ls" , checkLsHasTestGet2 },
176+ { "chmod 600 test-get-2" , NULL },
177+ { "rm test-get-2" , NULL },
178+ { "ls -s" , checkLsSize },
179+ /* empty arg tests: must not underflow on pt[sz-1] */
180+ { "mkdir" , NULL },
181+ { "cd" , NULL },
182+ { "ls" , NULL },
183+ { "chmod" , NULL },
184+ { "rmdir" , NULL },
185+ { "rm" , NULL },
186+ { "rename" , NULL },
187+ { "get" , NULL },
188+ { "put" , NULL },
189+ { "exit" , NULL },
190+ };
191+ static int commandIdx = 0 ;
192+
148193
149194static int commandCb (const char * in , char * out , int outSz )
150195{
@@ -157,18 +202,26 @@ static int commandCb(const char* in, char* out, int outSz)
157202
158203 /* get command input */
159204 if (out ) {
160- int sz = (int )WSTRLEN (cmds [commandIdx ]);
205+ int sz = (int )WSTRLEN (cmds [commandIdx ]. cmd );
161206 if (outSz < sz ) {
162207 ret = -1 ;
163208 }
164209 else {
165- WMEMCPY (out , cmds [commandIdx ], sz );
210+ WMEMCPY (out , cmds [commandIdx ]. cmd , sz );
166211 }
167212
168- if (Expected (commandIdx ) != 0 ) {
169- fprintf (stderr , "Failed on command index %d\n" , commandIdx );
170- exit (1 ); /* abort out */
213+ /* validate output from the previous command */
214+ if (commandIdx > 0 &&
215+ cmds [commandIdx - 1 ].check != NULL ) {
216+ if (cmds [commandIdx - 1 ].check () != 0 ) {
217+ fprintf (stderr ,
218+ "Check failed for \"%s\" (index %d)\n" ,
219+ cmds [commandIdx - 1 ].cmd ,
220+ commandIdx - 1 );
221+ exit (1 );
222+ }
171223 }
224+ WMEMSET (inBuf , 0 , sizeof (inBuf ));
172225 commandIdx ++ ;
173226 }
174227 return ret ;
0 commit comments