msvcirt: Add implementation of streambuf::sbumpc.
[wine.git] / dlls / msvcirt / tests / msvcirt.c
blob8ebf045363a20e8c306c64ddee8ce3f1f5e24408
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 void (*__thiscall p_streambuf_pbump)(streambuf*, int);
61 static int (*__thiscall p_streambuf_sbumpc)(streambuf*);
62 static void (*__thiscall p_streambuf_setb)(streambuf*, char*, char*, int);
63 static void (*__thiscall p_streambuf_setlock)(streambuf*);
64 static streambuf* (*__thiscall p_streambuf_setbuf)(streambuf*, char*, int);
65 static int (*__thiscall p_streambuf_sgetc)(streambuf*);
66 static int (*__thiscall p_streambuf_snextc)(streambuf*);
67 static int (*__thiscall p_streambuf_sputc)(streambuf*, int);
68 static int (*__thiscall p_streambuf_sync)(streambuf*);
69 static void (*__thiscall p_streambuf_unlock)(streambuf*);
70 static int (*__thiscall p_streambuf_xsgetn)(streambuf*, char*, int);
71 static int (*__thiscall p_streambuf_xsputn)(streambuf*, const char*, int);
73 /* Emulate a __thiscall */
74 #ifdef __i386__
76 #include "pshpack1.h"
77 struct thiscall_thunk
79 BYTE pop_eax; /* popl %eax (ret addr) */
80 BYTE pop_edx; /* popl %edx (func) */
81 BYTE pop_ecx; /* popl %ecx (this) */
82 BYTE push_eax; /* pushl %eax */
83 WORD jmp_edx; /* jmp *%edx */
85 #include "poppack.h"
87 static void * (WINAPI *call_thiscall_func1)( void *func, void *this );
88 static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a );
89 static void * (WINAPI *call_thiscall_func3)( void *func, void *this, const void *a, const void *b );
90 static void * (WINAPI *call_thiscall_func4)( void *func, void *this, const void *a, const void *b,
91 const void *c );
92 static void * (WINAPI *call_thiscall_func5)( void *func, void *this, const void *a, const void *b,
93 const void *c, const void *d );
95 static void init_thiscall_thunk(void)
97 struct thiscall_thunk *thunk = VirtualAlloc( NULL, sizeof(*thunk),
98 MEM_COMMIT, PAGE_EXECUTE_READWRITE );
99 thunk->pop_eax = 0x58; /* popl %eax */
100 thunk->pop_edx = 0x5a; /* popl %edx */
101 thunk->pop_ecx = 0x59; /* popl %ecx */
102 thunk->push_eax = 0x50; /* pushl %eax */
103 thunk->jmp_edx = 0xe2ff; /* jmp *%edx */
104 call_thiscall_func1 = (void *)thunk;
105 call_thiscall_func2 = (void *)thunk;
106 call_thiscall_func3 = (void *)thunk;
107 call_thiscall_func4 = (void *)thunk;
108 call_thiscall_func5 = (void *)thunk;
111 #define call_func1(func,_this) call_thiscall_func1(func,_this)
112 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
113 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
114 #define call_func4(func,_this,a,b,c) call_thiscall_func4(func,_this,(const void*)(a),(const void*)(b), \
115 (const void*)(c))
116 #define call_func5(func,_this,a,b,c,d) call_thiscall_func5(func,_this,(const void*)(a),(const void*)(b), \
117 (const void*)(c), (const void *)(d))
119 #else
121 #define init_thiscall_thunk()
122 #define call_func1(func,_this) func(_this)
123 #define call_func2(func,_this,a) func(_this,a)
124 #define call_func3(func,_this,a,b) func(_this,a,b)
125 #define call_func4(func,_this,a,b,c) func(_this,a,b,c)
126 #define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d)
128 #endif /* __i386__ */
130 static HMODULE msvcirt;
131 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcirt,y)
132 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
133 static BOOL init(void)
135 msvcirt = LoadLibraryA("msvcirt.dll");
136 if(!msvcirt) {
137 win_skip("msvcirt.dll not installed\n");
138 return FALSE;
141 if(sizeof(void*) == 8) { /* 64-bit initialization */
142 SET(p_streambuf_reserve_ctor, "??0streambuf@@IEAA@PEADH@Z");
143 SET(p_streambuf_ctor, "??0streambuf@@IEAA@XZ");
144 SET(p_streambuf_dtor, "??1streambuf@@UEAA@XZ");
145 SET(p_streambuf_allocate, "?allocate@streambuf@@IEAAHXZ");
146 SET(p_streambuf_clrclock, "?clrlock@streambuf@@QEAAXXZ");
147 SET(p_streambuf_doallocate, "?doallocate@streambuf@@MEAAHXZ");
148 SET(p_streambuf_gbump, "?gbump@streambuf@@IEAAXH@Z");
149 SET(p_streambuf_lock, "?lock@streambuf@@QEAAXXZ");
150 SET(p_streambuf_pbump, "?pbump@streambuf@@IEAAXH@Z");
151 SET(p_streambuf_sbumpc, "?sbumpc@streambuf@@QEAAHXZ");
152 SET(p_streambuf_setb, "?setb@streambuf@@IEAAXPEAD0H@Z");
153 SET(p_streambuf_setbuf, "?setbuf@streambuf@@UEAAPEAV1@PEADH@Z");
154 SET(p_streambuf_setlock, "?setlock@streambuf@@QEAAXXZ");
155 SET(p_streambuf_sgetc, "?sgetc@streambuf@@QEAAHXZ");
156 SET(p_streambuf_snextc, "?snextc@streambuf@@QEAAHXZ");
157 SET(p_streambuf_sputc, "?sputc@streambuf@@QEAAHH@Z");
158 SET(p_streambuf_sync, "?sync@streambuf@@UEAAHXZ");
159 SET(p_streambuf_unlock, "?unlock@streambuf@@QEAAXXZ");
160 SET(p_streambuf_xsgetn, "?xsgetn@streambuf@@UEAAHPEADH@Z");
161 SET(p_streambuf_xsputn, "?xsputn@streambuf@@UEAAHPEBDH@Z");
162 } else {
163 SET(p_streambuf_reserve_ctor, "??0streambuf@@IAE@PADH@Z");
164 SET(p_streambuf_ctor, "??0streambuf@@IAE@XZ");
165 SET(p_streambuf_dtor, "??1streambuf@@UAE@XZ");
166 SET(p_streambuf_allocate, "?allocate@streambuf@@IAEHXZ");
167 SET(p_streambuf_clrclock, "?clrlock@streambuf@@QAEXXZ");
168 SET(p_streambuf_doallocate, "?doallocate@streambuf@@MAEHXZ");
169 SET(p_streambuf_gbump, "?gbump@streambuf@@IAEXH@Z");
170 SET(p_streambuf_lock, "?lock@streambuf@@QAEXXZ");
171 SET(p_streambuf_pbump, "?pbump@streambuf@@IAEXH@Z");
172 SET(p_streambuf_sbumpc, "?sbumpc@streambuf@@QAEHXZ");
173 SET(p_streambuf_setb, "?setb@streambuf@@IAEXPAD0H@Z");
174 SET(p_streambuf_setbuf, "?setbuf@streambuf@@UAEPAV1@PADH@Z");
175 SET(p_streambuf_setlock, "?setlock@streambuf@@QAEXXZ");
176 SET(p_streambuf_sgetc, "?sgetc@streambuf@@QAEHXZ");
177 SET(p_streambuf_snextc, "?snextc@streambuf@@QAEHXZ");
178 SET(p_streambuf_sputc, "?sputc@streambuf@@QAEHH@Z");
179 SET(p_streambuf_sync, "?sync@streambuf@@UAEHXZ");
180 SET(p_streambuf_unlock, "?unlock@streambuf@@QAEXXZ");
181 SET(p_streambuf_xsgetn, "?xsgetn@streambuf@@UAEHPADH@Z");
182 SET(p_streambuf_xsputn, "?xsputn@streambuf@@UAEHPBDH@Z");
185 init_thiscall_thunk();
186 return TRUE;
189 static int overflow_count, underflow_count;
190 static streambuf *test_this;
191 static char test_get_buffer[24];
192 static int buffer_pos, get_end;
194 #ifdef __i386__
195 static int __thiscall test_streambuf_overflow(int ch)
196 #else
197 static int __thiscall test_streambuf_overflow(streambuf *this, int ch)
198 #endif
200 overflow_count++;
201 if (ch == 'L') /* simulate a failure */
202 return EOF;
203 if (!test_this->unbuffered)
204 test_this->pptr = test_this->pbase + 5;
205 return ch;
208 #ifdef __i386__
209 static int __thiscall test_streambuf_underflow(void)
210 #else
211 static int __thiscall test_streambuf_underflow(streambuf *this)
212 #endif
214 underflow_count++;
215 if (test_this->unbuffered) {
216 return (buffer_pos < 23) ? test_get_buffer[buffer_pos++] : EOF;
217 } else if (test_this->gptr < test_this->egptr) {
218 return *test_this->gptr;
219 } else {
220 return get_end ? EOF : *(test_this->gptr = test_this->eback);
224 struct streambuf_lock_arg
226 streambuf *sb;
227 HANDLE lock[4];
228 HANDLE test[4];
231 static DWORD WINAPI lock_streambuf(void *arg)
233 struct streambuf_lock_arg *lock_arg = arg;
234 call_func1(p_streambuf_lock, lock_arg->sb);
235 SetEvent(lock_arg->lock[0]);
236 WaitForSingleObject(lock_arg->test[0], INFINITE);
237 call_func1(p_streambuf_lock, lock_arg->sb);
238 SetEvent(lock_arg->lock[1]);
239 WaitForSingleObject(lock_arg->test[1], INFINITE);
240 call_func1(p_streambuf_lock, lock_arg->sb);
241 SetEvent(lock_arg->lock[2]);
242 WaitForSingleObject(lock_arg->test[2], INFINITE);
243 call_func1(p_streambuf_unlock, lock_arg->sb);
244 SetEvent(lock_arg->lock[3]);
245 WaitForSingleObject(lock_arg->test[3], INFINITE);
246 call_func1(p_streambuf_unlock, lock_arg->sb);
247 return 0;
250 static void test_streambuf(void)
252 streambuf sb, sb2, sb3, *psb;
253 vtable_ptr test_streambuf_vtbl[11];
254 struct streambuf_lock_arg lock_arg;
255 HANDLE thread;
256 char reserve[16];
257 int ret, i;
258 BOOL locked;
260 memset(&sb, 0xab, sizeof(streambuf));
261 memset(&sb2, 0xab, sizeof(streambuf));
262 memset(&sb3, 0xab, sizeof(streambuf));
264 /* constructors */
265 call_func1(p_streambuf_ctor, &sb);
266 ok(sb.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb.allocated);
267 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
268 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
269 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
270 ok(sb.lock.LockCount == -1, "wrong critical section state, expected -1 got %d\n", sb.lock.LockCount);
271 call_func3(p_streambuf_reserve_ctor, &sb2, reserve, 16);
272 ok(sb2.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb2.allocated);
273 ok(sb2.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb2.unbuffered);
274 ok(sb2.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb2.base);
275 ok(sb2.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb2.ebuf);
276 ok(sb.lock.LockCount == -1, "wrong critical section state, expected -1 got %d\n", sb.lock.LockCount);
277 call_func1(p_streambuf_ctor, &sb3);
278 ok(sb3.allocated == 0, "wrong allocate value, expected 0 got %d\n", sb3.allocated);
279 ok(sb3.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb3.unbuffered);
280 ok(sb3.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb3.base);
281 ok(sb3.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb3.ebuf);
283 memcpy(test_streambuf_vtbl, sb.vtable, sizeof(test_streambuf_vtbl));
284 test_streambuf_vtbl[7] = (vtable_ptr)&test_streambuf_overflow;
285 test_streambuf_vtbl[8] = (vtable_ptr)&test_streambuf_underflow;
286 sb2.vtable = test_streambuf_vtbl;
287 sb3.vtable = test_streambuf_vtbl;
288 overflow_count = underflow_count = 0;
289 strcpy(test_get_buffer, "CompuGlobalHyperMegaNet");
290 buffer_pos = get_end = 0;
292 /* setlock */
293 ok(sb.do_lock == -1, "expected do_lock value -1, got %d\n", sb.do_lock);
294 call_func1(p_streambuf_setlock, &sb);
295 ok(sb.do_lock == -2, "expected do_lock value -2, got %d\n", sb.do_lock);
296 call_func1(p_streambuf_setlock, &sb);
297 ok(sb.do_lock == -3, "expected do_lock value -3, got %d\n", sb.do_lock);
298 sb.do_lock = 3;
299 call_func1(p_streambuf_setlock, &sb);
300 ok(sb.do_lock == 2, "expected do_lock value 2, got %d\n", sb.do_lock);
302 /* clrlock */
303 sb.do_lock = -2;
304 call_func1(p_streambuf_clrclock, &sb);
305 ok(sb.do_lock == -1, "expected do_lock value -1, got %d\n", sb.do_lock);
306 call_func1(p_streambuf_clrclock, &sb);
307 ok(sb.do_lock == 0, "expected do_lock value 0, got %d\n", sb.do_lock);
308 call_func1(p_streambuf_clrclock, &sb);
309 ok(sb.do_lock == 1, "expected do_lock value 1, got %d\n", sb.do_lock);
310 call_func1(p_streambuf_clrclock, &sb);
311 ok(sb.do_lock == 1, "expected do_lock value 1, got %d\n", sb.do_lock);
313 /* lock/unlock */
314 lock_arg.sb = &sb;
315 for (i = 0; i < 4; i++) {
316 lock_arg.lock[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
317 ok(lock_arg.lock[i] != NULL, "CreateEventW failed\n");
318 lock_arg.test[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
319 ok(lock_arg.test[i] != NULL, "CreateEventW failed\n");
322 sb.do_lock = 0;
323 thread = CreateThread(NULL, 0, lock_streambuf, (void*)&lock_arg, 0, NULL);
324 ok(thread != NULL, "CreateThread failed\n");
325 WaitForSingleObject(lock_arg.lock[0], INFINITE);
326 locked = TryEnterCriticalSection(&sb.lock);
327 ok(locked != 0, "could not lock the streambuf\n");
328 LeaveCriticalSection(&sb.lock);
330 sb.do_lock = 1;
331 SetEvent(lock_arg.test[0]);
332 WaitForSingleObject(lock_arg.lock[1], INFINITE);
333 locked = TryEnterCriticalSection(&sb.lock);
334 ok(locked != 0, "could not lock the streambuf\n");
335 LeaveCriticalSection(&sb.lock);
337 sb.do_lock = -1;
338 SetEvent(lock_arg.test[1]);
339 WaitForSingleObject(lock_arg.lock[2], INFINITE);
340 locked = TryEnterCriticalSection(&sb.lock);
341 ok(locked == 0, "the streambuf was not locked before\n");
343 sb.do_lock = 0;
344 SetEvent(lock_arg.test[2]);
345 WaitForSingleObject(lock_arg.lock[3], INFINITE);
346 locked = TryEnterCriticalSection(&sb.lock);
347 ok(locked == 0, "the streambuf was not locked before\n");
348 sb.do_lock = -1;
350 /* setb */
351 call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 0);
352 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
353 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
354 call_func4(p_streambuf_setb, &sb, reserve, reserve+16, 4);
355 ok(sb.allocated == 4, "wrong allocate value, expected 4 got %d\n", sb.allocated);
356 sb.allocated = 0;
357 call_func4(p_streambuf_setb, &sb, NULL, NULL, 3);
358 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
360 /* setbuf */
361 psb = call_func3(p_streambuf_setbuf, &sb, NULL, 5);
362 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
363 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
364 ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered);
365 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
366 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
367 psb = call_func3(p_streambuf_setbuf, &sb, reserve, 0);
368 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
369 ok(sb.unbuffered == 1, "wrong unbuffered value, expected 1 got %d\n", sb.unbuffered);
370 ok(sb.base == NULL, "wrong base pointer, expected %p got %p\n", NULL, sb.base);
371 ok(sb.ebuf == NULL, "wrong ebuf pointer, expected %p got %p\n", NULL, sb.ebuf);
372 psb = call_func3(p_streambuf_setbuf, &sb, reserve, 16);
373 ok(psb == &sb, "wrong return value, expected %p got %p\n", &sb, psb);
374 ok(sb.allocated == 3, "wrong allocate value, expected 3 got %d\n", sb.allocated);
375 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
376 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
377 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
378 psb = call_func3(p_streambuf_setbuf, &sb, NULL, 8);
379 ok(psb == NULL, "wrong return value, expected %p got %p\n", NULL, psb);
380 ok(sb.unbuffered == 0, "wrong unbuffered value, expected 0 got %d\n", sb.unbuffered);
381 ok(sb.base == reserve, "wrong base pointer, expected %p got %p\n", reserve, sb.base);
382 ok(sb.ebuf == reserve+16, "wrong ebuf pointer, expected %p got %p\n", reserve+16, sb.ebuf);
384 /* allocate */
385 ret = (int) call_func1(p_streambuf_allocate, &sb);
386 ok(ret == 0, "wrong return value, expected 0 got %d\n", ret);
387 sb.base = NULL;
388 ret = (int) call_func1(p_streambuf_allocate, &sb);
389 ok(ret == 1, "wrong return value, expected 1 got %d\n", ret);
390 ok(sb.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb.allocated);
391 ok(sb.ebuf - sb.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb.ebuf, sb.base);
393 /* doallocate */
394 ret = (int) call_func1(p_streambuf_doallocate, &sb2);
395 ok(ret == 1, "doallocate failed, got %d\n", ret);
396 ok(sb2.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb2.allocated);
397 ok(sb2.ebuf - sb2.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb2.ebuf, sb2.base);
398 ret = (int) call_func1(p_streambuf_doallocate, &sb3);
399 ok(ret == 1, "doallocate failed, got %d\n", ret);
400 ok(sb3.allocated == 1, "wrong allocate value, expected 1 got %d\n", sb3.allocated);
401 ok(sb3.ebuf - sb3.base == 512 , "wrong reserve area size, expected 512 got %p-%p\n", sb3.ebuf, sb3.base);
403 /* sb: buffered, space available */
404 sb.eback = sb.gptr = sb.base;
405 sb.egptr = sb.base + 256;
406 sb.pbase = sb.pptr = sb.base + 256;
407 sb.epptr = sb.base + 512;
408 /* sb2: buffered, no space available */
409 sb2.eback = sb2.base;
410 sb2.gptr = sb2.egptr = sb2.base + 256;
411 sb2.pbase = sb2.base + 256;
412 sb2.pptr = sb2.epptr = sb2.base + 512;
413 /* sb3: unbuffered */
414 sb3.unbuffered = 1;
416 /* gbump */
417 call_func2(p_streambuf_gbump, &sb, 10);
418 ok(sb.gptr == sb.eback + 10, "advance get pointer failed, expected %p got %p\n", sb.eback + 10, sb.gptr);
419 call_func2(p_streambuf_gbump, &sb, -15);
420 ok(sb.gptr == sb.eback - 5, "advance get pointer failed, expected %p got %p\n", sb.eback - 5, sb.gptr);
421 sb.gptr = sb.eback;
423 /* pbump */
424 call_func2(p_streambuf_pbump, &sb, -2);
425 ok(sb.pptr == sb.pbase - 2, "advance put pointer failed, expected %p got %p\n", sb.pbase - 2, sb.pptr);
426 call_func2(p_streambuf_pbump, &sb, 20);
427 ok(sb.pptr == sb.pbase + 18, "advance put pointer failed, expected %p got %p\n", sb.pbase + 18, sb.pptr);
428 sb.pptr = sb.pbase;
430 /* sync */
431 ret = (int) call_func1(p_streambuf_sync, &sb);
432 ok(ret == EOF, "sync failed, expected EOF got %d\n", ret);
433 sb.gptr = sb.egptr;
434 ret = (int) call_func1(p_streambuf_sync, &sb);
435 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
436 sb.gptr = sb.egptr + 1;
437 ret = (int) call_func1(p_streambuf_sync, &sb);
438 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
439 sb.gptr = sb.eback;
440 ret = (int) call_func1(p_streambuf_sync, &sb2);
441 ok(ret == EOF, "sync failed, expected EOF got %d\n", ret);
442 sb2.pptr = sb2.pbase;
443 ret = (int) call_func1(p_streambuf_sync, &sb2);
444 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
445 sb2.pptr = sb2.pbase - 1;
446 ret = (int) call_func1(p_streambuf_sync, &sb2);
447 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
448 sb2.pptr = sb2.epptr;
449 ret = (int) call_func1(p_streambuf_sync, &sb3);
450 ok(ret == 0, "sync failed, expected 0 got %d\n", ret);
452 /* sgetc */
453 strcpy(sb2.eback, "WorstTestEver");
454 test_this = &sb2;
455 ret = (int) call_func1(p_streambuf_sgetc, &sb2);
456 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
457 ok(underflow_count == 1, "expected call to underflow\n");
458 ok(sb2.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb2.stored_char);
459 sb2.gptr++;
460 ret = (int) call_func1(p_streambuf_sgetc, &sb2);
461 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
462 ok(underflow_count == 2, "expected call to underflow\n");
463 ok(sb2.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb2.stored_char);
464 sb2.gptr = sb2.egptr;
465 test_this = &sb3;
466 ret = (int) call_func1(p_streambuf_sgetc, &sb3);
467 ok(ret == 'C', "expected 'C' got '%c'\n", ret);
468 ok(underflow_count == 3, "expected call to underflow\n");
469 ok(sb3.stored_char == 'C', "wrong stored character, expected 'C' got %c\n", sb3.stored_char);
470 sb3.stored_char = 'b';
471 ret = (int) call_func1(p_streambuf_sgetc, &sb3);
472 ok(ret == 'b', "expected 'b' got '%c'\n", ret);
473 ok(underflow_count == 3, "no call to underflow expected\n");
474 ok(sb3.stored_char == 'b', "wrong stored character, expected 'b' got %c\n", sb3.stored_char);
476 /* sputc */
477 *sb.pbase = 'a';
478 ret = (int) call_func2(p_streambuf_sputc, &sb, 'c');
479 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
480 ok(overflow_count == 0, "no call to overflow expected\n");
481 ok(*sb.pbase == 'c', "expected 'c' in the put area, got %c\n", *sb.pbase);
482 ok(sb.pptr == sb.pbase + 1, "wrong put pointer, expected %p got %p\n", sb.pbase + 1, sb.pptr);
483 test_this = &sb2;
484 ret = (int) call_func2(p_streambuf_sputc, &sb2, 'c');
485 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
486 ok(overflow_count == 1, "expected call to overflow\n");
487 ok(sb2.pptr == sb2.pbase + 5, "wrong put pointer, expected %p got %p\n", sb2.pbase + 5, sb2.pptr);
488 test_this = &sb3;
489 ret = (int) call_func2(p_streambuf_sputc, &sb3, 'c');
490 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
491 ok(overflow_count == 2, "expected call to overflow\n");
492 sb3.pbase = sb3.pptr = sb3.base;
493 sb3.epptr = sb3.ebuf;
494 ret = (int) call_func2(p_streambuf_sputc, &sb3, 'c');
495 ok(ret == 'c', "wrong return value, expected 'c' got %d\n", ret);
496 ok(overflow_count == 2, "no call to overflow expected\n");
497 ok(*sb3.pbase == 'c', "expected 'c' in the put area, got %c\n", *sb3.pbase);
498 sb3.pbase = sb3.pptr = sb3.epptr = NULL;
500 /* xsgetn */
501 sb2.gptr = sb2.egptr = sb2.eback + 13;
502 test_this = &sb2;
503 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 5);
504 ok(ret == 5, "wrong return value, expected 5 got %d\n", ret);
505 ok(!strncmp(reserve, "Worst", 5), "expected 'Worst' got %s\n", reserve);
506 ok(sb2.gptr == sb2.eback + 5, "wrong get pointer, expected %p got %p\n", sb2.eback + 5, sb2.gptr);
507 ok(underflow_count == 4, "expected call to underflow\n");
508 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 4);
509 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
510 ok(!strncmp(reserve, "Test", 4), "expected 'Test' got %s\n", reserve);
511 ok(sb2.gptr == sb2.eback + 9, "wrong get pointer, expected %p got %p\n", sb2.eback + 9, sb2.gptr);
512 ok(underflow_count == 5, "expected call to underflow\n");
513 get_end = 1;
514 ret = (int) call_func3(p_streambuf_xsgetn, &sb2, reserve, 16);
515 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
516 ok(!strncmp(reserve, "Ever", 4), "expected 'Ever' got %s\n", reserve);
517 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
518 ok(underflow_count == 7, "expected 2 calls to underflow, got %d\n", underflow_count - 5);
519 test_this = &sb3;
520 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 11);
521 ok(ret == 11, "wrong return value, expected 11 got %d\n", ret);
522 ok(!strncmp(reserve, "bompuGlobal", 11), "expected 'bompuGlobal' got %s\n", reserve);
523 ok(sb3.stored_char == 'H', "wrong stored character, expected 'H' got %c\n", sb3.stored_char);
524 ok(underflow_count == 18, "expected 11 calls to underflow, got %d\n", underflow_count - 7);
525 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 16);
526 ok(ret == 12, "wrong return value, expected 12 got %d\n", ret);
527 ok(!strncmp(reserve, "HyperMegaNet", 12), "expected 'HyperMegaNet' got %s\n", reserve);
528 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
529 ok(underflow_count == 30, "expected 12 calls to underflow, got %d\n", underflow_count - 18);
530 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 3);
531 ok(ret == 0, "wrong return value, expected 0 got %d\n", ret);
532 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
533 ok(underflow_count == 31, "expected call to underflow\n");
534 buffer_pos = 0;
535 ret = (int) call_func3(p_streambuf_xsgetn, &sb3, reserve, 5);
536 ok(ret == 5, "wrong return value, expected 5 got %d\n", ret);
537 ok(!strncmp(reserve, "Compu", 5), "expected 'Compu' got %s\n", reserve);
538 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
539 ok(underflow_count == 37, "expected 6 calls to underflow, got %d\n", underflow_count - 31);
541 /* xsputn */
542 ret = (int) call_func3(p_streambuf_xsputn, &sb, "Test\0ing", 8);
543 ok(ret == 8, "wrong return value, expected 8 got %d\n", ret);
544 ok(sb.pptr == sb.pbase + 9, "wrong put pointer, expected %p got %p\n", sb.pbase + 9, sb.pptr);
545 test_this = &sb2;
546 sb2.pptr = sb2.epptr - 7;
547 ret = (int) call_func3(p_streambuf_xsputn, &sb2, "Testing", 7);
548 ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
549 ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
550 ok(overflow_count == 2, "no call to overflow expected\n");
551 sb2.pptr = sb2.epptr - 5;
552 sb2.pbase[5] = 'a';
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.pbase[5] == 'g', "expected 'g' got %c\n", sb2.pbase[5]);
556 ok(sb2.pptr == sb2.pbase + 6, "wrong put pointer, expected %p got %p\n", sb2.pbase + 6, sb2.pptr);
557 ok(overflow_count == 3, "expected call to overflow\n");
558 sb2.pptr = sb2.epptr - 4;
559 ret = (int) call_func3(p_streambuf_xsputn, &sb2, "TestLing", 8);
560 ok(ret == 4, "wrong return value, expected 4 got %d\n", ret);
561 ok(sb2.pptr == sb2.epptr, "wrong put pointer, expected %p got %p\n", sb2.epptr, sb2.pptr);
562 ok(overflow_count == 4, "expected call to overflow\n");
563 test_this = &sb3;
564 ret = (int) call_func3(p_streambuf_xsputn, &sb3, "Testing", 7);
565 ok(ret == 7, "wrong return value, expected 7 got %d\n", ret);
566 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
567 ok(overflow_count == 11, "expected 7 calls to overflow, got %d\n", overflow_count - 4);
568 ret = (int) call_func3(p_streambuf_xsputn, &sb3, "TeLephone", 9);
569 ok(ret == 2, "wrong return value, expected 2 got %d\n", ret);
570 ok(sb3.stored_char == 'G', "wrong stored character, expected 'G' got %c\n", sb3.stored_char);
571 ok(overflow_count == 14, "expected 3 calls to overflow, got %d\n", overflow_count - 11);
573 /* snextc */
574 strcpy(sb.eback, "Test");
575 ret = (int) call_func1(p_streambuf_snextc, &sb);
576 ok(ret == 'e', "expected 'e' got '%c'\n", ret);
577 ok(sb.gptr == sb.eback + 1, "wrong get pointer, expected %p got %p\n", sb.eback + 1, sb.gptr);
578 test_this = &sb2;
579 ret = (int) call_func1(p_streambuf_snextc, &sb2);
580 ok(ret == EOF, "expected EOF got '%c'\n", ret);
581 ok(sb2.gptr == sb2.egptr + 1, "wrong get pointer, expected %p got %p\n", sb2.egptr + 1, sb2.gptr);
582 ok(underflow_count == 39, "expected 2 calls to underflow, got %d\n", underflow_count - 37);
583 sb2.gptr = sb2.egptr - 1;
584 ret = (int) call_func1(p_streambuf_snextc, &sb2);
585 ok(ret == EOF, "expected EOF got '%c'\n", ret);
586 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
587 ok(underflow_count == 40, "expected call to underflow\n");
588 get_end = 0;
589 ret = (int) call_func1(p_streambuf_snextc, &sb2);
590 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
591 ok(sb2.gptr == sb2.eback + 1, "wrong get pointer, expected %p got %p\n", sb2.eback + 1, sb2.gptr);
592 ok(underflow_count == 41, "expected call to underflow\n");
593 sb2.gptr = sb2.egptr - 1;
594 ret = (int) call_func1(p_streambuf_snextc, &sb2);
595 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
596 ok(sb2.gptr == sb2.eback, "wrong get pointer, expected %p got %p\n", sb2.eback, sb2.gptr);
597 ok(underflow_count == 42, "expected call to underflow\n");
598 sb2.gptr = sb2.egptr;
599 test_this = &sb3;
600 ret = (int) call_func1(p_streambuf_snextc, &sb3);
601 ok(ret == 'l', "expected 'l' got '%c'\n", ret);
602 ok(sb3.stored_char == 'l', "wrong stored character, expected 'l' got %c\n", sb3.stored_char);
603 ok(underflow_count == 43, "expected call to underflow\n");
604 buffer_pos = 22;
605 ret = (int) call_func1(p_streambuf_snextc, &sb3);
606 ok(ret == 't', "expected 't' got '%c'\n", ret);
607 ok(sb3.stored_char == 't', "wrong stored character, expected 't' got %c\n", sb3.stored_char);
608 ok(underflow_count == 44, "expected call to underflow\n");
609 ret = (int) call_func1(p_streambuf_snextc, &sb3);
610 ok(ret == EOF, "expected EOF got '%c'\n", ret);
611 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
612 ok(underflow_count == 45, "expected call to underflow\n");
613 buffer_pos = 0;
614 ret = (int) call_func1(p_streambuf_snextc, &sb3);
615 ok(ret == 'o', "expected 'o' got '%c'\n", ret);
616 ok(sb3.stored_char == 'o', "wrong stored character, expected 'o' got %c\n", sb3.stored_char);
617 ok(underflow_count == 47, "expected 2 calls to underflow, got %d\n", underflow_count - 45);
618 sb3.stored_char = EOF;
619 ret = (int) call_func1(p_streambuf_snextc, &sb3);
620 ok(ret == 'p', "expected 'p' got '%c'\n", ret);
621 ok(sb3.stored_char == 'p', "wrong stored character, expected 'p' got %c\n", sb3.stored_char);
622 ok(underflow_count == 49, "expected 2 calls to underflow, got %d\n", underflow_count - 47);
624 /* sbumpc */
625 ret = (int) call_func1(p_streambuf_sbumpc, &sb);
626 ok(ret == 'e', "expected 'e' got '%c'\n", ret);
627 ok(sb.gptr == sb.eback + 2, "wrong get pointer, expected %p got %p\n", sb.eback + 2, sb.gptr);
628 test_this = &sb2;
629 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
630 ok(ret == 'W', "expected 'W' got '%c'\n", ret);
631 ok(sb2.gptr == sb2.eback + 1, "wrong get pointer, expected %p got %p\n", sb2.eback + 1, sb2.gptr);
632 ok(underflow_count == 50, "expected call to underflow\n");
633 sb2.gptr = sb2.egptr - 1;
634 *sb2.gptr = 't';
635 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
636 ok(ret == 't', "expected 't' got '%c'\n", ret);
637 ok(sb2.gptr == sb2.egptr, "wrong get pointer, expected %p got %p\n", sb2.egptr, sb2.gptr);
638 ok(underflow_count == 50, "no call to underflow expected\n");
639 get_end = 1;
640 ret = (int) call_func1(p_streambuf_sbumpc, &sb2);
641 ok(ret == EOF, "expected EOF got '%c'\n", ret);
642 ok(sb2.gptr == sb2.egptr + 1, "wrong get pointer, expected %p got %p\n", sb2.egptr + 1, sb2.gptr);
643 ok(underflow_count == 51, "expected call to underflow\n");
644 sb2.gptr = sb2.egptr;
645 test_this = &sb3;
646 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
647 ok(ret == 'p', "expected 'p' got '%c'\n", ret);
648 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
649 ok(underflow_count == 51, "no call to underflow expected\n");
650 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
651 ok(ret == 'u', "expected 'u' got '%c'\n", ret);
652 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
653 ok(underflow_count == 52, "expected call to underflow\n");
654 buffer_pos = 23;
655 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
656 ok(ret == EOF, "expected EOF got '%c'\n", ret);
657 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
658 ok(underflow_count == 53, "expected call to underflow\n");
659 buffer_pos = 0;
660 ret = (int) call_func1(p_streambuf_sbumpc, &sb3);
661 ok(ret == 'C', "expected 'C' got '%c'\n", ret);
662 ok(sb3.stored_char == EOF, "wrong stored character, expected EOF got %c\n", sb3.stored_char);
663 ok(underflow_count == 54, "expected call to underflow\n");
665 SetEvent(lock_arg.test[3]);
666 WaitForSingleObject(thread, INFINITE);
668 call_func1(p_streambuf_dtor, &sb);
669 call_func1(p_streambuf_dtor, &sb2);
670 call_func1(p_streambuf_dtor, &sb3);
671 for (i = 0; i < 4; i++) {
672 CloseHandle(lock_arg.lock[i]);
673 CloseHandle(lock_arg.test[i]);
675 CloseHandle(thread);
678 START_TEST(msvcirt)
680 if(!init())
681 return;
683 test_streambuf();
685 FreeLibrary(msvcirt);