Home | History | Annotate | Download | only in chrome
      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/console_logger.h"
      6 
      7 #include "base/compiler_specific.h"
      8 #include "base/format_macros.h"
      9 #include "base/memory/scoped_vector.h"
     10 #include "base/time/time.h"
     11 #include "base/values.h"
     12 #include "chrome/test/chromedriver/chrome/log.h"
     13 #include "chrome/test/chromedriver/chrome/status.h"
     14 #include "chrome/test/chromedriver/chrome/stub_devtools_client.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 namespace {
     18 
     19 class FakeDevToolsClient : public StubDevToolsClient {
     20  public:
     21   explicit FakeDevToolsClient(const std::string& id)
     22       : id_(id), listener_(NULL) {}
     23   virtual ~FakeDevToolsClient() {}
     24 
     25   std::string PopSentCommand() {
     26     std::string command;
     27     if (!sent_command_queue_.empty()) {
     28       command = sent_command_queue_.front();
     29       sent_command_queue_.pop_front();
     30     }
     31     return command;
     32   }
     33 
     34   Status TriggerEvent(const std::string& method,
     35                     const base::DictionaryValue& params) {
     36     return listener_->OnEvent(this, method, params);
     37   }
     38 
     39   // Overridden from DevToolsClient:
     40   virtual Status ConnectIfNecessary() OVERRIDE {
     41     return listener_->OnConnected(this);
     42   }
     43 
     44   virtual Status SendCommandAndGetResult(
     45       const std::string& method,
     46       const base::DictionaryValue& params,
     47       scoped_ptr<base::DictionaryValue>* result) OVERRIDE {
     48     sent_command_queue_.push_back(method);
     49     return Status(kOk);
     50   }
     51 
     52   virtual void AddListener(DevToolsEventListener* listener) OVERRIDE {
     53     CHECK(!listener_);
     54     listener_ = listener;
     55   }
     56 
     57   virtual const std::string& GetId() OVERRIDE {
     58     return id_;
     59   }
     60 
     61  private:
     62   const std::string id_;  // WebView id.
     63   std::list<std::string> sent_command_queue_;  // Commands that were sent.
     64   DevToolsEventListener* listener_;  // The fake allows only one event listener.
     65 };
     66 
     67 struct LogEntry {
     68   const base::Time timestamp;
     69   const Log::Level level;
     70   const std::string source;
     71   const std::string message;
     72 
     73   LogEntry(const base::Time& timestamp,
     74            Log::Level level,
     75            const std::string& source,
     76            const std::string& message)
     77       : timestamp(timestamp), level(level), source(source), message(message) {}
     78 };
     79 
     80 class FakeLog : public Log {
     81  public:
     82   virtual void AddEntryTimestamped(const base::Time& timestamp,
     83                                    Level level,
     84                                    const std::string& source,
     85                                    const std::string& message) OVERRIDE;
     86 
     87   const ScopedVector<LogEntry>& GetEntries() {
     88     return entries_;
     89   }
     90 
     91 private:
     92   ScopedVector<LogEntry> entries_;
     93 };
     94 
     95 void FakeLog::AddEntryTimestamped(const base::Time& timestamp,
     96                                   Level level,
     97                                   const std::string& source,
     98                                   const std::string& message) {
     99   entries_.push_back(new LogEntry(timestamp, level, source, message));
    100 }
    101 
    102 void ValidateLogEntry(const LogEntry *entry,
    103                       Log::Level expected_level,
    104                       const std::string& expected_source,
    105                       const std::string& expected_message) {
    106   EXPECT_EQ(expected_level, entry->level);
    107   EXPECT_EQ(expected_source, entry->source);
    108   EXPECT_LT(0, entry->timestamp.ToTimeT());
    109   EXPECT_EQ(expected_message, entry->message);
    110 }
    111 
    112 void ConsoleLogParams(base::DictionaryValue* out_params,
    113                       const char* source,
    114                       const char* url,
    115                       const char* level,
    116                       int line,
    117                       int column,
    118                       const char* text) {
    119   if (source != NULL)
    120     out_params->SetString("message.source", source);
    121   if (url != NULL)
    122     out_params->SetString("message.url", url);
    123   if (level != NULL)
    124     out_params->SetString("message.level", level);
    125   if (line != -1)
    126     out_params->SetInteger("message.line", line);
    127   if (column != -1)
    128     out_params->SetInteger("message.column", column);
    129   if (text != NULL)
    130     out_params->SetString("message.text", text);
    131 }
    132 
    133 }  // namespace
    134 
    135 TEST(ConsoleLogger, ConsoleMessages) {
    136   FakeDevToolsClient client("webview");
    137   FakeLog log;
    138   ConsoleLogger logger(&log);
    139 
    140   client.AddListener(&logger);
    141   logger.OnConnected(&client);
    142   EXPECT_EQ("Console.enable", client.PopSentCommand());
    143   EXPECT_TRUE(client.PopSentCommand().empty());
    144 
    145   base::DictionaryValue params1;  // All fields are set.
    146   ConsoleLogParams(&params1, "source1", "url1", "debug", 10, 1, "text1");
    147   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params1).code());
    148   // Ignored -- wrong method.
    149   ASSERT_EQ(kOk, client.TriggerEvent("Console.gaga", params1).code());
    150 
    151   base::DictionaryValue params2;  // All optionals are not set.
    152   ConsoleLogParams(&params2, "source2", NULL, "log", -1, -1, "text2");
    153   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params2).code());
    154 
    155   base::DictionaryValue params3;  // Line without column, no source.
    156   ConsoleLogParams(&params3, NULL, "url3", "warning", 30, -1, "text3");
    157   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params3).code());
    158 
    159   base::DictionaryValue params4;  // Column without line.
    160   ConsoleLogParams(&params4, "source4", "url4", "error", -1, 4, "text4");
    161   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params4).code());
    162 
    163   base::DictionaryValue params5;  // Bad level name.
    164   ConsoleLogParams(&params5, "source5", "url5", "gaga", 50, 5, "ulala");
    165   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params5).code());
    166 
    167   base::DictionaryValue params6;  // Unset level.
    168   ConsoleLogParams(&params6, "source6", "url6", NULL, 60, 6, NULL);
    169   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params6).code());
    170 
    171   base::DictionaryValue params7;  // No text.
    172   ConsoleLogParams(&params7, "source7", "url7", "log", -1, -1, NULL);
    173   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params7).code());
    174 
    175   base::DictionaryValue params8;  // No message object.
    176   params8.SetInteger("gaga", 8);
    177   ASSERT_EQ(kOk, client.TriggerEvent("Console.messageAdded", params8).code());
    178 
    179   EXPECT_TRUE(client.PopSentCommand().empty());  // No other commands sent.
    180 
    181   ASSERT_EQ(8u, log.GetEntries().size());
    182   ValidateLogEntry(log.GetEntries()[0], Log::kDebug, "source1",
    183                    "url1 10:1 text1");
    184   ValidateLogEntry(log.GetEntries()[1], Log::kInfo, "source2",
    185                    "source2 - text2");
    186   ValidateLogEntry(log.GetEntries()[2], Log::kWarning, "", "url3 30 text3");
    187   ValidateLogEntry(log.GetEntries()[3], Log::kError, "source4",
    188                    "url4 - text4");
    189   ValidateLogEntry(
    190       log.GetEntries()[4], Log::kWarning, "",
    191       "{\"message\":{\"column\":5,\"level\":\"gaga\",\"line\":50,"
    192       "\"source\":\"source5\",\"text\":\"ulala\",\"url\":\"url5\"}}");
    193   ValidateLogEntry(
    194       log.GetEntries()[5], Log::kWarning, "",
    195       "{\"message\":{\"column\":6,\"line\":60,"
    196       "\"source\":\"source6\",\"url\":\"url6\"}}");
    197   ValidateLogEntry(
    198       log.GetEntries()[6], Log::kWarning, "",
    199       "{\"message\":{\"level\":\"log\","
    200       "\"source\":\"source7\",\"url\":\"url7\"}}");
    201   ValidateLogEntry(log.GetEntries()[7], Log::kWarning, "", "{\"gaga\":8}");
    202 }
    203