1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This file is part of Valgrind, a dynamic binary instrumentation
3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  framework.
4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Copyright (C) 2008-2008 Google Inc
6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     opensource@google.com
7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is free software; you can redistribute it and/or
9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  modify it under the terms of the GNU General Public License as
10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  published by the Free Software Foundation; either version 2 of the
11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  License, or (at your option) any later version.
12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  This program is distributed in the hope that it will be useful, but
14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WITHOUT ANY WARRANTY; without even the implied warranty of
15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  General Public License for more details.
17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  You should have received a copy of the GNU General Public License
19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  along with this program; if not, write to the Free Software
20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  02111-1307, USA.
22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  The GNU General Public License is contained in the file COPYING.
24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* Author: Timur Iskhodzhanov <opensource@google.com>
27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file contains a set of Windows-specific unit tests for
29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a data race detection tool.
30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h>
33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "test_utils.h"
34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "gtest_fixture_injection.h"
35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DummyWorker() {
37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid LongWorker() {
40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Sleep(1);
41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  volatile int i = 1 << 20;
42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(i--);
43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WriteWorker(int *var) {
46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  LongWorker();
47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 42;
48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid VeryLongWriteWorker(int *var) {
51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Sleep(1000);
52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 42;
53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
55610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsCreateThreadFailureTest) {  // {{{1
56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t = ::CreateThread(0, -1,
57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                           (LPTHREAD_START_ROUTINE)DummyWorker, 0, 0, 0);
58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(t == 0);
59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
61610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_WindowsCreateThreadSuspendedTest) {  // {{{1
62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Hangs under TSan, see
63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // http://code.google.com/p/data-race-test/issues/detail?id=61
64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *var = new int;
65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t = ::CreateThread(0, 0,
66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                           (LPTHREAD_START_ROUTINE)WriteWorker, var,
67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                           CREATE_SUSPENDED, 0);
68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(t > 0);
69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_TIMEOUT,  ::WaitForSingleObject(t, 200));
70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 1;
71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(1, ResumeThread(t));
72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(t, INFINITE));
73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(42, *var);
74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete var;
75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
77610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsThreadStackSizeTest) {  // {{{1
78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Just spawn few threads with different stack sizes.
79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int sizes[3] = {1 << 19, 1 << 21, 1 << 22};
80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 3; i++) {
81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    HANDLE t = ::CreateThread(0, sizes[i],
82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                             (LPTHREAD_START_ROUTINE)DummyWorker, 0, 0, 0);
83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(t > 0);
84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(t, INFINITE));
85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CloseHandle(t);
86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
89610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsJoinWithTimeout) {  // {{{1
90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t = ::CreateThread(0, 0,
91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)LongWorker, 0, 0, 0);
92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t > 0);
93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_TIMEOUT,  ::WaitForSingleObject(t, 1));
94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(t, INFINITE));
95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t);
96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
98610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, HappensBeforeOnThreadJoin) {  // {{{1
99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *var = new int;
100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t = ::CreateThread(0, 0,
101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)WriteWorker, var, 0, 0);
102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t > 0);
103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Calling WaitForSingleObject two times to make sure the H-B arc
104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // is created on the second call. There was a bug that the thread handle
105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // was deleted even when WaitForSingleObject timed out.
106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_TIMEOUT,  ::WaitForSingleObject(t, 1));
107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(t, INFINITE));
108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(*var, 42);
109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t);
110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete var;
111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
113610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, HappensBeforeOnThreadJoinTidReuse) {  // {{{1
114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t1 = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)DummyWorker, 0, 0, 0);
115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t1);
116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Sleep(1000);
117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *var = new int;
119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t2 = ::CreateThread(0, 0,
120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                             (LPTHREAD_START_ROUTINE)WriteWorker, var, 0, 0);
121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("t1 = %d, t2 = %d\n");
122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(t2 > 0);
123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(WAIT_OBJECT_0 == ::WaitForSingleObject(t2, INFINITE));
124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*var == 42);
125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete var;
126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
128610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WaitForMultipleObjectsWaitAllTest) {
129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int var1 = 13,
130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      var2 = 13;
131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t1 = ::CreateThread(0, 0,
132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)WriteWorker, &var1, 0, 0),
133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         t2 = ::CreateThread(0, 0,
134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)WriteWorker, &var2, 0, 0);
135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t1 > 0);
136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t2 > 0);
137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE handles[2] = {t1, t2};
139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Calling WaitForMultipleObjectsTest two times to make sure the H-B arc
140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // are created on the second call.
141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_TIMEOUT,  ::WaitForMultipleObjects(2, handles, TRUE, 1));
142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(2, handles, TRUE, INFINITE));
143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(var1, 42);
144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(var2, 42);
145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t1);
146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t2);
147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
149610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WaitForMultipleObjectsWaitOneTest) {
150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int var1 = 13,
151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      var2 = 13;
152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE t1 = ::CreateThread(0, 0,
153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)VeryLongWriteWorker, &var1, 0, 0),
154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         t2 = ::CreateThread(0, 0,
155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                            (LPTHREAD_START_ROUTINE)WriteWorker, &var2, 0, 0);
156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t1 > 0);
157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(t2 > 0);
158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE handles[2] = {t1, t2};
160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Calling WaitForMultipleObjectsTest two times to make sure the H-B arc
161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // are created on the second call.
162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_TIMEOUT,  ::WaitForMultipleObjects(2, handles, FALSE, 1));
163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0 + 1, ::WaitForMultipleObjects(2, handles, FALSE, INFINITE));
164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(var2, 42);
165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(1, handles, FALSE, INFINITE));
166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(var1, 42);
167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t1);
168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(t2);
169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace RegisterWaitForSingleObjectTest {  // {{{1
172610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification *n = NULL;
173610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovHANDLE monitored_object = NULL;
174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SignalStealthNotification() {
176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n->wait();
177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  SetEvent(monitored_object);
178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid foo() { }
181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid CALLBACK DoneWaiting(void *param, BOOLEAN timed_out) {
183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *i = (int*)param;
184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  foo();  // make sure this function has a call. See issue 24.
185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*i)++;
186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
188610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsRegisterWaitForSingleObjectTest) {  // {{{1
189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // These are very tricky false positive found while testing Chromium.
190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //
191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Report #1:
192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   Everything after UnregisterWaitEx(*, INVALID_HANDLE_VALUE) happens-after
193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   execution of DoneWaiting callback. Currently, we don't catch this h-b.
194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //
195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Report #2:
196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   The callback thread is re-used between Registet/Unregister/Register calls
197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   so we miss h-b between "int *obj = ..." and DoneWaiting on the second
198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   iteration.
199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 2; i++) {
200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    n = new StealthNotification();
201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *obj = new int(0);
202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    HANDLE wait_object = NULL;
203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    monitored_object = ::CreateEvent(NULL, false, false, NULL);
205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("monitored_object = %p\n", monitored_object);
206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread mt(SignalStealthNotification);
207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mt.Start();
208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_TRACE_MEMORY(obj);
209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(0 != ::RegisterWaitForSingleObject(&wait_object, monitored_object,
210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                                             DoneWaiting, obj, INFINITE,
211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                                             WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE));
212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("wait_object      = %p\n", wait_object);
213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    n->signal();
214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mt.Join();
215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Sleep(1000);
216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(0 != ::UnregisterWaitEx(wait_object, INVALID_HANDLE_VALUE));
217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    (*obj)++;
218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(*obj == 2);
219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CloseHandle(monitored_object);
220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete n;
221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete obj;
222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace QueueUserWorkItemTests {
227610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovDWORD CALLBACK Callback(void *param) {
228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *ptr = (int*)param;
229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*ptr)++;
230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete ptr;
231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return 0;
232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
234610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsQueueUserWorkItemTest) {
235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // False positive:
236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   The callback thread is allocated from a thread pool and can be re-used.
237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   As a result, we may miss h-b between "int *obj = ..." and Callback execution.
238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 5; i++) {
239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *obj = new int(0);
240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_TRACE_MEMORY(obj);
241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(QueueUserWorkItem(Callback, obj, i % 2 ? WT_EXECUTELONGFUNCTION : 0));
242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Sleep(500);
243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 42;
247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
248610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovDWORD CALLBACK Callback2(void *param) {
249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  StealthNotification *ptr = (StealthNotification*)param;
250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Sleep(100);
252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ptr->signal();
253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return 0;
254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
256610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, WindowsQueueUserWorkItemTest) {
257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "PositiveTests.WindowsQueueUserWorkItemTest");
258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int N_THREAD = 5;
260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  StealthNotification n[N_THREAD];
261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_THREAD; i++)
263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(QueueUserWorkItem(Callback2, &n[i], i % 2 ? WT_EXECUTELONGFUNCTION : 0));
264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_THREAD; i++)
266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    n[i].wait();
267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsCriticalSectionTest {  // {{{1
271610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCRITICAL_SECTION cs;
272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
273610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsCriticalSectionTest) {
274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeCriticalSection(&cs);
275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EnterCriticalSection(&cs);
276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TryEnterCriticalSection(&cs);
277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  LeaveCriticalSection(&cs);
278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DeleteCriticalSection(&cs);
279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsSRWLockTest {  // {{{1
284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if WINVER >= 0x0600 // Vista or Windows Server 2000
285610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSRWLOCK SRWLock;
286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *obj;
287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockShared(&SRWLock);
290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*obj <= 2 && *obj >= 0);
291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSRWLockShared(&SRWLock);
292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockExclusive(&SRWLock);
296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*obj)++;
297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSRWLockExclusive(&SRWLock);
298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if 0  // This doesn't work in older versions of Windows.
301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TryReader() {
302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (TryAcquireSRWLockShared(&SRWLock)) {
303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(*obj <= 2 && *obj >= 0);
304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ReleaseSRWLockShared(&SRWLock);
305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TryWriter() {
309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (TryAcquireSRWLockExclusive(&SRWLock)) {
310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    (*obj)++;
311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ReleaseSRWLockExclusive(&SRWLock);
312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
316610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsSRWLockTest) {
317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeSRWLock(&SRWLock);
318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj = new int(0);
319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(obj);
320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader, Writer, Reader, Writer);
321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockShared(&SRWLock);
324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSRWLockShared(&SRWLock);
325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*obj == 2);
326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete obj;
327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
329610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsSRWLockHackyInitializationTest) {
330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // A similar pattern has been found on Chromium media_unittests
331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeSRWLock(&SRWLock);
332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockExclusive(&SRWLock);
333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Leave the lock acquired
334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Reset the lock
336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeSRWLock(&SRWLock);
337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj = new int(0);
338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader, Writer, Reader, Writer);
339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete obj;
342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // WINVER >= 0x0600
344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsConditionVariableSRWTest {  // {{{1
347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if WINVER >= 0x0600 // Vista or Windows Server 2000
348610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSRWLOCK SRWLock;
349610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCONDITION_VARIABLE cv;
350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool cond;
351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *obj;
352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
353610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WaiterSRW() {
356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *obj = 1;
357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockExclusive(&SRWLock);
359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  cond = true;
360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WakeConditionVariable(&cv);
361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSRWLockExclusive(&SRWLock);
362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WakerSRW() {
365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AcquireSRWLockExclusive(&SRWLock);
366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (!cond) {
368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    SleepConditionVariableSRW(&cv, &SRWLock, 10, 0);
369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSRWLockExclusive(&SRWLock);
371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*obj == 1);
372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *obj = 2;
373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
375610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsConditionVariableSRWTest) {
376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeSRWLock(&SRWLock);
377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeConditionVariable(&cv);
378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj = new int(0);
379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  cond = false;
380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(obj);
381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(WaiterSRW, WakerSRW);
382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*obj == 2);
385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete obj;
386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // WINVER >= 0x0600
388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsInterlockedListTest {  // {{{1
392610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSLIST_HEADER list;
393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Item {
395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  SLIST_ENTRY entry;
396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int foo;
397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Push() {
400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Item *item = new Item;
401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  item->foo = 42;
402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InterlockedPushEntrySList(&list, (PSINGLE_LIST_ENTRY)item);
403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Pop() {
406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Item *item;
407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (0 == (item = (Item*)InterlockedPopEntrySList(&list))) {
408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Sleep(1);
409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(item->foo == 42);
411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete item;
412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
414610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsInterlockedListTest) {
415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitializeSListHead(&list);
416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Push, Pop);
417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace FileSystemReports {  // {{{1
424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This is a test for the flaky report found in
426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Chromium net_unittests.
427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Looks like the test is sensitive to memory allocations / scheduling order,
429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// so you shouldn't run other tests while investigating the issue.
430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The report is ~50% flaky.
431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
432610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovHANDLE hDone = NULL;
433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid CreateFileJob() {
435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE hFile = CreateFileA("ZZZ\\tmpfile", GENERIC_READ | GENERIC_WRITE,
436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                      FILE_SHARE_READ, NULL, CREATE_ALWAYS,
437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                      FILE_ATTRIBUTE_NORMAL, NULL);
438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(hFile);
439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DWORD attr1 = GetFileAttributes("ZZZ");  // "Concurrent write" is here.
440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
442610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovDWORD CALLBACK PrintDirectoryListingJob(void *param) {
443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Sleep(500);
444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WIN32_FIND_DATAA data;
445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // "Current write" is here.
447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE hFind = FindFirstFileA("ZZZ/*", &data);
448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(hFind != INVALID_HANDLE_VALUE);
449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(hFind);
451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  SetEvent(hDone);
452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return 0;
453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is not very friendly to bots environment, so you should only
456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// run it manually.
457610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_CreateFileVsFindFirstFileTest) {
458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  hDone = ::CreateEvent(NULL, false, false, NULL);
459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ::CreateDirectory("ZZZ", NULL);
461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Run PrintDirectoryListingJob in a concurrent thread.
463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(::QueueUserWorkItem(PrintDirectoryListingJob, NULL,
464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                          WT_EXECUTELONGFUNCTION));
465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CreateFileJob();
466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ::WaitForSingleObject(hDone, INFINITE);
468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ::CloseHandle(hDone);
469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(::DeleteFile("ZZZ\\tmpfile"));
470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(::RemoveDirectory("ZZZ"));
471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  //namespace
474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsAtomicsTests { // {{{1
476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test should not give us any reports if compiled with proper MSVS flags.
477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The Atomic_{Read,Write} functions are ignored in racecheck_unittest.ignore
478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 42;
480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline int Atomic_Read(volatile const int* ptr) {
482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // MSVS volatile gives us atomicity.
483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int value = *ptr;
484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return value;
485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline void Atomic_Write(volatile int* ptr, int value) {
488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // MSVS volatile gives us atomicity.
489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *ptr = value;
490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int value = Atomic_Read(&GLOB);
494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Atomic_Write(&GLOB, ~value);
495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
497610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, WindowsAtomicsTests) {
498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Worker, Worker);
499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace WindowsSemaphoreTests {
506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Poster(int *var, HANDLE sem) {
507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 1;
508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ReleaseSemaphore(sem, 1, NULL);
509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter(int *var, HANDLE sem) {
512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DWORD ret = ::WaitForSingleObject(sem, INFINITE);
513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_EQ(ret, WAIT_OBJECT_0);
514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(*var, 1);
515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
517610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, SimpleSemaphoreTest) {
518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE sem = CreateSemaphore(NULL,
519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                               0 /* initial count */,
520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                               20 /* max count */,
521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                               NULL);
522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(sem != NULL);
523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int VAR = 0;
526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool tp(2);
527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.StartWorkers();
528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Waiter, &VAR, sem));
529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Poster, &VAR, sem));
530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(sem);
533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
535610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_SemaphoreNameReuseTest) {
536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // TODO(timurrrr): Semaphore reuse is not yet understood by TSan.
537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const char NAME[] = "SemaphoreZZZ";
538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE h1 = CreateSemaphore(NULL, 0, 10, NAME),
539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         h2 = CreateSemaphore(NULL, 0, 15, NAME);
540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(h1 != NULL);
541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(h2 != NULL);
542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // h1 and h2 refer to the same semaphore but are not equal.
544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_NE(h1, h2);
545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int VAR = 0;
548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool tp(2);
549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.StartWorkers();
550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Waiter, &VAR, h1));
551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Poster, &VAR, h2));
552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(h1);
555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(h2);
556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace HandleReuseTests {
561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker(int *var, HANDLE h) {
563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 1;
564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  SetEvent(h);
565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter(int *var, HANDLE h) {
568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DWORD ret = ::WaitForSingleObject(h, INFINITE);
569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_EQ(ret, WAIT_OBJECT_0);
570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_EQ(*var, 1);
571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
573610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_EventHandleReuseTest) {
574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // TODO(timurrrr): DuplicateHandle is not yet understood by TSan.
575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE h1 = CreateEvent(NULL, false, false, NULL);
576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(h1 != NULL);
577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HANDLE h2 = NULL;
578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  DuplicateHandle(GetCurrentProcess(), h1,
579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  GetCurrentProcess(), &h2,
580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  0 /* access */, FALSE /* inherit*/, DUPLICATE_SAME_ACCESS);
581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(h2 != NULL);
582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // h1 and h2 refer to the same Event but are not equal.
584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_NE(h1, h2);
585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int VAR = 0;
588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool tp(2);
589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.StartWorkers();
590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Waiter, &VAR, h1));
591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    tp.Add(NewCallback(Waker,  &VAR, h2));
592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(h1);
595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CloseHandle(h2);
596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1
600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
601