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