Chromium Code Reviews| Index: test/cctest/test-cpu-profiler.cc |
| diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc |
| index 0bf80003f86e0dbbc3fbb053965a38d953b89a5b..c130fccb5718d880da7b60d00d72194c5b9d2124 100644 |
| --- a/test/cctest/test-cpu-profiler.cc |
| +++ b/test/cctest/test-cpu-profiler.cc |
| @@ -30,6 +30,7 @@ |
| #include "v8.h" |
| #include "cpu-profiler-inl.h" |
| #include "cctest.h" |
| +#include "utils.h" |
| #include "../include/v8-profiler.h" |
| using i::CodeEntry; |
| @@ -39,7 +40,9 @@ using i::CpuProfilesCollection; |
| using i::ProfileGenerator; |
| using i::ProfileNode; |
| using i::ProfilerEventsProcessor; |
| +using i::ScopedVector; |
| using i::TokenEnumerator; |
| +using i::Vector; |
| TEST(StartStop) { |
| @@ -399,3 +402,142 @@ TEST(DeleteCpuProfileDifferentTokens) { |
| CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
| CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); |
| } |
| + |
| + |
| +static bool ContainsString(v8::Handle<v8::String> string, |
| + const Vector<v8::Handle<v8::String> >& vector) { |
| + for (int i = 0; i < vector.length(); i++) { |
| + if (string->Equals(vector[i])) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| +static void CheckChildrenNames(const v8::CpuProfileNode* node, |
| + const Vector<v8::Handle<v8::String> >& names) { |
| + int count = node->GetChildrenCount(); |
| + for (int i = 0; i < count; i++) { |
| + v8::Handle<v8::String> name = node->GetChild(i)->GetFunctionName(); |
| + CHECK(ContainsString(name, names)); |
| + // Check that there are no duplicates. |
| + for (int j = 0; j < count; j++) { |
| + if (j == i) continue; |
| + CHECK_NE(name, node->GetChild(j)->GetFunctionName()); |
| + } |
| + } |
| +} |
| + |
| + |
| +static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node, |
| + const char* name) { |
| + int count = node->GetChildrenCount(); |
| + v8::Handle<v8::String> nameHandle = v8::String::New(name); |
| + for (int i = 0; i < count; i++) { |
| + const v8::CpuProfileNode* child = node->GetChild(i); |
| + if (nameHandle->Equals(child->GetFunctionName())) return child; |
| + } |
| + CHECK(false); |
| + return NULL; |
| +} |
| + |
| + |
| +static void CheckSimpleBranch(const v8::CpuProfileNode* node, |
| + const char* names[], int length) { |
| + for (int i = 0; i < length; i++) { |
| + const char* name = names[i]; |
| + node = FindChild(node, name); |
| + CHECK(node); |
| + int expectedChildrenCount = (i == length - 1) ? 0 : 1; |
| + CHECK_EQ(expectedChildrenCount, node->GetChildrenCount()); |
| + } |
| +} |
| + |
| + |
| +static const char* cpu_profiler_test_source = "function loop(n) {\n" |
| +" this.mmm = 0;\n" |
| +" while(n > 1) {\n" |
|
loislo
2013/04/04 09:53:17
it will run non deterministic time.
yurys
2013/04/04 10:21:05
As long as I don't measure exact time spent in thi
|
| +" n--;\n" |
| +" this.mmm += n * n * n;\n" |
| +" }\n" |
| +" return n;\n" |
| +"}\n" |
| +"function delay() { try { loop(100*1000); } catch(e) { } }\n" |
| +"function bar() { delay(); }\n" |
| +"function baz() { delay(); }\n" |
| +"function foo() {\n" |
| +" try {\n" |
| +" delay();\n" |
| +" bar();\n" |
| +" delay();\n" |
| +" baz();\n" |
| +" } catch (e) { }\n" |
| +"}\n" |
| +"function start() {\n" |
| +" var start = Date.now();\n" |
| +" do {\n" |
| +" foo();\n" |
| +" var duration = Date.now() - start;\n" |
| +" } while (duration < 1000);\n" |
| +" return duration;\n" |
| +"}\n"; |
| + |
| + |
| +// Check that the profile tree for the script above will look like the |
| +// following: |
| +// |
| +// [Top down]: |
| +// 1062 0 (root) [-1] |
| +// 1054 0 start [-1] |
| +// 1054 1 foo [-1] |
| +// 265 0 baz [-1] |
| +// 265 1 delay [-1] |
| +// 264 264 loop [-1] |
| +// 525 3 delay [-1] |
| +// 522 522 loop [-1] |
| +// 263 0 bar [-1] |
| +// 263 1 delay [-1] |
| +// 262 262 loop [-1] |
| +// 2 2 (program) [-1] |
| +// 6 6 (garbage collector) [-1] |
| +TEST(CollectCpuProfile) { |
| + LocalContext env; |
| + v8::HandleScope scope(env->GetIsolate()); |
| + |
| + v8::Script::Compile(v8::String::New(cpu_profiler_test_source))->Run(); |
| + v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| + env->Global()->Get(v8::String::New("start"))); |
| + |
| + v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
| + v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
| + |
| + cpu_profiler->StartCpuProfiling(profile_name); |
| + function->Call(env->Global(), 0, 0); |
| + const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
| + |
| + CHECK_NE(NULL, profile); |
| + // Dump collected profile to have a better diagnostic in case of failure. |
| + reinterpret_cast<i::CpuProfile*>( |
| + const_cast<v8::CpuProfile*>(profile))->Print(); |
| + |
| + const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| + |
| + ScopedVector<v8::Handle<v8::String> > names(3); |
| + names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); |
| + names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| + names[2] = v8::String::New("start"); |
| + CheckChildrenNames(root, names); |
| + |
| + const v8::CpuProfileNode* startNode = FindChild(root, "start"); |
| + CHECK_EQ(1, startNode->GetChildrenCount()); |
| + |
| + const v8::CpuProfileNode* fooNode = FindChild(startNode, "foo"); |
| + CHECK_EQ(3, fooNode->GetChildrenCount()); |
| + |
| + const char* barBranch[] = { "bar", "delay", "loop" }; |
| + CheckSimpleBranch(fooNode, barBranch, ARRAY_SIZE(barBranch)); |
| + const char* bazBranch[] = { "baz", "delay", "loop" }; |
| + CheckSimpleBranch(fooNode, bazBranch, ARRAY_SIZE(bazBranch)); |
| + const char* delayBranch[] = { "delay", "loop" }; |
| + CheckSimpleBranch(fooNode, delayBranch, ARRAY_SIZE(delayBranch)); |
| +} |