1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*===================================================================== |
6 | ** |
7 | ** Source: ungetc.c (test 2) |
8 | ** |
9 | ** Purpose: Tests the PAL implementation of the ungetc function |
10 | ** |
11 | ** Dependencies: |
12 | ** fopen |
13 | ** fread |
14 | ** fclose |
15 | ** fseek |
16 | ** getc |
17 | ** |
18 | ** |
19 | **===================================================================*/ |
20 | |
21 | #include <palsuite.h> |
22 | |
23 | |
24 | int __cdecl main(int argc, char *argv[]) |
25 | { |
26 | const char szFileName[] = {"test2.txt" }; |
27 | const char szNewString[] = {"bar bar" }; |
28 | char szBuffer[MAX_PATH]; |
29 | FILE* pFile = NULL; |
30 | int nChar = 32; /* space */ |
31 | int i = 0; |
32 | int nRc = 0; |
33 | size_t nCount = 0; |
34 | |
35 | |
36 | if (0 != PAL_Initialize(argc,argv)) |
37 | { |
38 | return FAIL; |
39 | } |
40 | |
41 | |
42 | memset(szBuffer, 0, MAX_PATH); |
43 | |
44 | /* |
45 | ** open the file in write only mode, populate it and |
46 | ** attempt to push an unread character back on the stream |
47 | */ |
48 | |
49 | |
50 | /* open the file for read */ |
51 | pFile = fopen(szFileName, "r" ); |
52 | if (pFile == NULL) |
53 | { |
54 | Fail("ungetc: ERROR -> fopen failed to open the file \"%s\"" |
55 | " as read-only.n" , |
56 | szFileName); |
57 | } |
58 | |
59 | |
60 | /* |
61 | ** Call getc to get the first char and ungetc to put |
62 | ** it back. getc should read it again. |
63 | */ |
64 | |
65 | /* read a character */ |
66 | if ((nChar = getc(pFile)) == EOF) |
67 | { |
68 | Trace("ungetc: ERROR -> getc encountered an error reading.\n" ); |
69 | if (fclose(pFile) != 0) |
70 | { |
71 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
72 | } |
73 | Fail("" ); |
74 | } |
75 | |
76 | /* put it back */ |
77 | if ((nRc = ungetc(nChar, pFile)) == EOF) |
78 | { |
79 | Trace("ungetc: ERROR -> ungetc failed to push '%c' back onto the" |
80 | " stream.\n" ); |
81 | if (fclose(pFile) != 0) |
82 | { |
83 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
84 | } |
85 | Fail("" ); |
86 | } |
87 | |
88 | /* read it again... hopefully */ |
89 | if (((nChar = getc(pFile)) == EOF) || (nChar != nRc)) |
90 | { |
91 | Trace("ungetc: ERROR -> getc encountered an error reading.\n" ); |
92 | if (fclose(pFile) != 0) |
93 | { |
94 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
95 | } |
96 | Fail("" ); |
97 | } |
98 | |
99 | /* |
100 | ** test multiple ungetcs by replacing "foo" in the stream with "bar" |
101 | */ |
102 | |
103 | /* move the file pointer back to the beginning of the file */ |
104 | if (fseek(pFile, 0, SEEK_SET) != 0) |
105 | { |
106 | Trace("ungetc: ERROR -> fseek failed to move the file pointer to the " |
107 | "beginning of the file. GetLastError returned %ld\n" , |
108 | GetLastError()); |
109 | if (fclose(pFile) != 0) |
110 | { |
111 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
112 | } |
113 | Fail("" ); |
114 | } |
115 | |
116 | /* read a few characters */ |
117 | for (i = 0; i < 3; i++) |
118 | { |
119 | if (getc(pFile) == EOF) |
120 | { |
121 | Trace("ungetc: ERROR -> getc encountered an error reading. " |
122 | "GetLastError returned %ld\n" , |
123 | GetLastError()); |
124 | if (fclose(pFile) != 0) |
125 | { |
126 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
127 | } |
128 | Fail("" ); |
129 | } |
130 | } |
131 | |
132 | /* we just read "foo" so push "bar" back on the stream */ |
133 | for (i = 2; i >= 0; i--) |
134 | { |
135 | if ((nRc = ungetc(szNewString[i], pFile)) == EOF) |
136 | { |
137 | Trace("ungetc: ERROR -> ungetc failed to push '%c' back onto the" |
138 | " stream.\n" ); |
139 | if (fclose(pFile) != 0) |
140 | { |
141 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
142 | } |
143 | Fail("" ); |
144 | } |
145 | } |
146 | |
147 | |
148 | /* read the new and improved stream - I use szNewString because it |
149 | is correct length */ |
150 | nCount = fread(szBuffer, sizeof(char), strlen(szNewString), pFile); |
151 | |
152 | /* did we get the right number of characters?*/ |
153 | if (nCount != strlen(szNewString)) |
154 | { |
155 | Trace("ungetc: ERROR -> fread read %d characters from the stream but" |
156 | " %d characters were expected\n" , |
157 | nRc, |
158 | strlen(szNewString)); |
159 | if (fclose(pFile) != 0) |
160 | { |
161 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
162 | } |
163 | Fail("" ); |
164 | } |
165 | |
166 | /* did we get the right string? */ |
167 | if (strcmp(szBuffer, szNewString) != 0) |
168 | { |
169 | Trace("ungetc: ERROR -> fread returned \"%s\" but \"%s\" was " |
170 | "expected\n" , |
171 | szBuffer, |
172 | szNewString); |
173 | if (fclose(pFile) != 0) |
174 | { |
175 | Trace("ungetc: ERROR -> fclose failed to close the file.\n" ); |
176 | } |
177 | Fail("" ); |
178 | } |
179 | |
180 | if (fclose(pFile) != 0) |
181 | { |
182 | Fail("ungetc: ERROR -> fclose failed to close the file.\n" ); |
183 | } |
184 | |
185 | |
186 | PAL_Terminate(); |
187 | return PASS; |
188 | } |
189 | |