update for HEAD-2003021201
[reactos.git] / apps / testsets / msvcrt / fileio / _tfileio.c
1 /*
2  *  ReactOS test program - 
3  *
4  *  _tfileio.c
5  *
6  *  Copyright (C) 2002  Robert Dickenson <robd@reactos.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <tchar.h>
26 #include <wchar.h>
27 #include <stdio.h>
28
29
30 #ifdef UNICODE
31 #define _tfopen      _wfopen
32 #define _tunlink     _wunlink
33 #define _TEOF        WEOF
34 #define _gettchar    getwchar 
35 #define _puttchar    putwchar  
36 #define _THEX_FORMAT _T("0x%04x ")
37 #else /*UNICODE*/
38 #define _tfopen      fopen
39 #define _tunlink     _unlink
40 #define _TEOF        EOF
41 #define _gettchar    getchar
42 #define _puttchar    putchar
43 #define _THEX_FORMAT "0x%02x "
44 #endif /*UNICODE*/
45
46
47 #define TEST_BUFFER_SIZE 200
48 #define TEST_FILE_LINES  4
49
50 extern BOOL verbose_flagged;
51 extern BOOL status_flagged;
52
53 static TCHAR test_buffer[TEST_BUFFER_SIZE];
54
55 static TCHAR dos_data[] = _T("line1: this is a bunch of readable text.\r\n")\
56                    _T("line2: some more printable text and punctuation !@#$%^&*()\r\n")\
57                    _T("line3: followed up with some numerals 1234567890\r\n")\
58                    _T("line4: done.\r\n");
59
60 static TCHAR nix_data[] = _T("line1: this is a bunch of readable text.\n")\
61                    _T("line2: some more printable text and punctuation !@#$%^&*()\n")\
62                    _T("line3: followed up with some numerals 1234567890\n")\
63                    _T("line4: done.\n");
64
65 #ifdef UNICODE
66 #define TEST_B1_FILE_SIZE ((((sizeof(dos_data)/2)-1)+TEST_FILE_LINES)/2) // (166+4)/2=85
67 #define TEST_B2_FILE_SIZE (((sizeof(dos_data)/2)-1)*2)                   // (166*2)  =332
68 #define TEST_B3_FILE_SIZE ((((sizeof(nix_data)/2)-1)+TEST_FILE_LINES)/2) // (162+4)/2=83
69 #define TEST_B4_FILE_SIZE (((sizeof(nix_data)/2)-1)*2)                   // (162*2)  =324
70 #else /*UNICODE*/
71 #define TEST_B1_FILE_SIZE (sizeof(dos_data)-1+TEST_FILE_LINES) // (166+4)=170
72 #define TEST_B2_FILE_SIZE (sizeof(dos_data)-1-TEST_FILE_LINES) // (166-4)=162
73 #define TEST_B3_FILE_SIZE (sizeof(nix_data)-1+TEST_FILE_LINES) // (162+4)=166
74 #define TEST_B4_FILE_SIZE (sizeof(nix_data)-1)                 // (162)  =162
75 #endif /*UNICODE*/
76
77
78 //    result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
79
80 static BOOL test_file_truncate(TCHAR* file_name)
81 {
82     BOOL result = FALSE;
83     int count = -1;
84     int error_code;
85     TCHAR ch;
86     TCHAR* file_data = _T("this file should have been truncated to zero bytes...");
87     FILE *file = _tfopen(file_name, _T("wb"));
88
89     if (verbose_flagged) {
90         _tprintf(_T("test_file_truncate(\"%s\")\n"), file_name);
91     }
92
93     if (file != NULL) {
94         if (_fputts(file_data, file) != _TEOF) {
95         } else {
96             _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
97             _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
98         }
99         fclose(file);
100     } else {
101         _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
102         _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
103     }
104
105     file = _tfopen(file_name, _T("wb"));
106     if (file != NULL) {
107         error_code = ferror(file);
108         if (error_code) {
109              _tprintf(_T("ERROR: (%s) ferror returned %d\n"), file_name, error_code);
110         }
111         fclose(file);
112     } else {
113         _tprintf(_T("ERROR: (%s) failed to open file for truncating\n"), file_name);
114     }
115
116     file = _tfopen(file_name, _T("rb"));
117     if (file != NULL) {
118         count = 0;
119         while ((ch = _fgettc(file)) != _TEOF) {
120             if (verbose_flagged) {
121                 _tprintf(_THEX_FORMAT, ch);
122             }
123             ++count;
124         }
125         error_code = ferror(file);
126         if (error_code) {
127              _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
128              perror("Read error");
129         }
130         fclose(file);
131     } else {
132         _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
133     }
134     if (count) {
135         result = TRUE;
136     }
137     return result;
138 }
139
140 static BOOL create_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
141 {
142     BOOL result = FALSE;
143     FILE *file = _tfopen(file_name, file_mode);
144     if (file != NULL) {
145         if (_fputts(file_data, file) != _TEOF) {
146             result = TRUE;
147         } else {
148             _tprintf(_T("ERROR: failed to write data to file \"%s\"\n"), file_name);
149             _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
150         }
151         fclose(file);
152     } else {
153         _tprintf(_T("ERROR: failed to open/create file \"%s\" for output\n"), file_name);
154         _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
155     }
156     return result;
157 }
158
159 static BOOL verify_output_file(TCHAR* file_name, TCHAR* file_mode, TCHAR* file_data)
160 {
161     int error_code;
162     int offset = 0;
163     int line_num = 0;
164     BOOL result = FALSE;
165     BOOL error_flagged = FALSE;
166     FILE* file = _tfopen(file_name, file_mode);
167     if (file == NULL) {
168         _tprintf(_T("ERROR: (%s) Can't open file for reading\n"), file_name);
169         _tprintf(_T("ERROR: ferror returned %d\n"), ferror(file));
170         return FALSE;
171     } else if (status_flagged) {
172         _tprintf(_T("STATUS: (%s) opened file for reading\n"), file_name);
173     }
174     while (_fgetts(test_buffer, TEST_BUFFER_SIZE, file)) {
175         int length = _tcslen(test_buffer);
176         int req_len = _tcschr(file_data+offset, _T('\n')) - (file_data+offset) + 1;
177
178         ++line_num;
179         if (length > req_len) {
180             _tprintf(_T("ERROR: read excess bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
181             error_flagged = TRUE;
182             break;
183         }
184         if (length < req_len) {
185             _tprintf(_T("ERROR: read to few bytes from line %d, length %d, but expected %d\n"), line_num, length, req_len);
186             error_flagged = TRUE;
187             break;
188         }
189         if (status_flagged) {
190             _tprintf(_T("STATUS: Verifying %d bytes read from line %d\n"), length, line_num);
191         }
192         if (_tcsncmp(test_buffer, file_data+offset, length - 1) == 0) {
193             result = TRUE;
194         } else {
195             if (status_flagged) {
196                 int i;
197                 _tprintf(_T("WARNING: (%s) failed to verify file\n"), file_name);
198                 for (i = 0; i < length; i++) {
199                     if (file_data[offset+i] != test_buffer[i]) {
200                         _tprintf(_T("line %d, offset %d expected: 0x%04x found: 0x%04x\n"), line_num, i, (int)file_data[offset+i], (int)test_buffer[i]);
201                     }
202                 }
203                 _tprintf(_T("\n"));
204             } else {
205                 error_flagged = TRUE;
206             }
207         }
208         offset += length;
209     }
210     error_code = ferror(file);
211     if (error_code) {
212          _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
213          perror("Read error");
214     }
215     if (!line_num) {
216         _tprintf(_T("ERROR: (%s) failed to read from file\n"), file_name);
217     }
218     if (error_flagged == TRUE) {
219         _tprintf(_T("ERROR: (%s) failed to verify file\n"), file_name);
220         result = FALSE;
221     }
222     fclose(file);
223     return result;
224 }
225
226 static int create_test_file(TCHAR* file_name, TCHAR* write_mode, TCHAR* read_mode, TCHAR* file_data)
227 {
228     if (status_flagged) {
229         _tprintf(_T("STATUS: Attempting to create output file %s\n"), file_name);
230     }
231     if (create_output_file(file_name, write_mode, file_data)) {
232         if (status_flagged) {
233             _tprintf(_T("STATUS: Attempting to verify output file %s\n"), file_name);
234         }
235         if (verify_output_file(file_name, read_mode, file_data)) {
236             if (status_flagged) {
237                 _tprintf(_T("SUCCESS: %s verified ok\n"), file_name);
238             }
239         } else {
240             //_tprintf(_T("ERROR: failed to verify file %s\n"), file_name);
241             return 2;
242         }
243     } else {
244         _tprintf(_T("ERROR: failed to create file %s\n"), file_name);
245         return 1;
246     }
247     return 0;
248 }
249
250 static int check_file_size(TCHAR* file_name, TCHAR* file_mode, int expected)
251 {
252     int count = 0;
253     FILE* file;
254     TCHAR ch;
255     int error_code;
256
257     if (status_flagged) {
258         //_tprintf(_T("STATUS: (%s) checking for %d bytes in %s mode\n"), file_name, expected, _tcschr(file_mode, _T('b')) ? _T("binary") : _T("text"));
259         _tprintf(_T("STATUS: (%s) checking for %d bytes with mode %s\n"), file_name, expected, file_mode);
260     }
261     file = _tfopen(file_name, file_mode);
262     if (file == NULL) {
263         _tprintf(_T("ERROR: (%s) failed to open file for reading\n"), file_name);
264         return 1;
265     }
266     while ((ch = _fgettc(file)) != _TEOF) {
267         if (verbose_flagged) {
268             _tprintf(_THEX_FORMAT, ch);
269         }
270         ++count;
271     }
272     error_code = ferror(file);
273     if (error_code) {
274          _tprintf(_T("ERROR: (%s) ferror returned %d after reading\n"), file_name, error_code);
275          perror("Read error");
276     }
277
278     if (verbose_flagged) {
279 //        _puttc(_T('\n'), stdout);
280     }
281     fclose(file);
282     if (count == expected) {
283         if (status_flagged) {
284             _tprintf(_T("PASSED: (%s) read %d bytes\n"), file_name, count);
285         }
286     } else {
287         _tprintf(_T("FAILED: (%s) read %d bytes but expected %d using mode \"%s\"\n"), file_name, count, expected, file_mode);
288     }
289     return (count == expected) ? 0 : -1;
290 }
291
292 static int test_console_io(void)
293 {
294     TCHAR buffer[81];
295     TCHAR ch;
296     int i, j;
297
298     _tprintf(_T("Enter a line for echoing:\n"));
299
300     //for (i = 0; (i < 80) && ((ch = _gettchar()) != _TEOF) && (ch != _T('\n')); i++) {
301     for (i = 0; (i < 80) && ((ch = _gettc(stdin)) != _TEOF) && (ch != _T('\n')); i++) {
302         buffer[i] = (TCHAR)ch;
303     }
304     buffer[i] = _T('\0');
305     for (j = 0; j < i; j++) {
306         _puttc(buffer[j], stdout);
307     }
308     _puttc(_T('\n'), stdout);
309     _tprintf(_T("%s\n"), buffer);
310     return 0;
311 }
312
313 static int test_console_getchar(void)
314 {
315     int result = 0;
316     TCHAR ch;
317
318     _tprintf(_T("Enter lines for dumping or <ctrl-z><nl> to finish:\n"));
319
320     //while ((ch = _gettchar()) != _TEOF) {
321     while ((ch = _gettc(stdin)) != _TEOF) {
322         _tprintf(_THEX_FORMAT, ch);
323         //printf("0x%04x ", ch);
324     }
325     return result;
326 }
327
328 static int test_console_putch(void)
329 {
330     int result = 0;
331
332     _putch('1');
333     _putch('@');
334     _putch('3');
335     _putch(':');
336     _putch('\n');
337     _putch('a');
338     _putch('B');
339     _putch('c');
340     _putch(':');
341     _putch('\n');
342     return result;
343 }
344
345 static int test_unlink_files(void)
346 {
347     int result = 0;
348
349     //printf("sizeof dos_data: %d\n", sizeof(dos_data));
350     //printf("sizeof nix_data: %d\n", sizeof(nix_data));
351
352     result |= _tunlink(_T("binary.dos"));
353     result |= _tunlink(_T("binary.nix"));
354     result |= _tunlink(_T("text.dos"));
355     result |= _tunlink(_T("text.nix"));
356     return result;
357 }
358
359 static int test_text_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
360 {
361     int result = 0;
362
363     result = create_test_file(file_name, _T("w"), _T("r"), file_data);
364     result = check_file_size(file_name, _T("r"), tsize);
365     result = check_file_size(file_name, _T("rb"), bsize);
366     return result;
367 }
368
369 static int test_binary_fileio(TCHAR* file_name, TCHAR* file_data, int tsize, int bsize)
370 {
371     int result = 0;
372
373     result = create_test_file(file_name, _T("wb"), _T("rb"), file_data);
374     result = check_file_size(file_name, _T("r"), tsize);
375     result = check_file_size(file_name, _T("rb"), bsize);
376     return result;
377 }
378
379 static int test_files(int test_num, char* type)
380 {
381     int result = 0;
382
383     printf("performing test: %d (%s)\n", test_num, type);
384
385
386     if (test_file_truncate(_T("zerosize.foo"))) {
387         printf("System unable to truncate files yet, unlinking:\n");
388         test_unlink_files();
389     }
390
391     switch (test_num) {
392     case 1:
393         result = test_text_fileio(_T("text.dos"), dos_data, 166, TEST_B1_FILE_SIZE);
394         break;
395     case 2:
396         result = test_binary_fileio(_T("binary.dos"), dos_data, TEST_B2_FILE_SIZE, 166);
397         break;
398     case 3:
399         result = test_text_fileio(_T("text.nix"), nix_data, 162, TEST_B3_FILE_SIZE);
400         break;
401     case 4:
402         result = test_binary_fileio(_T("binary.nix"), nix_data, TEST_B4_FILE_SIZE, 162);
403         break;
404     case 5:
405         result = test_console_io();
406         break;
407     case 6:
408         result = test_console_getchar();
409         break;
410     case 7:
411         result = test_console_putch();
412         break;
413     case -1:
414         result = test_unlink_files();
415         break;
416     default:
417         _tprintf(_T("no test number selected\n"));
418         break;
419     }
420     return result;
421 }