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.
8 #include "base/memory/scoped_ptr.h"
9 #include "base/values.h"
10 #include "chrome/test/chromedriver/chrome/heap_snapshot_taker.h"
11 #include "chrome/test/chromedriver/chrome/status.h"
12 #include "chrome/test/chromedriver/chrome/stub_devtools_client.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 const char* chunks[] = {"{\"a\": 1,", "\"b\": 2}"};
19 scoped_ptr<base::Value> GetSnapshotAsValue() {
20 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
21 dict->SetInteger("a", 1);
22 dict->SetInteger("b", 2);
23 return dict.PassAs<base::Value>();
26 class DummyDevToolsClient : public StubDevToolsClient {
28 DummyDevToolsClient(const std::string& method, bool error_after_events)
30 error_after_events_(error_after_events),
34 virtual ~DummyDevToolsClient() {}
36 bool IsCleared() { return cleared_; }
38 bool IsDisabled() { return disabled_; }
40 virtual Status SendAddProfileHeaderEvent() {
41 base::DictionaryValue event_params;
42 event_params.SetInteger("header.uid", uid_);
43 return listeners_.front()->OnEvent(
44 this, "HeapProfiler.addProfileHeader", event_params);
47 virtual Status SendAddHeapSnapshotChunkEvent() {
48 base::DictionaryValue event_params;
49 event_params.SetInteger("uid", uid_);
50 for (size_t i = 0; i < arraysize(chunks); ++i) {
51 event_params.SetString("chunk", chunks[i]);
52 Status status = listeners_.front()->OnEvent(
53 this, "HeapProfiler.addHeapSnapshotChunk", event_params);
60 // Overridden from DevToolsClient:
61 virtual Status SendCommand(const std::string& method,
62 const base::DictionaryValue& params) OVERRIDE {
64 cleared_ = method == "HeapProfiler.clearProfiles";
66 disabled_ = method == "Debugger.disable";
67 if (method == method_ && !error_after_events_)
68 return Status(kUnknownError);
70 if (method == "HeapProfiler.takeHeapSnapshot") {
71 Status status = SendAddProfileHeaderEvent();
74 } else if (method == "HeapProfiler.getHeapSnapshot") {
75 Status status = SendAddHeapSnapshotChunkEvent();
80 if (method == method_ && error_after_events_)
81 return Status(kUnknownError);
82 return StubDevToolsClient::SendCommand(method, params);
86 std::string method_; // Throw error on command with this method.
87 bool error_after_events_;
89 bool cleared_; // True if HeapProfiler.clearProfiles was issued.
90 bool disabled_; // True if Debugger.disable was issued.
95 TEST(HeapSnapshotTaker, SuccessfulCase) {
96 DummyDevToolsClient client("", false);
97 HeapSnapshotTaker taker(&client);
98 scoped_ptr<base::Value> snapshot;
99 Status status = taker.TakeSnapshot(&snapshot);
100 ASSERT_EQ(kOk, status.code());
101 ASSERT_TRUE(GetSnapshotAsValue()->Equals(snapshot.get()));
102 ASSERT_TRUE(client.IsCleared());
103 ASSERT_TRUE(client.IsDisabled());
106 TEST(HeapSnapshotTaker, FailIfErrorOnDebuggerEnable) {
107 DummyDevToolsClient client("Debugger.enable", false);
108 HeapSnapshotTaker taker(&client);
109 scoped_ptr<base::Value> snapshot;
110 Status status = taker.TakeSnapshot(&snapshot);
111 ASSERT_TRUE(status.IsError());
112 ASSERT_FALSE(snapshot.get());
113 ASSERT_FALSE(client.IsCleared());
114 ASSERT_TRUE(client.IsDisabled());
117 TEST(HeapSnapshotTaker, FailIfErrorOnCollectGarbage) {
118 DummyDevToolsClient client("HeapProfiler.collectGarbage", false);
119 HeapSnapshotTaker taker(&client);
120 scoped_ptr<base::Value> snapshot;
121 Status status = taker.TakeSnapshot(&snapshot);
122 ASSERT_TRUE(status.IsError());
123 ASSERT_FALSE(snapshot.get());
124 ASSERT_FALSE(client.IsCleared());
125 ASSERT_TRUE(client.IsDisabled());
128 TEST(HeapSnapshotTaker, ErrorBeforeReceivingUid) {
129 DummyDevToolsClient client("HeapProfiler.takeHeapSnapshot", false);
130 HeapSnapshotTaker taker(&client);
131 scoped_ptr<base::Value> snapshot;
132 Status status = taker.TakeSnapshot(&snapshot);
133 ASSERT_TRUE(status.IsError());
134 ASSERT_FALSE(snapshot.get());
135 ASSERT_FALSE(client.IsCleared());
136 ASSERT_TRUE(client.IsDisabled());
139 TEST(HeapSnapshotTaker, ErrorAfterReceivingUid) {
140 DummyDevToolsClient client("HeapProfiler.takeHeapSnapshot", true);
141 HeapSnapshotTaker taker(&client);
142 scoped_ptr<base::Value> snapshot;
143 Status status = taker.TakeSnapshot(&snapshot);
144 ASSERT_TRUE(status.IsError());
145 ASSERT_FALSE(snapshot.get());
146 ASSERT_TRUE(client.IsCleared());
147 ASSERT_TRUE(client.IsDisabled());
152 class TwoUidEventClient : public DummyDevToolsClient {
154 TwoUidEventClient() : DummyDevToolsClient("", false) {}
155 virtual ~TwoUidEventClient() {}
157 // Overridden from DummyDevToolsClient:
158 virtual Status SendAddProfileHeaderEvent() OVERRIDE {
159 Status status = DummyDevToolsClient::SendAddProfileHeaderEvent();
160 if (status.IsError())
163 status = DummyDevToolsClient::SendAddProfileHeaderEvent();
171 TEST(HeapSnapshotTaker, MuiltipleUidEvents) {
172 TwoUidEventClient client;
173 HeapSnapshotTaker taker(&client);
174 scoped_ptr<base::Value> snapshot;
175 Status status = taker.TakeSnapshot(&snapshot);
176 ASSERT_EQ(kOk, status.code());
177 ASSERT_TRUE(GetSnapshotAsValue()->Equals(snapshot.get()));
178 ASSERT_TRUE(client.IsCleared());
179 ASSERT_TRUE(client.IsDisabled());
184 class ChunkWithDifferentUidClient : public DummyDevToolsClient {
186 ChunkWithDifferentUidClient() : DummyDevToolsClient("", false) {}
187 virtual ~ChunkWithDifferentUidClient() {}
189 // Overridden from DummyDevToolsClient:
190 virtual Status SendAddHeapSnapshotChunkEvent() OVERRIDE {
191 Status status = DummyDevToolsClient::SendAddHeapSnapshotChunkEvent();
192 if (status.IsError())
195 status = DummyDevToolsClient::SendAddHeapSnapshotChunkEvent();
203 TEST(HeapSnapshotTaker, IgnoreChunkWithDifferentUid) {
204 ChunkWithDifferentUidClient client;
205 HeapSnapshotTaker taker(&client);
206 scoped_ptr<base::Value> snapshot;
207 Status status = taker.TakeSnapshot(&snapshot);
208 ASSERT_EQ(kOk, status.code());
209 ASSERT_TRUE(GetSnapshotAsValue()->Equals(snapshot.get()));
210 ASSERT_TRUE(client.IsCleared());
211 ASSERT_TRUE(client.IsDisabled());
214 TEST(HeapSnapshotTaker, ErrorAfterFinishEvent) {
215 DummyDevToolsClient client("HeapProfiler.getHeapSnapshot", true);
216 HeapSnapshotTaker taker(&client);
217 scoped_ptr<base::Value> snapshot;
218 Status status = taker.TakeSnapshot(&snapshot);
219 ASSERT_TRUE(status.IsError());
220 ASSERT_FALSE(snapshot.get());
221 ASSERT_TRUE(client.IsCleared());
222 ASSERT_TRUE(client.IsDisabled());