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