1// Copyright (c) 2012 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 "base/values.h"
6#include "base/memory/scoped_ptr.h"
7#include "chrome/browser/prerender/prerender_history.h"
8#include "testing/gtest/include/gtest/gtest.h"
9
10namespace prerender {
11
12namespace {
13
14bool ListEntryMatches(base::ListValue* list,
15                      size_t index,
16                      const char* expected_url,
17                      FinalStatus expected_final_status,
18                      Origin expected_origin,
19                      const std::string& expected_end_time) {
20  if (index >= list->GetSize())
21    return false;
22  base::DictionaryValue* dict = NULL;
23  if (!list->GetDictionary(index, &dict))
24    return false;
25  if (dict->size() != 4u)
26    return false;
27  std::string url;
28  if (!dict->GetString("url", &url))
29    return false;
30  if (url != expected_url)
31    return false;
32  std::string final_status;
33  if (!dict->GetString("final_status", &final_status))
34    return false;
35  if (final_status != NameFromFinalStatus(expected_final_status))
36    return false;
37  std::string origin;
38  if (!dict->GetString("origin", &origin))
39    return false;
40  if (origin != NameFromOrigin(expected_origin))
41    return false;
42  std::string end_time;
43  if (!dict->GetString("end_time", &end_time))
44    return false;
45  if (end_time != expected_end_time)
46    return false;
47  return true;
48}
49
50TEST(PrerenderHistoryTest, GetAsValue)  {
51  scoped_ptr<base::Value> entry_value;
52  base::ListValue* entry_list = NULL;
53
54  // Create a history with only 2 values.
55  PrerenderHistory history(2);
56
57  // Make sure an empty list exists when retrieving as value.
58  entry_value.reset(history.GetEntriesAsValue());
59  ASSERT_TRUE(entry_value.get() != NULL);
60  ASSERT_TRUE(entry_value->GetAsList(&entry_list));
61  EXPECT_TRUE(entry_list->empty());
62
63  // Base time used for all events.  Each event is given a time 1 millisecond
64  // after that of the previous one.
65  base::Time epoch_start = base::Time::UnixEpoch();
66
67  // Add a single entry and make sure that it matches up.
68  const char* const kFirstUrl = "http://www.alpha.com/";
69  const FinalStatus kFirstFinalStatus = FINAL_STATUS_USED;
70  const Origin kFirstOrigin = ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN;
71  PrerenderHistory::Entry entry_first(
72      GURL(kFirstUrl), kFirstFinalStatus, kFirstOrigin, epoch_start);
73  history.AddEntry(entry_first);
74  entry_value.reset(history.GetEntriesAsValue());
75  ASSERT_TRUE(entry_value.get() != NULL);
76  ASSERT_TRUE(entry_value->GetAsList(&entry_list));
77  EXPECT_EQ(1u, entry_list->GetSize());
78  EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kFirstUrl, kFirstFinalStatus,
79                               kFirstOrigin, "0"));
80
81  // Add a second entry and make sure both first and second appear.
82  const char* const kSecondUrl = "http://www.beta.com/";
83  const FinalStatus kSecondFinalStatus = FINAL_STATUS_INVALID_HTTP_METHOD;
84  const Origin kSecondOrigin = ORIGIN_OMNIBOX;
85  PrerenderHistory::Entry entry_second(
86      GURL(kSecondUrl), kSecondFinalStatus, kSecondOrigin,
87      epoch_start + base::TimeDelta::FromMilliseconds(1));
88  history.AddEntry(entry_second);
89  entry_value.reset(history.GetEntriesAsValue());
90  ASSERT_TRUE(entry_value.get() != NULL);
91  ASSERT_TRUE(entry_value->GetAsList(&entry_list));
92  EXPECT_EQ(2u, entry_list->GetSize());
93  EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kSecondUrl, kSecondFinalStatus,
94                               kSecondOrigin, "1"));
95  EXPECT_TRUE(ListEntryMatches(entry_list, 1u, kFirstUrl, kFirstFinalStatus,
96                               kFirstOrigin, "0"));
97
98  // Add a third entry and make sure that the first one drops off.
99  const char* const kThirdUrl = "http://www.gamma.com/";
100  const FinalStatus kThirdFinalStatus = FINAL_STATUS_AUTH_NEEDED;
101  const Origin kThirdOrigin = ORIGIN_LINK_REL_PRERENDER_CROSSDOMAIN;
102  PrerenderHistory::Entry entry_third(
103      GURL(kThirdUrl), kThirdFinalStatus, kThirdOrigin,
104      epoch_start + base::TimeDelta::FromMilliseconds(2));
105  history.AddEntry(entry_third);
106  entry_value.reset(history.GetEntriesAsValue());
107  ASSERT_TRUE(entry_value.get() != NULL);
108  ASSERT_TRUE(entry_value->GetAsList(&entry_list));
109  EXPECT_EQ(2u, entry_list->GetSize());
110  EXPECT_TRUE(ListEntryMatches(entry_list, 0u, kThirdUrl, kThirdFinalStatus,
111                               kThirdOrigin, "2"));
112  EXPECT_TRUE(ListEntryMatches(entry_list, 1u, kSecondUrl, kSecondFinalStatus,
113                               kSecondOrigin, "1"));
114
115  // Make sure clearing history acts as expected.
116  history.Clear();
117  entry_value.reset(history.GetEntriesAsValue());
118  ASSERT_TRUE(entry_value.get() != NULL);
119  ASSERT_TRUE(entry_value->GetAsList(&entry_list));
120  EXPECT_TRUE(entry_list->empty());
121}
122
123}  // namespace
124
125}  // namespace prerender
126