Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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/bind.h" | |
| 6 #include "base/run_loop.h" | |
| 7 #include "base/time/time.h" | |
| 8 #include "content/public/test/test_browser_thread_bundle.h" | |
| 9 #include "extensions/browser/extension_api_frame_id_map.h" | |
| 10 #include "testing/gtest/include/gtest/gtest.h" | |
| 11 | |
| 12 using FrameIdCallback = extensions::ExtensionApiFrameIdMap::FrameIdCallback; | |
| 13 | |
| 14 namespace extensions { | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 ExtensionApiFrameId ToTestFrameId(int render_process_id, int frame_routing_id) { | |
| 19 if (render_process_id == -1 && frame_routing_id == -1) | |
| 20 return ExtensionApiFrameId(); | |
| 21 // Return a deterministic value (yet different from the input) for testing. | |
| 22 return ExtensionApiFrameId(render_process_id + 1, frame_routing_id + 1); | |
| 23 } | |
| 24 | |
| 25 class TestExtensionApiFrameIdMap : public ExtensionApiFrameIdMap { | |
| 26 public: | |
| 27 int GetInternalSize() { return frame_id_map_.size(); } | |
| 28 int GetInternalCallbackCount() { return callbacks_.size(); } | |
| 29 void TriggerInternalCleanup() { | |
| 30 // Modify the internal structure: Set the creation time to a time in the | |
| 31 // distant past and trigger a removal. | |
| 32 for (FrameIdRemovalTask& task : pending_deletions_) | |
| 33 task.creation_time = base::TimeTicks(); | |
| 34 // The map cannot have invalid frame IDs, so this is a no-op. | |
| 35 RemoveFrameId(-1, -1); | |
| 36 // The only remaining task is the removal of the invalid ID above, all other | |
| 37 // pending deletion tasks should have been run by now. | |
| 38 EXPECT_EQ(1u, pending_deletions_.size()); | |
| 39 } | |
| 40 | |
| 41 private: | |
| 42 // ExtensionApiFrameIdMap: | |
| 43 ExtensionApiFrameId KeyToValue(const RenderFrameIdKey& key) const override { | |
| 44 return ToTestFrameId(key.render_process_id, key.frame_routing_id); | |
| 45 } | |
| 46 }; | |
| 47 | |
| 48 class ExtensionApiFrameIdMapTest : public testing::Test { | |
| 49 public: | |
| 50 ExtensionApiFrameIdMapTest() | |
| 51 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} | |
| 52 | |
| 53 FrameIdCallback CreateCallback(int render_process_id, int frame_routing_id) { | |
| 54 return base::Bind(&ExtensionApiFrameIdMapTest::OnCalledCallback, | |
| 55 base::Unretained(this), render_process_id, | |
| 56 frame_routing_id); | |
| 57 } | |
| 58 | |
| 59 void OnCalledCallback(int render_process_id, | |
| 60 int frame_routing_id, | |
| 61 const ExtensionApiFrameId extension_api_frame_id) { | |
| 62 // Save results for later, to see whether the ordering is OK. | |
| 63 results_.push_back(extension_api_frame_id); | |
| 64 | |
| 65 // If this fails, then the mapping is completely wrong. | |
| 66 EXPECT_EQ(ToTestFrameId(render_process_id, frame_routing_id), | |
| 67 extension_api_frame_id); | |
| 68 } | |
| 69 | |
| 70 const std::vector<ExtensionApiFrameId>& results() { return results_; } | |
| 71 | |
| 72 private: | |
| 73 content::TestBrowserThreadBundle thread_bundle_; | |
| 74 std::vector<ExtensionApiFrameId> results_; | |
| 75 | |
| 76 DISALLOW_COPY_AND_ASSIGN(ExtensionApiFrameIdMapTest); | |
| 77 }; | |
| 78 | |
| 79 } // namespace | |
| 80 | |
| 81 // Tests whether getting data from the map gives consistent results. | |
| 82 TEST_F(ExtensionApiFrameIdMapTest, Basics) { | |
| 83 scoped_ptr<TestExtensionApiFrameIdMap> map(new TestExtensionApiFrameIdMap()); | |
|
nasko
2015/12/22 22:12:10
Why not move this to be a member of the test class
| |
| 84 EXPECT_EQ(0, map->GetInternalSize()); | |
| 85 | |
| 86 EXPECT_EQ(ToTestFrameId(1, 2), map->GetFrameId(1, 2)); | |
| 87 EXPECT_EQ(1, map->GetInternalSize()); | |
| 88 | |
| 89 // Already cached, the map size should not change. | |
| 90 EXPECT_EQ(ToTestFrameId(1, 2), map->GetFrameId(1, 2)); | |
| 91 EXPECT_EQ(1, map->GetInternalSize()); | |
| 92 | |
| 93 EXPECT_EQ(ToTestFrameId(2, 1), map->GetFrameId(2, 1)); | |
| 94 EXPECT_EQ(2, map->GetInternalSize()); | |
| 95 | |
| 96 // Don't save invalid values in the map because they are never deleted. | |
| 97 EXPECT_EQ(ToTestFrameId(-1, -1), map->GetFrameId(-1, -1)); | |
| 98 EXPECT_EQ(2, map->GetInternalSize()); | |
| 99 | |
| 100 // Remove frame ID. Key erasure is not immediate but delayed. | |
| 101 map->RemoveFrameId(1, 2); | |
| 102 EXPECT_EQ(2, map->GetInternalSize()); | |
| 103 map->TriggerInternalCleanup(); | |
| 104 EXPECT_EQ(1, map->GetInternalSize()); | |
|
nasko
2015/12/22 22:12:10
If the map moves to be a class member, then you ca
| |
| 105 | |
| 106 // Non-existing frame ID. | |
| 107 map->RemoveFrameId(1, 1337); | |
| 108 EXPECT_EQ(1, map->GetInternalSize()); | |
| 109 map->TriggerInternalCleanup(); | |
| 110 EXPECT_EQ(1, map->GetInternalSize()); | |
| 111 | |
| 112 // Non-existing frame ID (because it's already removed). | |
| 113 map->RemoveFrameId(1, 2); | |
| 114 EXPECT_EQ(1, map->GetInternalSize()); | |
| 115 map->TriggerInternalCleanup(); | |
| 116 EXPECT_EQ(1, map->GetInternalSize()); | |
| 117 | |
| 118 // Invalid frame ID. | |
| 119 map->RemoveFrameId(-1, -1); | |
| 120 EXPECT_EQ(1, map->GetInternalSize()); | |
| 121 map->TriggerInternalCleanup(); | |
| 122 EXPECT_EQ(1, map->GetInternalSize()); | |
| 123 } | |
| 124 | |
| 125 TEST_F(ExtensionApiFrameIdMapTest, GetFrameIdOnIO) { | |
| 126 scoped_ptr<TestExtensionApiFrameIdMap> map(new TestExtensionApiFrameIdMap()); | |
| 127 EXPECT_EQ(0, map->GetInternalSize()); | |
| 128 | |
| 129 // Two identical calls, should be processed at the next message loop. | |
| 130 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 131 EXPECT_EQ(1, map->GetInternalCallbackCount()); | |
| 132 EXPECT_EQ(0, map->GetInternalSize()); | |
| 133 | |
| 134 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 135 EXPECT_EQ(2, map->GetInternalCallbackCount()); | |
| 136 EXPECT_EQ(0, map->GetInternalSize()); | |
| 137 | |
| 138 // First get the frame ID on IO (queued on message loop), then on UI. | |
| 139 map->GetFrameIdOnIO(2, 1, CreateCallback(2, 1)); | |
| 140 EXPECT_EQ(3, map->GetInternalCallbackCount()); | |
| 141 EXPECT_EQ(0, map->GetInternalSize()); | |
| 142 | |
| 143 EXPECT_EQ(ToTestFrameId(2, 1), map->GetFrameId(2, 1)); | |
| 144 EXPECT_EQ(1, map->GetInternalSize()); | |
| 145 | |
| 146 // First get the frame ID on UI, then on IO (queued on message loop). | |
| 147 EXPECT_EQ(ToTestFrameId(3, 1), map->GetFrameId(3, 1)); | |
| 148 EXPECT_EQ(2, map->GetInternalSize()); | |
| 149 | |
| 150 map->GetFrameIdOnIO(3, 1, CreateCallback(3, 1)); | |
| 151 EXPECT_EQ(4, map->GetInternalCallbackCount()); | |
| 152 EXPECT_EQ(2, map->GetInternalSize()); | |
| 153 | |
| 154 // A call identical to the very first call. | |
| 155 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 156 EXPECT_EQ(5, map->GetInternalCallbackCount()); | |
| 157 EXPECT_EQ(2, map->GetInternalSize()); | |
| 158 | |
| 159 base::RunLoop().RunUntilIdle(); | |
| 160 EXPECT_EQ(0, map->GetInternalCallbackCount()); | |
| 161 | |
| 162 EXPECT_EQ(3, map->GetInternalSize()); | |
| 163 EXPECT_EQ(5U, results().size()); | |
| 164 | |
| 165 // Callbacks should be run in order. | |
| 166 EXPECT_EQ(ToTestFrameId(1, 2), results()[0]); | |
| 167 EXPECT_EQ(ToTestFrameId(1, 2), results()[1]); | |
| 168 EXPECT_EQ(ToTestFrameId(2, 1), results()[2]); | |
| 169 EXPECT_EQ(ToTestFrameId(3, 1), results()[3]); | |
| 170 EXPECT_EQ(ToTestFrameId(1, 2), results()[4]); | |
| 171 | |
| 172 // Request the frame ID for input that was already looked up. Should complete | |
| 173 // synchronously. | |
| 174 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 175 EXPECT_EQ(0, map->GetInternalCallbackCount()); | |
| 176 EXPECT_EQ(3, map->GetInternalSize()); | |
| 177 EXPECT_EQ(6U, results().size()); | |
| 178 EXPECT_EQ(ToTestFrameId(1, 2), results()[5]); | |
| 179 | |
| 180 // Queue frame removal and look up frame ID. Frame ID should not be removed | |
| 181 // yet and GetFrameIdOnIO() should complete synchronously. | |
| 182 map->RemoveFrameId(1, 2); | |
| 183 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 184 EXPECT_EQ(0, map->GetInternalCallbackCount()); | |
| 185 EXPECT_EQ(3, map->GetInternalSize()); | |
| 186 EXPECT_EQ(7U, results().size()); | |
| 187 EXPECT_EQ(ToTestFrameId(1, 2), results()[6]); | |
| 188 | |
| 189 // Now fire the timer that triggers frame removal, and request the frame ID. | |
| 190 // Thread hopping should be necessary again. | |
| 191 map->TriggerInternalCleanup(); | |
| 192 EXPECT_EQ(2, map->GetInternalSize()); | |
| 193 map->GetFrameIdOnIO(1, 2, CreateCallback(1, 2)); | |
| 194 EXPECT_EQ(1, map->GetInternalCallbackCount()); | |
| 195 base::RunLoop().RunUntilIdle(); | |
| 196 EXPECT_EQ(0, map->GetInternalCallbackCount()); | |
| 197 EXPECT_EQ(3, map->GetInternalSize()); | |
| 198 EXPECT_EQ(8U, results().size()); | |
| 199 EXPECT_EQ(ToTestFrameId(1, 2), results()[7]); | |
| 200 } | |
| 201 | |
| 202 } // namespace extensions | |
| OLD | NEW |