- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / chrome / performance_logger_unittest.cc
1 // Copyright (c) 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.
4
5 #include "chrome/test/chromedriver/chrome/performance_logger.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/format_macros.h"
9 #include "base/json/json_reader.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "chrome/test/chromedriver/chrome/log.h"
14 #include "chrome/test/chromedriver/chrome/status.h"
15 #include "chrome/test/chromedriver/chrome/stub_devtools_client.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19
20 class FakeDevToolsClient : public StubDevToolsClient {
21  public:
22   explicit FakeDevToolsClient(const std::string& id)
23       : id_(id), listener_(NULL) {}
24   virtual ~FakeDevToolsClient() {}
25
26   std::string PopSentCommand() {
27     std::string command;
28     if (!sent_command_queue_.empty()) {
29       command = sent_command_queue_.front();
30       sent_command_queue_.pop_front();
31     }
32     return command;
33   }
34
35   Status TriggerEvent(const std::string& method) {
36     base::DictionaryValue empty_params;
37     return listener_->OnEvent(this, method, empty_params);
38   }
39
40   // Overridden from DevToolsClient:
41   virtual Status ConnectIfNecessary() OVERRIDE {
42     return listener_->OnConnected(this);
43   }
44
45   virtual Status SendCommandAndGetResult(
46       const std::string& method,
47       const base::DictionaryValue& params,
48       scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
49     sent_command_queue_.push_back(method);
50     return Status(kOk);
51   }
52
53   virtual void AddListener(DevToolsEventListener* listener) OVERRIDE {
54     CHECK(!listener_);
55     listener_ = listener;
56   }
57
58   virtual const std::string& GetId() OVERRIDE {
59     return id_;
60   }
61
62  private:
63   const std::string id_;  // WebView id.
64   std::list<std::string> sent_command_queue_;  // Commands that were sent.
65   DevToolsEventListener* listener_;  // The fake allows only one event listener.
66 };
67
68 struct LogEntry {
69   const base::Time timestamp;
70   const Log::Level level;
71   const std::string source;
72   const std::string message;
73
74   LogEntry(const base::Time& timestamp,
75            Log::Level level,
76            const std::string& source,
77            const std::string& message)
78       : timestamp(timestamp), level(level), source(source), message(message) {}
79 };
80
81 class FakeLog : public Log {
82  public:
83   virtual void AddEntryTimestamped(const base::Time& timestamp,
84                         Level level,
85                         const std::string& source,
86                         const std::string& message) OVERRIDE;
87
88   const ScopedVector<LogEntry>& GetEntries() {
89     return entries_;
90   }
91
92  private:
93   ScopedVector<LogEntry> entries_;
94 };
95
96 void FakeLog::AddEntryTimestamped(const base::Time& timestamp,
97                                   Level level,
98                                   const std::string& source,
99                                   const std::string& message) {
100   entries_.push_back(new LogEntry(timestamp, level, source, message));
101 }
102
103 scoped_ptr<DictionaryValue> ParseDictionary(const std::string& json) {
104   std::string error;
105   scoped_ptr<Value> value(base::JSONReader::ReadAndReturnError(
106       json, base::JSON_PARSE_RFC, NULL, &error));
107   if (value == NULL) {
108     SCOPED_TRACE(json.c_str());
109     SCOPED_TRACE(error.c_str());
110     ADD_FAILURE();
111     return scoped_ptr<DictionaryValue>();
112   }
113   DictionaryValue* dict = NULL;
114   if (!value->GetAsDictionary(&dict)) {
115     SCOPED_TRACE("JSON object is not a dictionary");
116     ADD_FAILURE();
117     return scoped_ptr<DictionaryValue>();
118   }
119   return scoped_ptr<DictionaryValue>(dict->DeepCopy());
120 }
121
122 void ValidateLogEntry(const LogEntry *entry,
123                       const std::string& expected_webview,
124                       const std::string& expected_method) {
125   EXPECT_EQ(Log::kInfo, entry->level);
126   EXPECT_LT(0, entry->timestamp.ToTimeT());
127
128   scoped_ptr<base::DictionaryValue> message(ParseDictionary(entry->message));
129   std::string webview;
130   EXPECT_TRUE(message->GetString("webview", &webview));
131   EXPECT_EQ(expected_webview, webview);
132   std::string method;
133   EXPECT_TRUE(message->GetString("message.method", &method));
134   EXPECT_EQ(expected_method, method);
135   DictionaryValue* params;
136   EXPECT_TRUE(message->GetDictionary("message.params", &params));
137   EXPECT_EQ(0u, params->size());
138 }
139
140 void ExpectEnableDomains(FakeDevToolsClient& client) {
141   EXPECT_EQ("Network.enable", client.PopSentCommand());
142   EXPECT_EQ("Page.enable", client.PopSentCommand());
143   EXPECT_EQ("Timeline.start", client.PopSentCommand());
144   EXPECT_TRUE(client.PopSentCommand().empty());
145 }
146
147 }  // namespace
148
149 TEST(PerformanceLogger, OneWebView) {
150   FakeDevToolsClient client("webview-1");
151   FakeLog log;
152   PerformanceLogger logger(&log);
153
154   client.AddListener(&logger);
155   logger.OnConnected(&client);
156   ExpectEnableDomains(client);
157   ASSERT_EQ(kOk, client.TriggerEvent("Network.gaga").code());
158   ASSERT_EQ(kOk, client.TriggerEvent("Page.ulala").code());
159   // Ignore -- different domain.
160   ASSERT_EQ(kOk, client.TriggerEvent("Console.bad").code());
161
162   ASSERT_EQ(2u, log.GetEntries().size());
163   ValidateLogEntry(log.GetEntries()[0], "webview-1", "Network.gaga");
164   ValidateLogEntry(log.GetEntries()[1], "webview-1", "Page.ulala");
165 }
166
167 TEST(PerformanceLogger, TwoWebViews) {
168   FakeDevToolsClient client1("webview-1");
169   FakeDevToolsClient client2("webview-2");
170   FakeLog log;
171   PerformanceLogger logger(&log);
172
173   client1.AddListener(&logger);
174   client2.AddListener(&logger);
175   logger.OnConnected(&client1);
176   logger.OnConnected(&client2);
177   ExpectEnableDomains(client1);
178   ExpectEnableDomains(client2);
179   // OnConnected sends the enable command only to that client, not others.
180   client1.ConnectIfNecessary();
181   ExpectEnableDomains(client1);
182   EXPECT_TRUE(client2.PopSentCommand().empty());;
183
184   ASSERT_EQ(kOk, client1.TriggerEvent("Page.gaga1").code());
185   ASSERT_EQ(kOk, client2.TriggerEvent("Timeline.gaga2").code());
186
187   ASSERT_EQ(2u, log.GetEntries().size());
188   ValidateLogEntry(log.GetEntries()[0], "webview-1", "Page.gaga1");
189   ValidateLogEntry(log.GetEntries()[1], "webview-2", "Timeline.gaga2");
190 }