OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // NOTE(vtl): These tests are inherently flaky (e.g., if run on a heavily-loaded |
| 6 // system). Sorry. |kEpsilonMicros| may be increased to increase tolerance and |
| 7 // reduce observed flakiness. |
| 8 |
| 9 #include "mojo/system/waiter_list.h" |
| 10 |
| 11 #include "base/threading/platform_thread.h" // For |Sleep()|. |
| 12 #include "base/time/time.h" |
| 13 #include "mojo/system/waiter.h" |
| 14 #include "mojo/system/waiter_test_utils.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 |
| 17 namespace mojo { |
| 18 namespace system { |
| 19 namespace { |
| 20 |
| 21 const int64_t kMicrosPerMs = 1000; |
| 22 const int64_t kEpsilonMicros = 15 * kMicrosPerMs; // 15 ms. |
| 23 |
| 24 TEST(WaiterListTest, BasicCancel) { |
| 25 MojoResult result; |
| 26 |
| 27 // Cancel immediately after thread start. |
| 28 { |
| 29 WaiterList waiter_list; |
| 30 test::SimpleWaiterThread thread(&result); |
| 31 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0); |
| 32 thread.Start(); |
| 33 waiter_list.CancelAllWaiters(); |
| 34 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. |
| 35 } // Join |thread|. |
| 36 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 37 |
| 38 // Cancel before after thread start. |
| 39 { |
| 40 WaiterList waiter_list; |
| 41 test::SimpleWaiterThread thread(&result); |
| 42 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1); |
| 43 waiter_list.CancelAllWaiters(); |
| 44 thread.Start(); |
| 45 } // Join |thread|. |
| 46 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 47 |
| 48 // Cancel some time after thread start. |
| 49 { |
| 50 WaiterList waiter_list; |
| 51 test::SimpleWaiterThread thread(&result); |
| 52 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2); |
| 53 thread.Start(); |
| 54 base::PlatformThread::Sleep( |
| 55 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 56 waiter_list.CancelAllWaiters(); |
| 57 } // Join |thread|. |
| 58 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
| 59 } |
| 60 |
| 61 TEST(WaiterListTest, BasicAwakeSatisfied) { |
| 62 MojoResult result; |
| 63 |
| 64 // Awake immediately after thread start. |
| 65 { |
| 66 WaiterList waiter_list; |
| 67 test::SimpleWaiterThread thread(&result); |
| 68 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0); |
| 69 thread.Start(); |
| 70 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE, |
| 71 MOJO_WAIT_FLAG_READABLE | |
| 72 MOJO_WAIT_FLAG_WRITABLE); |
| 73 waiter_list.RemoveWaiter(thread.waiter()); |
| 74 } // Join |thread|. |
| 75 EXPECT_EQ(0, result); |
| 76 |
| 77 // Awake before after thread start. |
| 78 { |
| 79 WaiterList waiter_list; |
| 80 test::SimpleWaiterThread thread(&result); |
| 81 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1); |
| 82 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_WRITABLE, |
| 83 MOJO_WAIT_FLAG_READABLE | |
| 84 MOJO_WAIT_FLAG_WRITABLE); |
| 85 waiter_list.RemoveWaiter(thread.waiter()); |
| 86 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. |
| 87 thread.Start(); |
| 88 } // Join |thread|. |
| 89 EXPECT_EQ(1, result); |
| 90 |
| 91 // Awake some time after thread start. |
| 92 { |
| 93 WaiterList waiter_list; |
| 94 test::SimpleWaiterThread thread(&result); |
| 95 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2); |
| 96 thread.Start(); |
| 97 base::PlatformThread::Sleep( |
| 98 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 99 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE, |
| 100 MOJO_WAIT_FLAG_READABLE | |
| 101 MOJO_WAIT_FLAG_WRITABLE); |
| 102 waiter_list.RemoveWaiter(thread.waiter()); |
| 103 } // Join |thread|. |
| 104 EXPECT_EQ(2, result); |
| 105 } |
| 106 |
| 107 TEST(WaiterListTest, BasicAwakeUnsatisfiable) { |
| 108 MojoResult result; |
| 109 |
| 110 // Awake (for unsatisfiability) immediately after thread start. |
| 111 { |
| 112 WaiterList waiter_list; |
| 113 test::SimpleWaiterThread thread(&result); |
| 114 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 0); |
| 115 thread.Start(); |
| 116 waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_WRITABLE); |
| 117 waiter_list.RemoveWaiter(thread.waiter()); |
| 118 } // Join |thread|. |
| 119 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
| 120 |
| 121 // Awake (for unsatisfiability) before after thread start. |
| 122 { |
| 123 WaiterList waiter_list; |
| 124 test::SimpleWaiterThread thread(&result); |
| 125 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1); |
| 126 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE, |
| 127 MOJO_WAIT_FLAG_READABLE); |
| 128 waiter_list.RemoveWaiter(thread.waiter()); |
| 129 thread.Start(); |
| 130 } // Join |thread|. |
| 131 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
| 132 |
| 133 // Awake (for unsatisfiability) some time after thread start. |
| 134 { |
| 135 WaiterList waiter_list; |
| 136 test::SimpleWaiterThread thread(&result); |
| 137 waiter_list.AddWaiter(thread.waiter(), MOJO_WAIT_FLAG_READABLE, 2); |
| 138 thread.Start(); |
| 139 base::PlatformThread::Sleep( |
| 140 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 141 waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_WRITABLE); |
| 142 waiter_list.RemoveWaiter(thread.waiter()); |
| 143 waiter_list.RemoveWaiter(thread.waiter()); // Double-remove okay. |
| 144 } // Join |thread|. |
| 145 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
| 146 } |
| 147 |
| 148 TEST(WaiterListTest, MultipleWaiters) { |
| 149 MojoResult result_1; |
| 150 MojoResult result_2; |
| 151 MojoResult result_3; |
| 152 MojoResult result_4; |
| 153 |
| 154 // Cancel two waiters. |
| 155 { |
| 156 WaiterList waiter_list; |
| 157 test::SimpleWaiterThread thread_1(&result_1); |
| 158 waiter_list.AddWaiter(thread_1.waiter(), MOJO_WAIT_FLAG_READABLE, 0); |
| 159 thread_1.Start(); |
| 160 test::SimpleWaiterThread thread_2(&result_2); |
| 161 waiter_list.AddWaiter(thread_2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 1); |
| 162 thread_2.Start(); |
| 163 base::PlatformThread::Sleep( |
| 164 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 165 waiter_list.CancelAllWaiters(); |
| 166 } // Join threads. |
| 167 EXPECT_EQ(MOJO_RESULT_CANCELLED, result_1); |
| 168 EXPECT_EQ(MOJO_RESULT_CANCELLED, result_2); |
| 169 |
| 170 // Awake one waiter, cancel other. |
| 171 { |
| 172 WaiterList waiter_list; |
| 173 test::SimpleWaiterThread thread_1(&result_1); |
| 174 waiter_list.AddWaiter(thread_1.waiter(), MOJO_WAIT_FLAG_READABLE, 2); |
| 175 thread_1.Start(); |
| 176 test::SimpleWaiterThread thread_2(&result_2); |
| 177 waiter_list.AddWaiter(thread_2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 3); |
| 178 thread_2.Start(); |
| 179 base::PlatformThread::Sleep( |
| 180 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 181 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE, |
| 182 MOJO_WAIT_FLAG_READABLE | |
| 183 MOJO_WAIT_FLAG_WRITABLE); |
| 184 waiter_list.RemoveWaiter(thread_1.waiter()); |
| 185 waiter_list.CancelAllWaiters(); |
| 186 } // Join threads. |
| 187 EXPECT_EQ(2, result_1); |
| 188 EXPECT_EQ(MOJO_RESULT_CANCELLED, result_2); |
| 189 |
| 190 // Cancel one waiter, awake other for unsatisfiability. |
| 191 { |
| 192 WaiterList waiter_list; |
| 193 test::SimpleWaiterThread thread_1(&result_1); |
| 194 waiter_list.AddWaiter(thread_1.waiter(), MOJO_WAIT_FLAG_READABLE, 4); |
| 195 thread_1.Start(); |
| 196 test::SimpleWaiterThread thread_2(&result_2); |
| 197 waiter_list.AddWaiter(thread_2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 5); |
| 198 thread_2.Start(); |
| 199 base::PlatformThread::Sleep( |
| 200 base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros)); |
| 201 waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_READABLE); |
| 202 waiter_list.RemoveWaiter(thread_2.waiter()); |
| 203 waiter_list.CancelAllWaiters(); |
| 204 } // Join threads. |
| 205 EXPECT_EQ(MOJO_RESULT_CANCELLED, result_1); |
| 206 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result_2); |
| 207 |
| 208 // Cancel one waiter, awake other for unsatisfiability. |
| 209 { |
| 210 WaiterList waiter_list; |
| 211 test::SimpleWaiterThread thread_1(&result_1); |
| 212 waiter_list.AddWaiter(thread_1.waiter(), MOJO_WAIT_FLAG_READABLE, 6); |
| 213 thread_1.Start(); |
| 214 |
| 215 base::PlatformThread::Sleep( |
| 216 base::TimeDelta::FromMicroseconds(1 * kEpsilonMicros)); |
| 217 |
| 218 // Should do nothing. |
| 219 waiter_list.AwakeWaitersForStateChange(0, |
| 220 MOJO_WAIT_FLAG_READABLE | |
| 221 MOJO_WAIT_FLAG_WRITABLE); |
| 222 |
| 223 test::SimpleWaiterThread thread_2(&result_2); |
| 224 waiter_list.AddWaiter(thread_2.waiter(), MOJO_WAIT_FLAG_WRITABLE, 7); |
| 225 thread_2.Start(); |
| 226 |
| 227 base::PlatformThread::Sleep( |
| 228 base::TimeDelta::FromMicroseconds(1 * kEpsilonMicros)); |
| 229 |
| 230 // Awake #1. |
| 231 waiter_list.AwakeWaitersForStateChange(MOJO_WAIT_FLAG_READABLE, |
| 232 MOJO_WAIT_FLAG_READABLE | |
| 233 MOJO_WAIT_FLAG_WRITABLE); |
| 234 waiter_list.RemoveWaiter(thread_1.waiter()); |
| 235 |
| 236 base::PlatformThread::Sleep( |
| 237 base::TimeDelta::FromMicroseconds(1 * kEpsilonMicros)); |
| 238 |
| 239 test::SimpleWaiterThread thread_3(&result_3); |
| 240 waiter_list.AddWaiter(thread_3.waiter(), MOJO_WAIT_FLAG_WRITABLE, 8); |
| 241 thread_3.Start(); |
| 242 |
| 243 test::SimpleWaiterThread thread_4(&result_4); |
| 244 waiter_list.AddWaiter(thread_4.waiter(), MOJO_WAIT_FLAG_READABLE, 9); |
| 245 thread_4.Start(); |
| 246 |
| 247 base::PlatformThread::Sleep( |
| 248 base::TimeDelta::FromMicroseconds(1 * kEpsilonMicros)); |
| 249 |
| 250 // Awake #2 and #3 for unsatisfiability. |
| 251 waiter_list.AwakeWaitersForStateChange(0, MOJO_WAIT_FLAG_READABLE); |
| 252 waiter_list.RemoveWaiter(thread_2.waiter()); |
| 253 waiter_list.RemoveWaiter(thread_3.waiter()); |
| 254 |
| 255 // Cancel #4. |
| 256 waiter_list.CancelAllWaiters(); |
| 257 } // Join threads. |
| 258 EXPECT_EQ(6, result_1); |
| 259 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result_2); |
| 260 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result_3); |
| 261 EXPECT_EQ(MOJO_RESULT_CANCELLED, result_4); |
| 262 } |
| 263 |
| 264 } // namespace |
| 265 } // namespace system |
| 266 } // namespace mojo |
OLD | NEW |