| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 #include "base/multiprocess_test.h" | 5 #include "base/multiprocess_test.h" |
| 6 #include "base/platform_thread.h" | 6 #include "base/platform_thread.h" |
| 7 #include "base/simple_thread.h" | 7 #include "base/simple_thread.h" |
| 8 #include "base/shared_memory.h" |
| 8 #include "base/stats_table.h" | 9 #include "base/stats_table.h" |
| 9 #include "base/stats_counters.h" | 10 #include "base/stats_counters.h" |
| 10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "testing/multiprocess_func_list.h" | 13 #include "testing/multiprocess_func_list.h" |
| 13 | 14 |
| 14 #if defined(OS_WIN) | 15 #if defined(OS_WIN) |
| 15 #include <process.h> | 16 #include <process.h> |
| 16 #include <windows.h> | 17 #include <windows.h> |
| 17 #endif | 18 #endif |
| 18 | 19 |
| 19 namespace base { | 20 namespace base { |
| 20 | 21 |
| 21 class StatsTableTest : public MultiProcessTest { | 22 class StatsTableTest : public MultiProcessTest { |
| 23 public: |
| 24 void DeleteShmem(std::string name) { |
| 25 base::SharedMemory mem; |
| 26 mem.Delete(UTF8ToWide(name)); |
| 27 } |
| 22 }; | 28 }; |
| 23 | 29 |
| 24 // Open a StatsTable and verify that we can write to each of the | 30 // Open a StatsTable and verify that we can write to each of the |
| 25 // locations in the table. | 31 // locations in the table. |
| 26 TEST_F(StatsTableTest, VerifySlots) { | 32 TEST_F(StatsTableTest, VerifySlots) { |
| 27 const std::string kTableName = "VerifySlotsStatTable"; | 33 const std::string kTableName = "VerifySlotsStatTable"; |
| 28 const int kMaxThreads = 1; | 34 const int kMaxThreads = 1; |
| 29 const int kMaxCounter = 5; | 35 const int kMaxCounter = 5; |
| 36 DeleteShmem(kTableName); |
| 30 StatsTable table(kTableName, kMaxThreads, kMaxCounter); | 37 StatsTable table(kTableName, kMaxThreads, kMaxCounter); |
| 31 | 38 |
| 32 // Register a single thread. | 39 // Register a single thread. |
| 33 std::string thread_name = "mainThread"; | 40 std::string thread_name = "mainThread"; |
| 34 int slot_id = table.RegisterThread(thread_name); | 41 int slot_id = table.RegisterThread(thread_name); |
| 35 EXPECT_TRUE(slot_id); | 42 EXPECT_TRUE(slot_id); |
| 36 | 43 |
| 37 // Fill up the table with counters. | 44 // Fill up the table with counters. |
| 38 std::string counter_base_name = "counter"; | 45 std::string counter_base_name = "counter"; |
| 39 for (int index=0; index < kMaxCounter; index++) { | 46 for (int index=0; index < kMaxCounter; index++) { |
| 40 std::string counter_name = counter_base_name; | 47 std::string counter_name = counter_base_name; |
| 41 StringAppendF(&counter_name, "counter.ctr%d", index); | 48 StringAppendF(&counter_name, "counter.ctr%d", index); |
| 42 int counter_id = table.FindCounter(counter_name); | 49 int counter_id = table.FindCounter(counter_name); |
| 43 EXPECT_GT(counter_id, 0); | 50 EXPECT_GT(counter_id, 0); |
| 44 } | 51 } |
| 45 | 52 |
| 46 // Try to allocate an additional thread. Verify it fails. | 53 // Try to allocate an additional thread. Verify it fails. |
| 47 slot_id = table.RegisterThread("too many threads"); | 54 slot_id = table.RegisterThread("too many threads"); |
| 48 EXPECT_EQ(slot_id, 0); | 55 EXPECT_EQ(slot_id, 0); |
| 49 | 56 |
| 50 // Try to allocate an additional counter. Verify it fails. | 57 // Try to allocate an additional counter. Verify it fails. |
| 51 int counter_id = table.FindCounter(counter_base_name); | 58 int counter_id = table.FindCounter(counter_base_name); |
| 52 EXPECT_EQ(counter_id, 0); | 59 EXPECT_EQ(counter_id, 0); |
| 60 |
| 61 DeleteShmem(kTableName); |
| 53 } | 62 } |
| 54 | 63 |
| 55 // CounterZero will continually be set to 0. | 64 // CounterZero will continually be set to 0. |
| 56 const std::string kCounterZero = "CounterZero"; | 65 const std::string kCounterZero = "CounterZero"; |
| 57 // Counter1313 will continually be set to 1313. | 66 // Counter1313 will continually be set to 1313. |
| 58 const std::string kCounter1313 = "Counter1313"; | 67 const std::string kCounter1313 = "Counter1313"; |
| 59 // CounterIncrement will be incremented each time. | 68 // CounterIncrement will be incremented each time. |
| 60 const std::string kCounterIncrement = "CounterIncrement"; | 69 const std::string kCounterIncrement = "CounterIncrement"; |
| 61 // CounterDecrement will be decremented each time. | 70 // CounterDecrement will be decremented each time. |
| 62 const std::string kCounterDecrement = "CounterDecrement"; | 71 const std::string kCounterDecrement = "CounterDecrement"; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 PlatformThread::Sleep(index % 10); // short wait | 106 PlatformThread::Sleep(index % 10); // short wait |
| 98 } | 107 } |
| 99 } | 108 } |
| 100 | 109 |
| 101 // Create a few threads and have them poke on their counters. | 110 // Create a few threads and have them poke on their counters. |
| 102 TEST_F(StatsTableTest, MultipleThreads) { | 111 TEST_F(StatsTableTest, MultipleThreads) { |
| 103 // Create a stats table. | 112 // Create a stats table. |
| 104 const std::string kTableName = "MultipleThreadStatTable"; | 113 const std::string kTableName = "MultipleThreadStatTable"; |
| 105 const int kMaxThreads = 20; | 114 const int kMaxThreads = 20; |
| 106 const int kMaxCounter = 5; | 115 const int kMaxCounter = 5; |
| 116 DeleteShmem(kTableName); |
| 107 StatsTable table(kTableName, kMaxThreads, kMaxCounter); | 117 StatsTable table(kTableName, kMaxThreads, kMaxCounter); |
| 108 StatsTable::set_current(&table); | 118 StatsTable::set_current(&table); |
| 109 | 119 |
| 110 EXPECT_EQ(0, table.CountThreadsRegistered()); | 120 EXPECT_EQ(0, table.CountThreadsRegistered()); |
| 111 | 121 |
| 112 // Spin up a set of threads to go bang on the various counters. | 122 // Spin up a set of threads to go bang on the various counters. |
| 113 // After we join the threads, we'll make sure the counters | 123 // After we join the threads, we'll make sure the counters |
| 114 // contain the values we expected. | 124 // contain the values we expected. |
| 115 StatsTableThread* threads[kMaxThreads]; | 125 StatsTableThread* threads[kMaxThreads]; |
| 116 | 126 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 142 name = "c:" + kCounterIncrement; | 152 name = "c:" + kCounterIncrement; |
| 143 EXPECT_EQ(kMaxThreads * kThreadLoops, | 153 EXPECT_EQ(kMaxThreads * kThreadLoops, |
| 144 table.GetCounterValue(name)); | 154 table.GetCounterValue(name)); |
| 145 name = "c:" + kCounterDecrement; | 155 name = "c:" + kCounterDecrement; |
| 146 EXPECT_EQ(-kMaxThreads * kThreadLoops, | 156 EXPECT_EQ(-kMaxThreads * kThreadLoops, |
| 147 table.GetCounterValue(name)); | 157 table.GetCounterValue(name)); |
| 148 name = "c:" + kCounterMixed; | 158 name = "c:" + kCounterMixed; |
| 149 EXPECT_EQ((kMaxThreads % 2) * kThreadLoops, | 159 EXPECT_EQ((kMaxThreads % 2) * kThreadLoops, |
| 150 table.GetCounterValue(name)); | 160 table.GetCounterValue(name)); |
| 151 EXPECT_EQ(0, table.CountThreadsRegistered()); | 161 EXPECT_EQ(0, table.CountThreadsRegistered()); |
| 162 |
| 163 DeleteShmem(kTableName); |
| 152 } | 164 } |
| 153 | 165 |
| 154 const std::string kTableName = "MultipleProcessStatTable"; | 166 const std::string kMPTableName = "MultipleProcessStatTable"; |
| 155 | 167 |
| 156 MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) { | 168 MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) { |
| 157 // Each process will open the shared memory and set counters | 169 // Each process will open the shared memory and set counters |
| 158 // concurrently in a loop. We'll use some pauses to | 170 // concurrently in a loop. We'll use some pauses to |
| 159 // mixup the scheduling. | 171 // mixup the scheduling. |
| 160 | 172 |
| 161 StatsTable table(kTableName, 0, 0); | 173 StatsTable table(kMPTableName, 0, 0); |
| 162 StatsTable::set_current(&table); | 174 StatsTable::set_current(&table); |
| 163 StatsCounter zero_counter(kCounterZero); | 175 StatsCounter zero_counter(kCounterZero); |
| 164 StatsCounter lucky13_counter(kCounter1313); | 176 StatsCounter lucky13_counter(kCounter1313); |
| 165 StatsCounter increment_counter(kCounterIncrement); | 177 StatsCounter increment_counter(kCounterIncrement); |
| 166 StatsCounter decrement_counter(kCounterDecrement); | 178 StatsCounter decrement_counter(kCounterDecrement); |
| 167 for (int index = 0; index < kThreadLoops; index++) { | 179 for (int index = 0; index < kThreadLoops; index++) { |
| 168 zero_counter.Set(0); | 180 zero_counter.Set(0); |
| 169 lucky13_counter.Set(1313); | 181 lucky13_counter.Set(1313); |
| 170 increment_counter.Increment(); | 182 increment_counter.Increment(); |
| 171 decrement_counter.Decrement(); | 183 decrement_counter.Decrement(); |
| 172 PlatformThread::Sleep(index % 10); // short wait | 184 PlatformThread::Sleep(index % 10); // short wait |
| 173 } | 185 } |
| 174 return 0; | 186 return 0; |
| 175 } | 187 } |
| 176 | 188 |
| 177 // Create a few processes and have them poke on their counters. | 189 // Create a few processes and have them poke on their counters. |
| 178 TEST_F(StatsTableTest, MultipleProcesses) { | 190 TEST_F(StatsTableTest, MultipleProcesses) { |
| 179 // Create a stats table. | 191 // Create a stats table. |
| 180 const std::string kTableName = "MultipleProcessStatTable"; | |
| 181 const int kMaxProcs = 20; | 192 const int kMaxProcs = 20; |
| 182 const int kMaxCounter = 5; | 193 const int kMaxCounter = 5; |
| 183 StatsTable table(kTableName, kMaxProcs, kMaxCounter); | 194 DeleteShmem(kMPTableName); |
| 195 StatsTable table(kMPTableName, kMaxProcs, kMaxCounter); |
| 184 StatsTable::set_current(&table); | 196 StatsTable::set_current(&table); |
| 185 | |
| 186 EXPECT_EQ(0, table.CountThreadsRegistered()); | 197 EXPECT_EQ(0, table.CountThreadsRegistered()); |
| 187 | 198 |
| 188 // Spin up a set of processes to go bang on the various counters. | 199 // Spin up a set of processes to go bang on the various counters. |
| 189 // After we join the processes, we'll make sure the counters | 200 // After we join the processes, we'll make sure the counters |
| 190 // contain the values we expected. | 201 // contain the values we expected. |
| 191 ProcessHandle procs[kMaxProcs]; | 202 ProcessHandle procs[kMaxProcs]; |
| 192 | 203 |
| 193 // Spawn the processes. | 204 // Spawn the processes. |
| 194 for (int16 index = 0; index < kMaxProcs; index++) { | 205 for (int16 index = 0; index < kMaxProcs; index++) { |
| 195 procs[index] = this->SpawnChild(L"StatsTableMultipleProcessMain"); | 206 procs[index] = this->SpawnChild(L"StatsTableMultipleProcessMain"); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 213 name = "c:" + kCounter1313; | 224 name = "c:" + kCounter1313; |
| 214 EXPECT_EQ(1313 * kMaxProcs, | 225 EXPECT_EQ(1313 * kMaxProcs, |
| 215 table.GetCounterValue(name)); | 226 table.GetCounterValue(name)); |
| 216 name = "c:" + kCounterIncrement; | 227 name = "c:" + kCounterIncrement; |
| 217 EXPECT_EQ(kMaxProcs * kThreadLoops, | 228 EXPECT_EQ(kMaxProcs * kThreadLoops, |
| 218 table.GetCounterValue(name)); | 229 table.GetCounterValue(name)); |
| 219 name = "c:" + kCounterDecrement; | 230 name = "c:" + kCounterDecrement; |
| 220 EXPECT_EQ(-kMaxProcs * kThreadLoops, | 231 EXPECT_EQ(-kMaxProcs * kThreadLoops, |
| 221 table.GetCounterValue(name)); | 232 table.GetCounterValue(name)); |
| 222 EXPECT_EQ(0, table.CountThreadsRegistered()); | 233 EXPECT_EQ(0, table.CountThreadsRegistered()); |
| 234 |
| 235 DeleteShmem(kMPTableName); |
| 223 } | 236 } |
| 224 | 237 |
| 225 class MockStatsCounter : public StatsCounter { | 238 class MockStatsCounter : public StatsCounter { |
| 226 public: | 239 public: |
| 227 MockStatsCounter(const std::string& name) | 240 MockStatsCounter(const std::string& name) |
| 228 : StatsCounter(name) {} | 241 : StatsCounter(name) {} |
| 229 int* Pointer() { return GetPtr(); } | 242 int* Pointer() { return GetPtr(); } |
| 230 }; | 243 }; |
| 231 | 244 |
| 232 // Test some basic StatsCounter operations | 245 // Test some basic StatsCounter operations |
| 233 TEST_F(StatsTableTest, StatsCounter) { | 246 TEST_F(StatsTableTest, StatsCounter) { |
| 234 // Create a stats table. | 247 // Create a stats table. |
| 235 const std::string kTableName = "StatTable"; | 248 const std::string kTableName = "StatTable"; |
| 236 const int kMaxThreads = 20; | 249 const int kMaxThreads = 20; |
| 237 const int kMaxCounter = 5; | 250 const int kMaxCounter = 5; |
| 251 DeleteShmem(kTableName); |
| 238 StatsTable table(kTableName, kMaxThreads, kMaxCounter); | 252 StatsTable table(kTableName, kMaxThreads, kMaxCounter); |
| 239 StatsTable::set_current(&table); | 253 StatsTable::set_current(&table); |
| 240 | 254 |
| 241 MockStatsCounter foo("foo"); | 255 MockStatsCounter foo("foo"); |
| 242 | 256 |
| 243 // Test initial state. | 257 // Test initial state. |
| 244 EXPECT_TRUE(foo.Enabled()); | 258 EXPECT_TRUE(foo.Enabled()); |
| 245 EXPECT_NE(foo.Pointer(), static_cast<int*>(0)); | 259 EXPECT_NE(foo.Pointer(), static_cast<int*>(0)); |
| 246 EXPECT_EQ(0, table.GetCounterValue("c:foo")); | 260 EXPECT_EQ(0, table.GetCounterValue("c:foo")); |
| 247 EXPECT_EQ(0, *(foo.Pointer())); | 261 EXPECT_EQ(0, *(foo.Pointer())); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 264 foo.Set(0); | 278 foo.Set(0); |
| 265 EXPECT_EQ(0, table.GetCounterValue("c:foo")); | 279 EXPECT_EQ(0, table.GetCounterValue("c:foo")); |
| 266 | 280 |
| 267 // Test Decrement. | 281 // Test Decrement. |
| 268 foo.Decrement(1); | 282 foo.Decrement(1); |
| 269 EXPECT_EQ(-1, table.GetCounterValue("c:foo")); | 283 EXPECT_EQ(-1, table.GetCounterValue("c:foo")); |
| 270 foo.Decrement(0); | 284 foo.Decrement(0); |
| 271 EXPECT_EQ(-1, table.GetCounterValue("c:foo")); | 285 EXPECT_EQ(-1, table.GetCounterValue("c:foo")); |
| 272 foo.Decrement(-1); | 286 foo.Decrement(-1); |
| 273 EXPECT_EQ(0, table.GetCounterValue("c:foo")); | 287 EXPECT_EQ(0, table.GetCounterValue("c:foo")); |
| 288 |
| 289 DeleteShmem(kTableName); |
| 274 } | 290 } |
| 275 | 291 |
| 276 class MockStatsCounterTimer : public StatsCounterTimer { | 292 class MockStatsCounterTimer : public StatsCounterTimer { |
| 277 public: | 293 public: |
| 278 MockStatsCounterTimer(const std::string& name) | 294 MockStatsCounterTimer(const std::string& name) |
| 279 : StatsCounterTimer(name) {} | 295 : StatsCounterTimer(name) {} |
| 280 | 296 |
| 281 TimeTicks start_time() { return start_time_; } | 297 TimeTicks start_time() { return start_time_; } |
| 282 TimeTicks stop_time() { return stop_time_; } | 298 TimeTicks stop_time() { return stop_time_; } |
| 283 }; | 299 }; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 EXPECT_EQ(2, table.GetCounterValue("c:baz")); | 357 EXPECT_EQ(2, table.GetCounterValue("c:baz")); |
| 342 EXPECT_LE(1000, table.GetCounterValue("t:baz")); | 358 EXPECT_LE(1000, table.GetCounterValue("t:baz")); |
| 343 } | 359 } |
| 344 | 360 |
| 345 // Test some basic StatsScope operations | 361 // Test some basic StatsScope operations |
| 346 TEST_F(StatsTableTest, StatsScope) { | 362 TEST_F(StatsTableTest, StatsScope) { |
| 347 // Create a stats table. | 363 // Create a stats table. |
| 348 const std::string kTableName = "StatTable"; | 364 const std::string kTableName = "StatTable"; |
| 349 const int kMaxThreads = 20; | 365 const int kMaxThreads = 20; |
| 350 const int kMaxCounter = 5; | 366 const int kMaxCounter = 5; |
| 367 DeleteShmem(kTableName); |
| 351 StatsTable table(kTableName, kMaxThreads, kMaxCounter); | 368 StatsTable table(kTableName, kMaxThreads, kMaxCounter); |
| 352 StatsTable::set_current(&table); | 369 StatsTable::set_current(&table); |
| 353 | 370 |
| 354 StatsCounterTimer foo("foo"); | 371 StatsCounterTimer foo("foo"); |
| 355 StatsRate bar("bar"); | 372 StatsRate bar("bar"); |
| 356 | 373 |
| 357 // Test initial state. | 374 // Test initial state. |
| 358 EXPECT_EQ(0, table.GetCounterValue("t:foo")); | 375 EXPECT_EQ(0, table.GetCounterValue("t:foo")); |
| 359 EXPECT_EQ(0, table.GetCounterValue("t:bar")); | 376 EXPECT_EQ(0, table.GetCounterValue("t:bar")); |
| 360 EXPECT_EQ(0, table.GetCounterValue("c:bar")); | 377 EXPECT_EQ(0, table.GetCounterValue("c:bar")); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 371 | 388 |
| 372 // Try a second scope. | 389 // Try a second scope. |
| 373 { | 390 { |
| 374 StatsScope<StatsCounterTimer> timer(foo); | 391 StatsScope<StatsCounterTimer> timer(foo); |
| 375 StatsScope<StatsRate> timer2(bar); | 392 StatsScope<StatsRate> timer2(bar); |
| 376 PlatformThread::Sleep(500); | 393 PlatformThread::Sleep(500); |
| 377 } | 394 } |
| 378 EXPECT_LE(1000, table.GetCounterValue("t:foo")); | 395 EXPECT_LE(1000, table.GetCounterValue("t:foo")); |
| 379 EXPECT_LE(1000, table.GetCounterValue("t:bar")); | 396 EXPECT_LE(1000, table.GetCounterValue("t:bar")); |
| 380 EXPECT_EQ(2, table.GetCounterValue("c:bar")); | 397 EXPECT_EQ(2, table.GetCounterValue("c:bar")); |
| 398 |
| 399 DeleteShmem(kTableName); |
| 381 } | 400 } |
| 382 | 401 |
| 383 } // namespace base | 402 } // namespace base |
| OLD | NEW |