This source file includes following definitions.
- DeleteShmem
- TEST_F
- id_
- Run
- TEST_F
- MULTIPROCESS_TEST_MAIN
- TEST_F
- Pointer
- TEST_F
- start_time
- stop_time
- TEST_F
- TEST_F
- TEST_F
#include "base/memory/shared_memory.h"
#include "base/metrics/stats_counters.h"
#include "base/metrics/stats_table.h"
#include "base/process/kill.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/multiprocess_test.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
namespace base {
class StatsTableTest : public MultiProcessTest {
public:
void DeleteShmem(const std::string& name) {
SharedMemory mem;
mem.Delete(name);
}
};
TEST_F(StatsTableTest, VerifySlots) {
const std::string kTableName = "VerifySlotsStatTable";
const int kMaxThreads = 1;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
std::string thread_name = "mainThread";
int slot_id = table.RegisterThread(thread_name);
EXPECT_NE(slot_id, 0);
std::string counter_base_name = "counter";
for (int index = 0; index < kMaxCounter; index++) {
std::string counter_name = counter_base_name;
base::StringAppendF(&counter_name, "counter.ctr%d", index);
int counter_id = table.FindCounter(counter_name);
EXPECT_GT(counter_id, 0);
}
slot_id = table.RegisterThread("too many threads");
EXPECT_EQ(slot_id, 0);
int counter_id = table.FindCounter(counter_base_name);
EXPECT_EQ(counter_id, 0);
DeleteShmem(kTableName);
}
const std::string kCounterZero = "CounterZero";
const std::string kCounter1313 = "Counter1313";
const std::string kCounterIncrement = "CounterIncrement";
const std::string kCounterDecrement = "CounterDecrement";
const std::string kCounterMixed = "CounterMixed";
const int kThreadLoops = 100;
class StatsTableThread : public SimpleThread {
public:
StatsTableThread(std::string name, int id)
: SimpleThread(name),
id_(id) {}
virtual void Run() OVERRIDE;
private:
int id_;
};
void StatsTableThread::Run() {
StatsCounter zero_counter(kCounterZero);
StatsCounter lucky13_counter(kCounter1313);
StatsCounter increment_counter(kCounterIncrement);
StatsCounter decrement_counter(kCounterDecrement);
for (int index = 0; index < kThreadLoops; index++) {
StatsCounter mixed_counter(kCounterMixed);
zero_counter.Set(0);
lucky13_counter.Set(1313);
increment_counter.Increment();
decrement_counter.Decrement();
if (id_ % 2)
mixed_counter.Decrement();
else
mixed_counter.Increment();
PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
}
}
#if defined(OS_MACOSX) || defined(THREAD_SANITIZER)
#define MAYBE_MultipleThreads DISABLED_MultipleThreads
#else
#define MAYBE_MultipleThreads MultipleThreads
#endif
TEST_F(StatsTableTest, MAYBE_MultipleThreads) {
const std::string kTableName = "MultipleThreadStatTable";
const int kMaxThreads = 20;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
StatsTable::set_current(&table);
EXPECT_EQ(0, table.CountThreadsRegistered());
StatsTableThread* threads[kMaxThreads];
for (int index = 0; index < kMaxThreads; index++) {
threads[index] = new StatsTableThread("MultipleThreadsTest", index);
threads[index]->Start();
}
for (int index = 0; index < kMaxThreads; index++) {
threads[index]->Join();
delete threads[index];
}
StatsCounter zero_counter(kCounterZero);
StatsCounter lucky13_counter(kCounter1313);
StatsCounter increment_counter(kCounterIncrement);
StatsCounter decrement_counter(kCounterDecrement);
StatsCounter mixed_counter(kCounterMixed);
std::string name;
name = "c:" + kCounterZero;
EXPECT_EQ(0, table.GetCounterValue(name));
name = "c:" + kCounter1313;
EXPECT_EQ(1313 * kMaxThreads,
table.GetCounterValue(name));
name = "c:" + kCounterIncrement;
EXPECT_EQ(kMaxThreads * kThreadLoops,
table.GetCounterValue(name));
name = "c:" + kCounterDecrement;
EXPECT_EQ(-kMaxThreads * kThreadLoops,
table.GetCounterValue(name));
name = "c:" + kCounterMixed;
EXPECT_EQ((kMaxThreads % 2) * kThreadLoops,
table.GetCounterValue(name));
EXPECT_EQ(0, table.CountThreadsRegistered());
DeleteShmem(kTableName);
}
const std::string kMPTableName = "MultipleProcessStatTable";
MULTIPROCESS_TEST_MAIN(StatsTableMultipleProcessMain) {
StatsTable table(kMPTableName, 0, 0);
StatsTable::set_current(&table);
StatsCounter zero_counter(kCounterZero);
StatsCounter lucky13_counter(kCounter1313);
StatsCounter increment_counter(kCounterIncrement);
StatsCounter decrement_counter(kCounterDecrement);
for (int index = 0; index < kThreadLoops; index++) {
zero_counter.Set(0);
lucky13_counter.Set(1313);
increment_counter.Increment();
decrement_counter.Decrement();
PlatformThread::Sleep(TimeDelta::FromMilliseconds(index % 10));
}
return 0;
}
TEST_F(StatsTableTest, DISABLED_MultipleProcesses) {
const int kMaxProcs = 20;
const int kMaxCounter = 5;
DeleteShmem(kMPTableName);
StatsTable table(kMPTableName, kMaxProcs, kMaxCounter);
StatsTable::set_current(&table);
EXPECT_EQ(0, table.CountThreadsRegistered());
ProcessHandle procs[kMaxProcs];
for (int16 index = 0; index < kMaxProcs; index++) {
procs[index] = SpawnChild("StatsTableMultipleProcessMain");
EXPECT_NE(kNullProcessHandle, procs[index]);
}
for (int index = 0; index < kMaxProcs; index++) {
EXPECT_TRUE(WaitForSingleProcess(
procs[index], base::TimeDelta::FromMinutes(1)));
CloseProcessHandle(procs[index]);
}
StatsCounter zero_counter(kCounterZero);
StatsCounter lucky13_counter(kCounter1313);
StatsCounter increment_counter(kCounterIncrement);
StatsCounter decrement_counter(kCounterDecrement);
std::string name;
name = "c:" + kCounterZero;
EXPECT_EQ(0, table.GetCounterValue(name));
name = "c:" + kCounter1313;
EXPECT_EQ(1313 * kMaxProcs,
table.GetCounterValue(name));
name = "c:" + kCounterIncrement;
EXPECT_EQ(kMaxProcs * kThreadLoops,
table.GetCounterValue(name));
name = "c:" + kCounterDecrement;
EXPECT_EQ(-kMaxProcs * kThreadLoops,
table.GetCounterValue(name));
EXPECT_EQ(0, table.CountThreadsRegistered());
DeleteShmem(kMPTableName);
}
class MockStatsCounter : public StatsCounter {
public:
explicit MockStatsCounter(const std::string& name)
: StatsCounter(name) {}
int* Pointer() { return GetPtr(); }
};
TEST_F(StatsTableTest, StatsCounter) {
const std::string kTableName = "StatTable";
const int kMaxThreads = 20;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
StatsTable::set_current(&table);
MockStatsCounter foo("foo");
EXPECT_TRUE(foo.Enabled());
ASSERT_NE(foo.Pointer(), static_cast<int*>(0));
EXPECT_EQ(0, *(foo.Pointer()));
EXPECT_EQ(0, table.GetCounterValue("c:foo"));
while (*(foo.Pointer()) < 123) foo.Increment();
EXPECT_EQ(123, table.GetCounterValue("c:foo"));
foo.Add(0);
EXPECT_EQ(123, table.GetCounterValue("c:foo"));
foo.Add(-1);
EXPECT_EQ(122, table.GetCounterValue("c:foo"));
foo.Set(0);
EXPECT_EQ(0, table.GetCounterValue("c:foo"));
foo.Set(100);
EXPECT_EQ(100, table.GetCounterValue("c:foo"));
foo.Set(-1);
EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
foo.Set(0);
EXPECT_EQ(0, table.GetCounterValue("c:foo"));
foo.Subtract(1);
EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
foo.Subtract(0);
EXPECT_EQ(-1, table.GetCounterValue("c:foo"));
foo.Subtract(-1);
EXPECT_EQ(0, table.GetCounterValue("c:foo"));
DeleteShmem(kTableName);
}
class MockStatsCounterTimer : public StatsCounterTimer {
public:
explicit MockStatsCounterTimer(const std::string& name)
: StatsCounterTimer(name) {}
TimeTicks start_time() { return start_time_; }
TimeTicks stop_time() { return stop_time_; }
};
TEST_F(StatsTableTest, StatsCounterTimer) {
const std::string kTableName = "StatTable";
const int kMaxThreads = 20;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
StatsTable::set_current(&table);
MockStatsCounterTimer bar("bar");
EXPECT_FALSE(bar.Running());
EXPECT_TRUE(bar.start_time().is_null());
EXPECT_TRUE(bar.stop_time().is_null());
const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
bar.Start();
PlatformThread::Sleep(kDuration);
bar.Stop();
EXPECT_GT(table.GetCounterValue("t:bar"), 0);
EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
bar.Start();
PlatformThread::Sleep(kDuration);
bar.Stop();
EXPECT_GT(table.GetCounterValue("t:bar"), 0);
EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
DeleteShmem(kTableName);
}
TEST_F(StatsTableTest, StatsRate) {
const std::string kTableName = "StatTable";
const int kMaxThreads = 20;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
StatsTable::set_current(&table);
StatsRate baz("baz");
EXPECT_FALSE(baz.Running());
EXPECT_EQ(0, table.GetCounterValue("c:baz"));
EXPECT_EQ(0, table.GetCounterValue("t:baz"));
const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
baz.Start();
PlatformThread::Sleep(kDuration);
baz.Stop();
EXPECT_EQ(1, table.GetCounterValue("c:baz"));
EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:baz"));
baz.Start();
PlatformThread::Sleep(kDuration);
baz.Stop();
EXPECT_EQ(2, table.GetCounterValue("c:baz"));
EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:baz"));
DeleteShmem(kTableName);
}
TEST_F(StatsTableTest, StatsScope) {
const std::string kTableName = "StatTable";
const int kMaxThreads = 20;
const int kMaxCounter = 5;
DeleteShmem(kTableName);
StatsTable table(kTableName, kMaxThreads, kMaxCounter);
StatsTable::set_current(&table);
StatsCounterTimer foo("foo");
StatsRate bar("bar");
EXPECT_EQ(0, table.GetCounterValue("t:foo"));
EXPECT_EQ(0, table.GetCounterValue("t:bar"));
EXPECT_EQ(0, table.GetCounterValue("c:bar"));
const TimeDelta kDuration = TimeDelta::FromMilliseconds(100);
{
StatsScope<StatsCounterTimer> timer(foo);
StatsScope<StatsRate> timer2(bar);
PlatformThread::Sleep(kDuration);
}
EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:foo"));
EXPECT_LE(kDuration.InMilliseconds(), table.GetCounterValue("t:bar"));
EXPECT_EQ(1, table.GetCounterValue("c:bar"));
{
StatsScope<StatsCounterTimer> timer(foo);
StatsScope<StatsRate> timer2(bar);
PlatformThread::Sleep(kDuration);
}
EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:foo"));
EXPECT_LE(kDuration.InMilliseconds() * 2, table.GetCounterValue("t:bar"));
EXPECT_EQ(2, table.GetCounterValue("c:bar"));
DeleteShmem(kTableName);
}
}