Lalit Maganti | 8eba309 | 2019-03-27 13:25:29 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "src/trace_processor/string_pool.h" |
| 18 | |
| 19 | #include <random> |
| 20 | |
| 21 | #include "gtest/gtest.h" |
| 22 | |
| 23 | namespace perfetto { |
| 24 | namespace trace_processor { |
| 25 | namespace { |
| 26 | |
| 27 | TEST(StringPoolTest, EmptyPool) { |
| 28 | StringPool pool; |
| 29 | |
| 30 | ASSERT_EQ(pool.Get(0).c_str(), nullptr); |
| 31 | |
| 32 | auto it = pool.CreateIterator(); |
| 33 | ASSERT_TRUE(it); |
| 34 | ASSERT_EQ(it.StringView().c_str(), nullptr); |
| 35 | ASSERT_FALSE(++it); |
| 36 | } |
| 37 | |
| 38 | TEST(StringPoolTest, InternAndRetrieve) { |
| 39 | StringPool pool; |
| 40 | |
| 41 | static char kString[] = "Test String"; |
| 42 | auto id = pool.InternString(kString); |
| 43 | ASSERT_STREQ(pool.Get(id).c_str(), kString); |
| 44 | ASSERT_EQ(pool.Get(id), kString); |
| 45 | ASSERT_EQ(id, pool.InternString(kString)); |
| 46 | } |
| 47 | |
| 48 | TEST(StringPoolTest, NullPointerHandling) { |
| 49 | StringPool pool; |
| 50 | |
| 51 | auto id = pool.InternString(NullTermStringView()); |
| 52 | ASSERT_EQ(id, 0); |
| 53 | ASSERT_EQ(pool.Get(id).c_str(), nullptr); |
| 54 | } |
| 55 | |
| 56 | TEST(StringPoolTest, Iterator) { |
| 57 | StringPool pool; |
| 58 | |
| 59 | auto it = pool.CreateIterator(); |
| 60 | ASSERT_TRUE(it); |
| 61 | ASSERT_EQ(it.StringView().c_str(), nullptr); |
| 62 | ASSERT_FALSE(++it); |
| 63 | |
| 64 | static char kString[] = "Test String"; |
| 65 | pool.InternString(kString); |
| 66 | |
| 67 | it = pool.CreateIterator(); |
| 68 | ASSERT_TRUE(++it); |
| 69 | ASSERT_STREQ(it.StringView().c_str(), kString); |
| 70 | ASSERT_FALSE(++it); |
| 71 | } |
| 72 | |
Mikhail Khokhlov | f0b8dab | 2019-05-02 12:51:14 +0100 | [diff] [blame] | 73 | TEST(StringPoolTest, ConstIterator) { |
| 74 | StringPool pool; |
| 75 | static char kString[] = "Test String"; |
| 76 | pool.InternString(kString); |
| 77 | |
| 78 | const StringPool& const_pool = pool; |
| 79 | |
| 80 | auto it = const_pool.CreateIterator(); |
| 81 | ASSERT_TRUE(it); |
| 82 | ASSERT_TRUE(++it); |
| 83 | ASSERT_STREQ(it.StringView().c_str(), kString); |
| 84 | ASSERT_FALSE(++it); |
| 85 | } |
| 86 | |
Lalit Maganti | 8eba309 | 2019-03-27 13:25:29 +0000 | [diff] [blame] | 87 | TEST(StringPoolTest, StressTest) { |
Lalit Maganti | d63ec5a | 2019-03-28 13:55:56 +0000 | [diff] [blame] | 88 | // First create a buffer with 8MB of random characters. |
| 89 | constexpr size_t kBufferSize = 8 * 1024 * 1024; |
Lalit Maganti | 8eba309 | 2019-03-27 13:25:29 +0000 | [diff] [blame] | 90 | std::minstd_rand0 rnd_engine(0); |
| 91 | std::unique_ptr<char[]> buffer(new char[kBufferSize]); |
| 92 | for (size_t i = 0; i < kBufferSize; i++) |
| 93 | buffer.get()[i] = 'A' + (rnd_engine() % 26); |
| 94 | |
| 95 | // Next create strings of length 0 to 16k in length from this buffer and |
| 96 | // intern them, storing their ids. |
| 97 | StringPool pool; |
| 98 | std::multimap<StringPool::Id, base::StringView> string_map; |
| 99 | constexpr uint16_t kMaxStrSize = 16u * 1024u - 1; |
| 100 | for (size_t i = 0;;) { |
| 101 | size_t length = static_cast<uint64_t>(rnd_engine()) % (kMaxStrSize + 1); |
| 102 | if (i + length > kBufferSize) |
| 103 | break; |
| 104 | |
| 105 | auto str = base::StringView(&buffer.get()[i], length); |
| 106 | string_map.emplace(pool.InternString(str), str); |
| 107 | i += length; |
| 108 | } |
| 109 | |
| 110 | // Finally, iterate through each string in the string pool, check that all ids |
| 111 | // that match in the multimap are equal, and finish by checking we've removed |
| 112 | // every item in the multimap. |
| 113 | for (auto it = pool.CreateIterator(); it; ++it) { |
| 114 | ASSERT_EQ(it.StringView(), pool.Get(it.StringId())); |
| 115 | |
| 116 | auto it_pair = string_map.equal_range(it.StringId()); |
| 117 | for (auto in_it = it_pair.first; in_it != it_pair.second; ++in_it) { |
| 118 | ASSERT_EQ(it.StringView(), in_it->second); |
| 119 | } |
| 120 | string_map.erase(it_pair.first, it_pair.second); |
| 121 | } |
| 122 | ASSERT_EQ(string_map.size(), 0); |
| 123 | } |
| 124 | |
| 125 | } // namespace |
| 126 | } // namespace trace_processor |
| 127 | } // namespace perfetto |