rippled
TaggedCache_test.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/basics/TaggedCache.h>
21 #include <ripple/basics/chrono.h>
22 #include <ripple/beast/clock/manual_clock.h>
23 #include <ripple/beast/unit_test.h>
24 #include <ripple/protocol/Protocol.h>
25 #include <test/unit_test/SuiteJournal.h>
26 
27 namespace ripple {
28 
29 /*
30 I guess you can put some items in, make sure they're still there. Let some
31 time pass, make sure they're gone. Keep a strong pointer to one of them, make
32 sure you can still find it even after time passes. Create two objects with
33 the same key, canonicalize them both and make sure you get the same object.
34 Put an object in but keep a strong pointer to it, advance the clock a lot,
35 then canonicalize a new object with the same key, make sure you get the
36 original object.
37 */
38 
39 class TaggedCache_test : public beast::unit_test::suite
40 {
41 public:
42  void
43  run() override
44  {
45  using namespace std::chrono_literals;
46  using namespace beast::severities;
47  test::SuiteJournal journal("TaggedCache_test", *this);
48 
49  TestStopwatch clock;
50  clock.set(0);
51 
52  using Key = LedgerIndex;
53  using Value = std::string;
54  using Cache = TaggedCache<Key, Value>;
55 
56  Cache c("test", 1, 1s, clock, journal);
57 
58  // Insert an item, retrieve it, and age it so it gets purged.
59  {
60  BEAST_EXPECT(c.getCacheSize() == 0);
61  BEAST_EXPECT(c.getTrackSize() == 0);
62  BEAST_EXPECT(!c.insert(1, "one"));
63  BEAST_EXPECT(c.getCacheSize() == 1);
64  BEAST_EXPECT(c.getTrackSize() == 1);
65 
66  {
67  std::string s;
68  BEAST_EXPECT(c.retrieve(1, s));
69  BEAST_EXPECT(s == "one");
70  }
71 
72  ++clock;
73  c.sweep();
74  BEAST_EXPECT(c.getCacheSize() == 0);
75  BEAST_EXPECT(c.getTrackSize() == 0);
76  }
77 
78  // Insert an item, maintain a strong pointer, age it, and
79  // verify that the entry still exists.
80  {
81  BEAST_EXPECT(!c.insert(2, "two"));
82  BEAST_EXPECT(c.getCacheSize() == 1);
83  BEAST_EXPECT(c.getTrackSize() == 1);
84 
85  {
86  auto p = c.fetch(2);
87  BEAST_EXPECT(p != nullptr);
88  ++clock;
89  c.sweep();
90  BEAST_EXPECT(c.getCacheSize() == 0);
91  BEAST_EXPECT(c.getTrackSize() == 1);
92  }
93 
94  // Make sure its gone now that our reference is gone
95  ++clock;
96  c.sweep();
97  BEAST_EXPECT(c.getCacheSize() == 0);
98  BEAST_EXPECT(c.getTrackSize() == 0);
99  }
100 
101  // Insert the same key/value pair and make sure we get the same result
102  {
103  BEAST_EXPECT(!c.insert(3, "three"));
104 
105  {
106  auto const p1 = c.fetch(3);
107  auto p2 = std::make_shared<Value>("three");
108  c.canonicalize_replace_client(3, p2);
109  BEAST_EXPECT(p1.get() == p2.get());
110  }
111  ++clock;
112  c.sweep();
113  BEAST_EXPECT(c.getCacheSize() == 0);
114  BEAST_EXPECT(c.getTrackSize() == 0);
115  }
116 
117  // Put an object in but keep a strong pointer to it, advance the clock a
118  // lot, then canonicalize a new object with the same key, make sure you
119  // get the original object.
120  {
121  // Put an object in
122  BEAST_EXPECT(!c.insert(4, "four"));
123  BEAST_EXPECT(c.getCacheSize() == 1);
124  BEAST_EXPECT(c.getTrackSize() == 1);
125 
126  {
127  // Keep a strong pointer to it
128  auto const p1 = c.fetch(4);
129  BEAST_EXPECT(p1 != nullptr);
130  BEAST_EXPECT(c.getCacheSize() == 1);
131  BEAST_EXPECT(c.getTrackSize() == 1);
132  // Advance the clock a lot
133  ++clock;
134  c.sweep();
135  BEAST_EXPECT(c.getCacheSize() == 0);
136  BEAST_EXPECT(c.getTrackSize() == 1);
137  // Canonicalize a new object with the same key
138  auto p2 = std::make_shared<std::string>("four");
139  BEAST_EXPECT(c.canonicalize_replace_client(4, p2));
140  BEAST_EXPECT(c.getCacheSize() == 1);
141  BEAST_EXPECT(c.getTrackSize() == 1);
142  // Make sure we get the original object
143  BEAST_EXPECT(p1.get() == p2.get());
144  }
145 
146  ++clock;
147  c.sweep();
148  BEAST_EXPECT(c.getCacheSize() == 0);
149  BEAST_EXPECT(c.getTrackSize() == 0);
150  }
151  }
152 };
153 
154 BEAST_DEFINE_TESTSUITE(TaggedCache, common, ripple);
155 
156 } // namespace ripple
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:90
std::string
STL class.
ripple::TaggedCache
Map/cache combination.
Definition: Application.h:64
ripple::BEAST_DEFINE_TESTSUITE
BEAST_DEFINE_TESTSUITE(AccountTxPaging, app, ripple)
beast::severities
A namespace for easy access to logging severity values.
Definition: Journal.h:29
ripple::test::SuiteJournal
Definition: SuiteJournal.h:88
ripple::TaggedCache_test
Definition: TaggedCache_test.cpp:39
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
beast::manual_clock< std::chrono::steady_clock >
ripple::TaggedCache_test::run
void run() override
Definition: TaggedCache_test.cpp:43