msvcirt: Add implementation of streambuf::pbackfail.
[wine.git] / dlls / msvcirt / tests / msvcirt.c
blobeca030493e802eda086eac2455c4c8598c957e4b
1 /*
2 * Copyright 2015 Iván Matellanes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdio.h>
20 #include <windef.h>
21 #include <winbase.h>
22 #include "wine/test.h"
24 typedef void (*vtable_ptr)(void);
26 /* class streambuf */
27 typedef struct {
28 const vtable_ptr *vtable;
29 int allocated;
30 int unbuffered;
31 int stored_char;
32 char *base;
33 char *ebuf;
34 char *pbase;
35 char *pptr;
36 char *epptr;
37 char *eback;
38 char *gptr;
39 char *egptr;
40 int do_lock;
41 CRITICAL_SECTION lock;
42 } streambuf;
44 #undef __thiscall
45 #ifdef __i386__
46 #define __thiscall __stdcall
47 #else
48 #define __thiscall __cdecl
49 #endif
51 /* streambuf */
52 static streambuf* (*__thiscall p_streambuf_reserve_ctor)(streambuf*, char*, int);
53 static streambuf* (*__thiscall p_streambuf_ctor)(streambuf*);
54 static void (*__thiscall p_streambuf_dtor)(streambuf*);
55 static int (*__thiscall p_streambuf_allocate)(streambuf*);
56 static void (*__thiscall p_streambuf_clrclock)(streambuf*);
57 static int (*__thiscall p_streambuf_doallocate)(streambuf*);
58 static void (*__thiscall p_streambuf_gbump)(streambuf*, int);
59 static void (*__thiscall p_streambuf_lock)(streambuf*);
60 static int (*__thiscall p_streambuf_pbackfail)(streambuf*, int);
61 static void (*__thiscall p_streambuf_pbump)(streambuf*, int);
62 static int (*__thiscall p_streambuf_sbumpc)(streambuf*);
63 static void (*__thiscall p_streambuf_setb)(streambuf*, char*, char*, int);
64 static void (*__thiscall p_streambuf_setlock)(streambuf*);
65 static streambuf* (*__thiscall p_streambuf_setbuf)(streambuf*, char*, int);
66 static int (*__thiscall p_streambuf_sgetc)(streambuf*);
67 static int (*__thiscall p_streambuf_snextc)(streambuf*);
68 static int (*__thiscall p_streambuf_sputc)(streambuf*, int);
69 static void (*__thiscall p_streambuf_stossc)(streambuf*);
70 static int (*__thiscall p_streambuf_sync)(streambuf*);
71 static void (*__thiscall p_streambuf_unlock)(streambuf*);
72 static int (*__thiscall p_streambuf_xsgetn)(streambuf*, char*, int);
73 static int (*__thiscall p_streambuf_xsputn)(streambuf*, const char*, int);
75 /* Emulate a __thiscall */
76 #ifdef __i386__
78 #include "pshpack1.h"
79 struct thiscall_thunk
81 BYTE pop_eax; /* popl %eax (ret addr) */
82 BYTE pop_edx; /* popl %edx (func) */
83 BYTE pop_ecx; /* popl %ecx (this) */
84 BYTE push_eax; /* pushl %eax */
85 WORD jmp_edx; /* jmp *%edx */
87 #include "poppack.h"
89 static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
90 static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
91 static void * (WINAPI *call_thiscall_func3)( void *func, void *this, const void *a, const void *b );
92 static void * (WINAPI *call_thiscall_func4)( void *func, void *this, const void *a, const void *b,
93 const void *c );
94 static void * (WINAPI *call_thiscall_func5)( void *func, void *this, const void *a, const void *b,
95 const void *c, const void *d );
97 static void init_thiscall_thunk(void)
99 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
100 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
101 thunk->pop_eax = 0x58; /* popl %eax */
102 thunk->pop_edx = 0x5a; /* popl %edx */
103 thunk->pop_ecx = 0x59; /* popl %ecx */
104 thunk->push_eax = 0x50; /* pushl %eax */
105 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
106 call_thiscall_func1 = (void *)thunk;
107 call_thiscall_func2 = (void *)thunk;
108 call_thiscall_func3 = (void *)thunk;
109 call_thiscall_func4 = (void *)thunk;
110 call_thiscall_func5 = (void *)thunk;
113 #define call_func1(func,_this) call_thiscall_func1(func,_this)
114 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
115 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
116 #define call_func4(func,_this,a,b,c) call_thiscall_func4(func,_this,(const void*)(a),(const void*)(b), \
117 (const void*)(c))
118 #define call_func5(func,_this,a,b,c,d) call_thiscall_func5(func,_this,(const void*)(a),(const void*)(b), \
119 (const void*)(c), (const void *)(d))
121 #else
123 #define init_thiscall_thunk()
124 #define call_func1(func,_this) func(_this)
125 #define call_func2(func,_this,a) func(_this,a)
126 #define call_func3(func,_this,a,b) func(_this,a,b)
127 #define call_func4(func,_this,a,b,c) func(_this,a,b,c)
128 #define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d)
130 #endif /* __i386__ */
132 static HMODULE msvcirt;
133 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcirt,y)
134 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
135 static BOOL init(void)
137 msvcirt = LoadLibraryA("msvcirt.dll");
138 if(!msvcirt) {
139 win_skip("msvcirt.dll not installed\n");
140 return FALSE;
143 if(sizeof(void*) == 8) { /* 64-bit initialization */
144 SET(p_streambuf_reserve_ctor, "??0streambuf@@IEAA@PEADH@Z");
145 SET(p_streambuf_ctor, "??0streambuf@@IEAA@XZ");
146 SET(p_streambuf_dtor, "??1streambuf@@UEAA@XZ");
147 SET(p_streambuf_allocate, "?allocate@streambuf@@IEAAHXZ");
148 SET(p_streambuf_clrclock, "?clrlock@streambuf@@QEAAXXZ");
149 SET(p_streambuf_doallocate, "?doallocate@streambuf@@MEAAHXZ");
150 SET(p_streambuf_gbump, "?gbump@streambuf@@IEAAXH@Z");
151 SET(p_streambuf_lock, "?lock@streambuf@@QEAAXXZ");
152 SET(p_streambuf_pbackfail, "?pbackfail@streambuf@@UEAAHH@Z");
153 SET(p_streambuf_pbump, "?pbump@streambuf@@IEAAXH@Z");
154 SET(p_streambuf_sbumpc, "?sbumpc@streambuf@@QEAAHXZ");
155 SET(p_streambuf_setb, "?setb@streambuf@@IEAAXPEAD0H@Z");
156 SET(p_streambuf_setbuf, "?setbuf@streambuf@@UEAAPEAV1@PEADH@Z");
157 SET(p_streambuf_setlock, "?setlock@streambuf@@QEAAXXZ");
158 SET(p_streambuf_sgetc, "?sgetc@streambuf@@QEAAHXZ");
159 SET(p_streambuf_snextc, "?snextc@streambuf@@QEAAHXZ");
160 SET(p_streambuf_sputc, "?sputc@streambuf@@QEAAHH@Z");
161 SET(p_streambuf_stossc, "?stossc@streambuf@@QEAAXXZ");
162 SET(p_streambuf_sync, "?sync@streambuf@@UEAAHXZ");
163 SET(p_streambuf_unlock, "?unlock@streambuf@@QEAAXXZ");
164 SET(p_streambuf_xsgetn, "?xsgetn@streambuf@@UEAAHPEADH@Z");
165 SET(p_streambuf_xsputn, "?xsputn@streambuf@@UEAAHPEBDH@Z");
166 } else {
167 SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE@PADH@Z");
168 SET(p_streambuf_ctor, "??0streambuf@@IAE@XZ");
169 SET(p_streambuf_dtor, "??1streambuf@@UAE@XZ");
170 SET(p_streambuf_allocate, "?allocate@streambuf@@IAEHXZ");
171 SET(p_streambuf_clrclock, "?clrlock@streambuf@@QAEXXZ");
172 SET(p_streambuf_doallocate, "?doallocate@streambuf@@MAEHXZ");
173 SET(p_streambuf_gbump, "?gbump@streambuf@@IAEXH@Z");
174 SET(p_streambuf_lock, "?lock@streambuf@@QAEXXZ");
175 SET(p_streambuf_pbackfail, "?pbackfail@streambuf@@UAEHH@Z");
176 SET(p_streambuf_pbump, "?pbump@streambuf@@IAEXH@Z");
177 SET(p_streambuf_sbumpc, "?sbumpc@streambuf@@QAEHXZ");
178 SET(p_streambuf_setb, "?setb@streambuf@@IAEXPAD0H@Z");
179 SET(p_streambuf_setbuf, "?setbuf@streambuf@@UAEPAV1@PADH@Z");
180 SET(p_streambuf_setlock, "?setlock@streambuf@@QAEXXZ");
181 SET(p_streambuf_sgetc, "?sgetc@streambuf@@QAEHXZ");
182 SET(p_streambuf_snextc, "?snextc@streambuf@@QAEHXZ");
183 SET(p_streambuf_sputc, "?sputc@streambuf@@QAEHH@Z");
184 SET(p_streambuf_stossc, "?stossc@streambuf@@QAEXXZ");
185 SET(p_streambuf_sync, "?sync@streambuf@@UAEHXZ");
186 SET(p_streambuf_unlock, "?unlock@streambuf@@QAEXXZ");
187 SET(p_streambuf_xsgetn, "?xsgetn@streambuf@@UAEHPADH@Z");
188 SET(p_streambuf_xsputn, "?xsputn@streambuf@@UAEHPBDH@Z");
191 init_thiscall_thunk();
192 return TRUE;
195 static int overflow_count, underflow_count;
196 static streambuf *test_this;
197 static char test_get_buffer[24];
198 static int buffer_pos, get_end;
200 #ifdef __i386__
201 static int __thiscall test_streambuf_overflow(int ch)
202 #else
203 static int __thiscall test_streambuf_overflow(streambuf *this, int ch)
204 #endif
206 overflow_count++;
207 if (ch == 'L') /* simulate a failure */
208 return EOF;
209 if (!test_this->unbuffered)
210 test_this->pptr = test_this->pbase + 5;
211 return ch;
214 #ifdef __i386__
215 static int __thiscall test_streambuf_underflow(void)
216 #else
217 static int __thiscall test_streambuf_underflow(streambuf *this)
218 #endif
220 underflow_count++;
221 if (test_this->unbuffered) {
222 return (buffer_pos < 23) ? test_get_buffer[buffer_pos++] : EOF;
223 } else if (test_this->gptr < test_this->egptr) {
224 return *test_this->gptr;
225 } else {
226 return get_end ? EOF : *(test_this->gptr = test_this->eback);
230 struct streambuf_lock_arg
232 streambuf *sb;
233 HANDLE lock[4];
234 HANDLE test[4];
237 static DWORD WINAPI lock_streambuf(void *arg)
239 struct streambuf_lock_arg *lock_arg = arg;
240 call_func1(p_streambuf_lock, lock_arg->sb);
241 SetEvent(lock_arg->lock[0]);
242 WaitForSingleObject(lock_arg->test[0], INFINITE);
243 call_func1(p_streambuf_lock, lock_arg->sb);
244 SetEvent(lock_arg->lock[1]);
245 WaitForSingleObject(lock_arg->test[1], INFINITE);
246 call_func1(p_streambuf_lock, lock_arg->sb);
247 SetEvent(lock_arg->lock[2]);
248 WaitForSingleObject(lock_arg->test[2], INFINITE);
249 call_func1(p_streambuf_unlock, lock_arg->sb);
250 SetEvent(lock_arg->lock[3]);
251 WaitForSingleObject(lock_arg->test[3], INFINITE);
252 call_func1(p_streambuf_unlock, lock_arg->sb);
253 return 0;
256 static void test_streambuf(void)
258 streambuf sb, sb2, sb3, *psb;
259 vtable_ptr test_streambuf_vtbl[11];
260 struct streambuf_lock_arg lock_arg;
261 HANDLE thread;
262 char reserve[16];
263 int ret, i;
264 BOOL locked;
266 memset(&sb, 0xab, sizeof(streambuf));
267 memset(&sb2, 0xab, sizeof(streambuf));
268 memset(&sb3, 0xab, sizeof(streambuf));
270 /* constructors */
271 call_func1(p_streambuf_ctor, &sb);
272 ok(sb.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb.allocated);
273 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
274 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
275 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
276 ok(sb.lock.LockCount == -1, "wrong critical section state, expected -1 got %d\n", sb.lock.LockCount);
277 call_func3(p_streambuf_reserve_ctor, &sb2, reserve, 16);
278 ok(sb2.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb2.allocated);
279 ok(sb2.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb2.unbuffered);
280 ok(sb2.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb2.base);
281 ok(sb2.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb2.ebuf);
282 ok(sb.lock.LockCount == -1, "wrong critical section state, expected -1 got %d\n", sb.lock.LockCount);
283 call_func1(p_streambuf_ctor, &sb3);
284 ok(sb3.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb3.allocated);
285 ok(sb3.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb3.unbuffered);
286 ok(sb3.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb3.base);
287 ok(sb3.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb3.ebuf);
289 memcpy(test_streambuf_vtbl, sb.vtable, sizeof(test_streambuf_vtbl));
290 test_streambuf_vtbl[7] = (vtable_ptr)&test_streambuf_overflow;
291 test_streambuf_vtbl[8] = (vtable_ptr)&test_streambuf_underflow;
292 sb2.vtable = test_streambuf_vtbl;
293 sb3.vtable = test_streambuf_vtbl;
294 overflow_count = underflow_count = 0;
295 strcpy(test_get_buffer, "CompuGlobalHyperMegaNet");
296 buffer_pos = get_end = 0;
298 /* setlock */
299 ok(sb.do_lock == -1, "expected do_lock value -1, got %d\n", sb.do_lock);
300 call_func1(p_streambuf_setlock, &sb);
301 ok(sb.do_lock == -2, "expected do_lock value -2, got %d\n", sb.do_lock);
302 call_func1(p_streambuf_setlock, &sb);
303 ok(sb.do_lock == -3, "expected do_lock value -3, got %d\n", sb.do_lock);
304 sb.do_lock = 3;
305 call_func1(p_streambuf_setlock, &sb);
306 ok(sb.do_lock == 2, "expected do_lock value 2, got %d\n", sb.do_lock);
308 /* clrlock */
309 sb.do_lock = -2;
310 call_func1(p_streambuf_clrclock, &sb);
311 ok(sb.do_lock == -1, "expected do_lock value -1, got %d\n", sb.do_lock);
312 call_func1(p_streambuf_clrclock, &sb);
313 ok(sb.do_lock == 0, "expected do_lock value 0, got %d\n", sb.do_lock);
314 call_func1(p_streambuf_clrclock, &sb);
315 ok(sb.do_lock == 1, "expected do_lock value 1, got %d\n", sb.do_lock);
316 call_func1(p_streambuf_clrclock, &sb);
317 ok(sb.do_lock == 1, "expected do_lock value 1, got %d\n", sb.do_lock);
319 /* lock/unlock */
320 lock_arg.sb = &sb;
321 for (i = 0; i < 4; i++) {
322 lock_arg.lock[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
323 ok(lock_arg.lock[i] != NULL, "CreateEventW failed\n");
324 lock_arg.test[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
325 ok(lock_arg.test[i] != NULL, "CreateEventW failed\n");
328 sb.do_lock = 0;
329 thread = CreateThread(NULL, 0, lock_streambuf, (void*)&lock_arg, 0, NULL);
330 ok(thread != NULL, "CreateThread failed\n");
331 WaitForSingleObject(lock_arg.lock[0], INFINITE);
332 locked = TryEnterCriticalSection(&sb.lock);
333 ok(locked != 0, "could not lock the streambuf\n");
334 LeaveCriticalSection(&sb.lock);
336 sb.do_lock = 1;
337 SetEvent(lock_arg.test[0]);
338 WaitForSingleObject(lock_arg.lock[1], INFINITE);
339 locked = TryEnterCriticalSection(&sb.lock);
340 ok(locked != 0, "could not lock the streambuf\n");
341 LeaveCriticalSection(&sb.lock);
343 sb.do_lock = -1;
344 SetEvent(lock_arg.test[1]);
345 WaitForSingleObject(lock_arg.lock[2], INFINITE);
346 locked = TryEnterCriticalSection(&sb.lock);
347 ok(locked == 0, "the streambuf was not locked before\n");
349 sb.do_lock = 0;
350 SetEvent(lock_arg.test[2]);
351 WaitForSingleObject(lock_arg.lock[3], INFINITE);
352 locked = TryEnterCriticalSection(&sb.lock);
353 ok(locked == 0, "the streambuf was not locked before\n");
354 sb.do_lock = -1;
356 /* setb */
357 call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 0);
358 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
359 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
360 call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 4);
361 ok(sb.allocated == 4, "wrong allocate value, expected 4 got %d\n", sb.allocated);
362 sb.allocated = 0;
363 call_func4(p_streambuf_setb, &sb, NULL, NULL, 3);
364 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
366 /* setbuf */
367 psb = call_func3(p_streambuf_setbuf, &sb, NULL, 5);
368 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
369 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
370 ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered);
371 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
372 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
373 psb = call_func3(p_streambuf_setbuf, &sb, reserve, 0);
374 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
375 ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered);
376 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
377 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
378 psb = call_func3(p_streambuf_setbuf, &sb, reserve, 16);
379 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
380 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
381 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
382 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
383 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
384 psb = call_func3(p_streambuf_setbuf, &sb, NULL, 8);
385 ok(psb == NULL, "wrong return value, expected %p got %p\n", NULL, psb);
386 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
387 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
388 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
390 /* allocate */
391 ret = (int) call_func1(p_streambuf_allocate, &sb);
392 ok(ret == 0, "wrong return value, expected 0 got %d\n", ret);
393 sb.base = NULL;
394 ret = (int) call_func1(p_streambuf_allocate, &sb);
395 ok(ret == 1, "wrong return value, expected 1 got %d\n", ret);
396 ok(sb.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb.allocated);
397 ok(sb.ebuf - sb.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb.ebuf, sb.base);
399 /* doallocate */
400 ret = (int) call_func1(p_streambuf_doallocate, &sb2);
401 ok(ret == 1, "doallocate failed, got %d\n", ret);
402 ok(sb2.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb2.allocated);
403 ok(sb2.ebuf - sb2.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb2.ebuf, sb2.base);
404 ret = (int) call_func1(p_streambuf_doallocate, &sb3);
405 ok(ret == 1, "doallocate failed, got %d\n", ret);
406 ok(sb3.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb3.allocated);
407 ok(sb3.ebuf - sb3.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb3.ebuf, sb3.base);
409 /* sb: buffered, space available */
410 sb.eback = sb.gptr = sb.base;
411 sb.egptr = sb.base + 256;
412 sb.pbase = sb.pptr = sb.base + 256;
413 sb.epptr = sb.base + 512;
414 /* sb2: buffered, no space available */
415 sb2.eback = sb2.base;
416 sb2.gptr = sb2.egptr = sb2.base + 256;
417 sb2.pbase = sb2.base + 256;
418 sb2.pptr = sb2.epptr = sb2.base + 512;
419 /* sb3: unbuffered */
420 sb3.unbuffered = 1;
422 /* gbump */
423 call_func2(p_streambuf_gbump, &sb, 10);
424 ok(sb.gptr == sb.eback + 10, "advance get pointer failed, expected %p got %p\n", sb.eback + 10, sb.gptr);
425 call_func2(p_streambuf_gbump, &sb, -15);
426 ok(sb.gptr == sb.eback - 5, "advance get pointer failed, expected %p got %p\n", sb.eback - 5, sb.gptr);
427 sb.gptr = sb.eback;
429 /* pbump */
430 call_func2(p_streambuf_pbump, &sb, -2);
431 ok(sb.pptr == sb.pbase - 2, "advance put pointer failed, expected %p got %p\n", sb.pbase - 2, sb.pptr);
432 call_func2(p_streambuf_pbump, &sb, 20);
433 ok(sb.pptr == sb.pbase + 18, "advance put pointer failed, expected %p got %p\n", sb.pbase + 18, sb.pptr);
434 sb.pptr = sb.pbase;
436 /* sync */
437 ret = (int) call_func1(p_streambuf_sync, &sb);
438 ok(ret == EOF, "sync failed, expected EOF got %d\n", ret);
439 sb.gptr = sb.egptr;
440 ret = (int) call_func1(p_streambuf_sync, &sb);
441 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
442 sb.gptr = sb.egptr + 1;
443 ret = (int) call_func1(p_streambuf_sync, &sb);
444 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
445 sb.gptr = sb.eback;
446 ret = (int) call_func1(p_streambuf_sync, &sb2);
447 ok(ret == EOF, "sync failed, expected EOF got %d\n", ret);
448 sb2.pptr = sb2.pbase;
449 ret = (int) call_func1(p_streambuf_sync, &sb2);
450 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
451 sb2.pptr = sb2.pbase - 1;
452 ret = (int) call_func1(p_streambuf_sync, &sb2);
453 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
454 sb2.pptr = sb2.epptr;
455 ret = (int) call_func1(p_streambuf_sync, &sb3);
456 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
458 /* sgetc */
459 strcpy(sb2.eback, "WorstTestEver");
460 test_this = &sb2;
461 ret = (int) call_func1(p_streambuf_sgetc, &sb2);
462 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
463 ok(underflow_count == 1, "expected call to underflow\n");
464 ok(sb2.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb2.stored_char);
465 sb2.gptr++;
466 ret = (int) call_func1(p_streambuf_sgetc, &sb2);
467 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
468 ok(underflow_count == 2, "expected call to underflow\n");
469 ok(sb2.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb2.stored_char);
470 sb2.gptr = sb2.egptr;
471 test_this = &sb3;
472 ret = (int) call_func1(p_streambuf_sgetc, &sb3);
473 ok(ret == 'C', "expected 'C' got '%c'\n", ret);
474 ok(underflow_count == 3, "expected call to underflow\n");
475 ok(sb3.stored_char == 'C', "wrong stored character, expected 'C' got %c\n", sb3.stored_char);
476 sb3.stored_char = 'b';
477 ret = (int) call_func1(p_streambuf_sgetc, &sb3);
478 ok(ret == 'b', "expected 'b' got '%c'\n", ret);
479 ok(underflow_count == 3, "no call to underflow expected\n");
480 ok(sb3.stored_char == 'b', "wrong stored character, expected 'b' got %c\n", sb3.stored_char);
482 /* sputc */
483 *sb.pbase = 'a';
484 ret = (int) call_func2(p_streambuf_sputc, &sb, 'c');
485 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
486 ok(overflow_count == 0, "no call to overflow expected\n");
487 ok(*sb.pbase == 'c', "expected 'c' in the put area, got %c\n", *sb.pbase);
488 ok(sb.pptr == sb.pbase + 1, "wrong put pointer, expected %p got %p\n", sb.pbase + 1, sb.pptr);
489 test_this = &sb2;
490 ret = (int) call_func2(p_streambuf_sputc, &sb2, 'c');
491 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
492 ok(overflow_count == 1, "expected call to overflow\n");
493 ok(sb2.pptr == sb2.pbase + 5, "wrong put pointer, expected %p got %p\n", sb2.pbase + 5, sb2.pptr);
494 test_this = &sb3;
495 ret = (int) call_func2(p_streambuf_sputc, &sb3, 'c');
496 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
497 ok(overflow_count == 2, "expected call to overflow\n");
498 sb3.pbase = sb3.pptr = sb3.base;
499 sb3.epptr = sb3.ebuf;
500 ret = (int) call_func2(p_streambuf_sputc, &sb3, 'c');
501 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
502 ok(overflow_count == 2, "no call to overflow expected\n");
503 ok(*sb3.pbase == 'c', "expected 'c' in the put area, got %c\n", *sb3.pbase);
504 sb3.pbase = sb3.pptr = sb3.epptr = NULL;
506 /* xsgetn */
507 sb2.gptr = sb2.egptr = sb2.eback + 13;
508 test_this = &sb2;
509 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 5);
510 ok(ret == 5, "wrong return value, expected 5 got %d\n", ret);
511 ok(!strncmp(reserve, "Worst", 5), "expected 'Worst' got %s\n", reserve);
512 ok(sb2.gptr == sb2.eback + 5, "wrong get pointer, expected %p got %p\n", sb2.eback + 5, sb2.gptr);
513 ok(underflow_count == 4, "expected call to underflow\n");
514 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 4);
515 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
516 ok(!strncmp(reserve, "Test", 4), "expected 'Test' got %s\n", reserve);
517 ok(sb2.gptr == sb2.eback + 9, "wrong get pointer, expected %p got %p\n", sb2.eback + 9, sb2.gptr);
518 ok(underflow_count == 5, "expected call to underflow\n");
519 get_end = 1;
520 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 16);
521 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
522 ok(!strncmp(reserve, "Ever", 4), "expected 'Ever' got %s\n", reserve);
523 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
524 ok(underflow_count == 7, "expected 2 calls to underflow, got %d\n", underflow_count - 5);
525 test_this = &sb3;
526 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 11);
527 ok(ret == 11, "wrong return value, expected 11 got %d\n", ret);
528 ok(!strncmp(reserve, "bompuGlobal", 11), "expected 'bompuGlobal' got %s\n", reserve);
529 ok(sb3.stored_char == 'H', "wrong stored character, expected 'H' got %c\n", sb3.stored_char);
530 ok(underflow_count == 18, "expected 11 calls to underflow, got %d\n", underflow_count - 7);
531 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 16);
532 ok(ret == 12, "wrong return value, expected 12 got %d\n", ret);
533 ok(!strncmp(reserve, "HyperMegaNet", 12), "expected 'HyperMegaNet' got %s\n", reserve);
534 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
535 ok(underflow_count == 30, "expected 12 calls to underflow, got %d\n", underflow_count - 18);
536 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 3);
537 ok(ret == 0, "wrong return value, expected 0 got %d\n", ret);
538 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
539 ok(underflow_count == 31, "expected call to underflow\n");
540 buffer_pos = 0;
541 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 5);
542 ok(ret == 5, "wrong return value, expected 5 got %d\n", ret);
543 ok(!strncmp(reserve, "Compu", 5), "expected 'Compu' got %s\n", reserve);
544 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
545 ok(underflow_count == 37, "expected 6 calls to underflow, got %d\n", underflow_count - 31);
547 /* xsputn */
548 ret = (int) call_func3(p_streambuf_xsputn, &sb, "Test\0ing", 8);
549 ok(ret == 8, "wrong return value, expected 8 got %d\n", ret);
550 ok(sb.pptr == sb.pbase + 9, "wrong put pointer, expected %p got %p\n", sb.pbase + 9, sb.pptr);
551 test_this = &sb2;
552 sb2.pptr = sb2.epptr - 7;
553 ret = (int) call_func3(p_streambuf_xsputn, &sb2, "Testing", 7);
554 ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
555 ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
556 ok(overflow_count == 2, "no call to overflow expected\n");
557 sb2.pptr = sb2.epptr - 5;
558 sb2.pbase[5] = 'a';
559 ret = (int) call_func3(p_streambuf_xsputn, &sb2, "Testing", 7);
560 ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
561 ok(sb2.pbase[5] == 'g', "expected 'g' got %c\n", sb2.pbase[5]);
562 ok(sb2.pptr == sb2.pbase + 6, "wrong put pointer, expected %p got %p\n", sb2.pbase + 6, sb2.pptr);
563 ok(overflow_count == 3, "expected call to overflow\n");
564 sb2.pptr = sb2.epptr - 4;
565 ret = (int) call_func3(p_streambuf_xsputn, &sb2, "TestLing", 8);
566 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
567 ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
568 ok(overflow_count == 4, "expected call to overflow\n");
569 test_this = &sb3;
570 ret = (int) call_func3(p_streambuf_xsputn, &sb3, "Testing", 7);
571 ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
572 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
573 ok(overflow_count == 11, "expected 7 calls to overflow, got %d\n", overflow_count - 4);
574 ret = (int) call_func3(p_streambuf_xsputn, &sb3, "TeLephone", 9);
575 ok(ret == 2, "wrong return value, expected 2 got %d\n", ret);
576 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
577 ok(overflow_count == 14, "expected 3 calls to overflow, got %d\n", overflow_count - 11);
579 /* snextc */
580 strcpy(sb.eback, "Test");
581 ret = (int) call_func1(p_streambuf_snextc, &sb);
582 ok(ret == 'e', "expected 'e' got '%c'\n", ret);
583 ok(sb.gptr == sb.eback + 1, "wrong get pointer, expected %p got %p\n", sb.eback + 1, sb.gptr);
584 test_this = &sb2;
585 ret = (int) call_func1(p_streambuf_snextc, &sb2);
586 ok(ret == EOF, "expected EOF got '%c'\n", ret);
587 ok(sb2.gptr == sb2.egptr + 1, "wrong get pointer, expected %p got %p\n", sb2.egptr + 1, sb2.gptr);
588 ok(underflow_count == 39, "expected 2 calls to underflow, got %d\n", underflow_count - 37);
589 sb2.gptr = sb2.egptr - 1;
590 ret = (int) call_func1(p_streambuf_snextc, &sb2);
591 ok(ret == EOF, "expected EOF got '%c'\n", ret);
592 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
593 ok(underflow_count == 40, "expected call to underflow\n");
594 get_end = 0;
595 ret = (int) call_func1(p_streambuf_snextc, &sb2);
596 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
597 ok(sb2.gptr == sb2.eback + 1, "wrong get pointer, expected %p got %p\n", sb2.eback + 1, sb2.gptr);
598 ok(underflow_count == 41, "expected call to underflow\n");
599 sb2.gptr = sb2.egptr - 1;
600 ret = (int) call_func1(p_streambuf_snextc, &sb2);
601 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
602 ok(sb2.gptr == sb2.eback, "wrong get pointer, expected %p got %p\n", sb2.eback, sb2.gptr);
603 ok(underflow_count == 42, "expected call to underflow\n");
604 sb2.gptr = sb2.egptr;
605 test_this = &sb3;
606 ret = (int) call_func1(p_streambuf_snextc, &sb3);
607 ok(ret == 'l', "expected 'l' got '%c'\n", ret);
608 ok(sb3.stored_char == 'l', "wrong stored character, expected 'l' got %c\n", sb3.stored_char);
609 ok(underflow_count == 43, "expected call to underflow\n");
610 buffer_pos = 22;
611 ret = (int) call_func1(p_streambuf_snextc, &sb3);
612 ok(ret == 't', "expected 't' got '%c'\n", ret);
613 ok(sb3.stored_char == 't', "wrong stored character, expected 't' got %c\n", sb3.stored_char);
614 ok(underflow_count == 44, "expected call to underflow\n");
615 ret = (int) call_func1(p_streambuf_snextc, &sb3);
616 ok(ret == EOF, "expected EOF got '%c'\n", ret);
617 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
618 ok(underflow_count == 45, "expected call to underflow\n");
619 buffer_pos = 0;
620 ret = (int) call_func1(p_streambuf_snextc, &sb3);
621 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
622 ok(sb3.stored_char == 'o', "wrong stored character, expected 'o' got %c\n", sb3.stored_char);
623 ok(underflow_count == 47, "expected 2 calls to underflow, got %d\n", underflow_count - 45);
624 sb3.stored_char = EOF;
625 ret = (int) call_func1(p_streambuf_snextc, &sb3);
626 ok(ret == 'p', "expected 'p' got '%c'\n", ret);
627 ok(sb3.stored_char == 'p', "wrong stored character, expected 'p' got %c\n", sb3.stored_char);
628 ok(underflow_count == 49, "expected 2 calls to underflow, got %d\n", underflow_count - 47);
630 /* sbumpc */
631 ret = (int) call_func1(p_streambuf_sbumpc, &sb);
632 ok(ret == 'e', "expected 'e' got '%c'\n", ret);
633 ok(sb.gptr == sb.eback + 2, "wrong get pointer, expected %p got %p\n", sb.eback + 2, sb.gptr);
634 test_this = &sb2;
635 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
636 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
637 ok(sb2.gptr == sb2.eback + 1, "wrong get pointer, expected %p got %p\n", sb2.eback + 1, sb2.gptr);
638 ok(underflow_count == 50, "expected call to underflow\n");
639 sb2.gptr = sb2.egptr - 1;
640 *sb2.gptr = 't';
641 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
642 ok(ret == 't', "expected 't' got '%c'\n", ret);
643 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
644 ok(underflow_count == 50, "no call to underflow expected\n");
645 get_end = 1;
646 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
647 ok(ret == EOF, "expected EOF got '%c'\n", ret);
648 ok(sb2.gptr == sb2.egptr + 1, "wrong get pointer, expected %p got %p\n", sb2.egptr + 1, sb2.gptr);
649 ok(underflow_count == 51, "expected call to underflow\n");
650 sb2.gptr = sb2.egptr;
651 test_this = &sb3;
652 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
653 ok(ret == 'p', "expected 'p' got '%c'\n", ret);
654 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
655 ok(underflow_count == 51, "no call to underflow expected\n");
656 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
657 ok(ret == 'u', "expected 'u' got '%c'\n", ret);
658 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
659 ok(underflow_count == 52, "expected call to underflow\n");
660 buffer_pos = 23;
661 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
662 ok(ret == EOF, "expected EOF got '%c'\n", ret);
663 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
664 ok(underflow_count == 53, "expected call to underflow\n");
665 buffer_pos = 0;
666 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
667 ok(ret == 'C', "expected 'C' got '%c'\n", ret);
668 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
669 ok(underflow_count == 54, "expected call to underflow\n");
671 /* stossc */
672 call_func1(p_streambuf_stossc, &sb);
673 ok(sb.gptr == sb.eback + 3, "wrong get pointer, expected %p got %p\n", sb.eback + 3, sb.gptr);
674 test_this = &sb2;
675 call_func1(p_streambuf_stossc, &sb2);
676 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
677 ok(underflow_count == 55, "expected call to underflow\n");
678 get_end = 0;
679 call_func1(p_streambuf_stossc, &sb2);
680 ok(sb2.gptr == sb2.eback + 1, "wrong get pointer, expected %p got %p\n", sb2.eback + 1, sb2.gptr);
681 ok(underflow_count == 56, "expected call to underflow\n");
682 sb2.gptr = sb2.egptr - 1;
683 call_func1(p_streambuf_stossc, &sb2);
684 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
685 ok(underflow_count == 56, "no call to underflow expected\n");
686 test_this = &sb3;
687 call_func1(p_streambuf_stossc, &sb3);
688 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
689 ok(underflow_count == 57, "expected call to underflow\n");
690 sb3.stored_char = 'a';
691 call_func1(p_streambuf_stossc, &sb3);
692 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
693 ok(underflow_count == 57, "no call to underflow expected\n");
695 /* pbackfail */
696 ret = (int) call_func2(p_streambuf_pbackfail, &sb, 'A');
697 ok(ret == 'A', "expected 'A' got '%c'\n", ret);
698 ok(sb.gptr == sb.eback + 2, "wrong get pointer, expected %p got %p\n", sb.eback + 2, sb.gptr);
699 ok(*sb.gptr == 'A', "expected 'A' in the get area, got %c\n", *sb.gptr);
700 ret = (int) call_func2(p_streambuf_pbackfail, &sb, EOF);
701 ok(ret == EOF, "expected EOF got '%c'\n", ret);
702 ok(sb.gptr == sb.eback + 1, "wrong get pointer, expected %p got %p\n", sb.eback + 1, sb.gptr);
703 ok(*sb.gptr == EOF, "expected EOF in the get area, got %c\n", *sb.gptr);
704 sb.gptr = sb.eback;
705 ret = (int) call_func2(p_streambuf_pbackfail, &sb, 'Z');
706 ok(ret == EOF, "expected EOF got '%c'\n", ret);
707 ok(sb.gptr == sb.eback, "wrong get pointer, expected %p got %p\n", sb.eback, sb.gptr);
708 ok(*sb.gptr == 'T', "expected 'T' in the get area, got %c\n", *sb.gptr);
709 ret = (int) call_func2(p_streambuf_pbackfail, &sb, EOF);
710 ok(ret == EOF, "expected EOF got '%c'\n", ret);
711 ok(sb.gptr == sb.eback, "wrong get pointer, expected %p got %p\n", sb.eback, sb.gptr);
712 ok(*sb.gptr == 'T', "expected 'T' in the get area, got %c\n", *sb.gptr);
713 sb2.gptr = sb2.egptr + 1;
714 ret = (int) call_func2(p_streambuf_pbackfail, &sb2, 'X');
715 ok(ret == 'X', "expected 'X' got '%c'\n", ret);
716 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
717 ok(*sb2.gptr == 'X', "expected 'X' in the get area, got %c\n", *sb2.gptr);
719 SetEvent(lock_arg.test[3]);
720 WaitForSingleObject(thread, INFINITE);
722 call_func1(p_streambuf_dtor, &sb);
723 call_func1(p_streambuf_dtor, &sb2);
724 call_func1(p_streambuf_dtor, &sb3);
725 for (i = 0; i < 4; i++) {
726 CloseHandle(lock_arg.lock[i]);
727 CloseHandle(lock_arg.test[i]);
729 CloseHandle(thread);
732 START_TEST(msvcirt)
734 if(!init())
735 return;
737 test_streambuf();
739 FreeLibrary(msvcirt);