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- /* empty arg tests: trigger pt[sz-1] underflow if sz == 0 */
72- "mkdir" ,
73- "cd" ,
74- "ls" ,
75- "chmod" ,
76- "rmdir" ,
77- "rm" ,
78- "rename" ,
79- "get" ,
80- "put" ,
81- "exit"
82- };
83- 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 */
8459static char inBuf [1024 ] = {0 };
8560
86- /* return 0 on success */
87- static int Expected ( int command )
61+ /* check that pwd output ends in /a */
62+ static int checkPwdInA ( void )
8863{
8964 int i ;
65+ int len ;
9066
91- switch (command ) {
92- case 3 : /* pwd */
93- /* working directory should not contain a '.' at the end */
94- for (i = 0 ; i < (int )sizeof (inBuf ); i ++ ) {
95- if (inBuf [i ] == '\n' ) {
96- inBuf [i ] = '\0' ;
97- break ;
98- }
99- }
100-
101- if (inBuf [WSTRLEN (inBuf ) - 2 ] != '/' ) {
102- printf ("unexpected pwd of %s\n looking for '/'\n" , inBuf );
103- return -1 ;
104- }
105- if (inBuf [WSTRLEN (inBuf ) - 1 ] != 'a' ) {
106- printf ("unexpected pwd of %s\n looking for 'a'\n" , inBuf );
107- return -1 ;
108- }
67+ for (i = 0 ; i < (int )sizeof (inBuf ); i ++ ) {
68+ if (inBuf [i ] == '\n' ) {
69+ inBuf [i ] = '\0' ;
10970 break ;
71+ }
72+ }
11073
111- case 4 :
112- {
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+ {
11393#ifdef WOLFSSH_ZEPHYR
114- /* No . and .. in zephyr fs API */
115- char expt1 [] = "wolfSSH sftp> " ;
116- char expt2 [] = "wolfSSH sftp> " ;
94+ /* No . and .. in zephyr fs API */
95+ char expt1 [] = "wolfSSH sftp> " ;
96+ char expt2 [] = "wolfSSH sftp> " ;
11797#else
118- char expt1 [] = ".\n..\nwolfSSH sftp> " ;
119- char expt2 [] = "..\n.\nwolfSSH sftp> " ;
98+ char expt1 [] = ".\n..\nwolfSSH sftp> " ;
99+ char expt2 [] = "..\n.\nwolfSSH sftp> " ;
120100#endif
121- if (WMEMCMP (expt1 , inBuf , sizeof (expt1 )) != 0 &&
122- WMEMCMP (expt2 , inBuf , sizeof (expt2 )) != 0 ) {
123- printf ("unexpected ls\n" );
124- printf ("\texpected \n%s\n\tor\n%s\n\tbut got\n%s\n" , expt1 ,
125- expt2 , inBuf );
126- return -1 ;
127- }
128- else
129- return 0 ;
130-
131- }
132-
133- case 6 :
134- if (WSTRNSTR (inBuf , "configure.ac" , sizeof (inBuf )) == NULL ) {
135- fprintf (stderr , "configure.ac not found in %s\n" , inBuf );
136- return 1 ;
137- }
138- else {
139- return 0 ;
140- }
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+ }
141110
142- case 10 :
143- 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+ }
144120
145- case 13 :
146- 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+ }
147126
148- case 16 :
149- 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+ }
150132
151- default :
152- break ;
153- }
154- WMEMSET (inBuf , 0 , sizeof (inBuf ));
155- return 0 ;
133+ static int checkLsSize (void )
134+ {
135+ return (WSTRNSTR (inBuf , "size in bytes" ,
136+ sizeof (inBuf )) == NULL ) ? 1 : 0 ;
156137}
157138
139+ static const SftpTestCmd cmds [] = {
140+ { "mkdir a" , NULL },
141+ { "cd a" , NULL },
142+ { "pwd" , checkPwdInA },
143+ { "ls" , checkLsEmpty },
144+ #ifdef WOLFSSH_ZEPHYR
145+ { "put " CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/configure.ac" , NULL },
146+ #else
147+ { "put configure.ac" , NULL },
148+ #endif
149+ { "ls" , checkLsHasConfigureAc },
150+ #ifdef WOLFSSH_ZEPHYR
151+ { "get configure.ac "
152+ CONFIG_WOLFSSH_SFTP_DEFAULT_DIR "/test-get" , NULL },
153+ #else
154+ { "get configure.ac test-get" , NULL },
155+ #endif
156+ { "rm configure.ac" , NULL },
157+ { "cd ../" , NULL },
158+ { "ls" , checkLsHasTestGet },
159+ { "rename test-get test-get-2" , NULL },
160+ { "rmdir a" , NULL },
161+ { "ls" , checkLsHasTestGet2 },
162+ { "chmod 600 test-get-2" , NULL },
163+ { "rm test-get-2" , NULL },
164+ { "ls -s" , checkLsSize },
165+ /* empty arg tests: must not underflow on pt[sz-1] */
166+ { "mkdir" , NULL },
167+ { "cd" , NULL },
168+ { "ls" , NULL },
169+ { "chmod" , NULL },
170+ { "rmdir" , NULL },
171+ { "rm" , NULL },
172+ { "rename" , NULL },
173+ { "get" , NULL },
174+ { "put" , NULL },
175+ { "exit" , NULL },
176+ };
177+ static int commandIdx = 0 ;
178+
158179
159180static int commandCb (const char * in , char * out , int outSz )
160181{
@@ -167,18 +188,26 @@ static int commandCb(const char* in, char* out, int outSz)
167188
168189 /* get command input */
169190 if (out ) {
170- int sz = (int )WSTRLEN (cmds [commandIdx ]);
191+ int sz = (int )WSTRLEN (cmds [commandIdx ]. cmd );
171192 if (outSz < sz ) {
172193 ret = -1 ;
173194 }
174195 else {
175- WMEMCPY (out , cmds [commandIdx ], sz );
196+ WMEMCPY (out , cmds [commandIdx ]. cmd , sz );
176197 }
177198
178- if (Expected (commandIdx ) != 0 ) {
179- fprintf (stderr , "Failed on command index %d\n" , commandIdx );
180- exit (1 ); /* abort out */
199+ /* validate output from the previous command */
200+ if (commandIdx > 0 &&
201+ cmds [commandIdx - 1 ].check != NULL ) {
202+ if (cmds [commandIdx - 1 ].check () != 0 ) {
203+ fprintf (stderr ,
204+ "Check failed for \"%s\" (index %d)\n" ,
205+ cmds [commandIdx - 1 ].cmd ,
206+ commandIdx - 1 );
207+ exit (1 );
208+ }
181209 }
210+ WMEMSET (inBuf , 0 , sizeof (inBuf ));
182211 commandIdx ++ ;
183212 }
184213 return ret ;
0 commit comments