| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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/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<base::DictionaryValue> ParseDictionary(const std::string& json) { | |
| 104 std::string error; | |
| 105 scoped_ptr<base::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<base::DictionaryValue>(); | |
| 112 } | |
| 113 base::DictionaryValue* dict = NULL; | |
| 114 if (!value->GetAsDictionary(&dict)) { | |
| 115 SCOPED_TRACE("JSON object is not a dictionary"); | |
| 116 ADD_FAILURE(); | |
| 117 return scoped_ptr<base::DictionaryValue>(); | |
| 118 } | |
| 119 return scoped_ptr<base::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 base::DictionaryValue* params; | |
| 136 EXPECT_TRUE(message->GetDictionary("message.params", ¶ms)); | |
| 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 } | |
| OLD | NEW |