| OLD | NEW |
| (Empty) |
| 1 // Copyright 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 <algorithm> | |
| 6 | |
| 7 #include "base/rand_util.h" | |
| 8 #include "base/strings/string_number_conversions.h" | |
| 9 #include "base/time/time.h" | |
| 10 #include "chrome/browser/apps/ephemeral_app_service.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 // Generate a time N number of days before the reference time. | |
| 16 // The generated time can be randomized. | |
| 17 base::Time GetPastTime(const base::Time& reference_time, | |
| 18 int days_before, | |
| 19 bool randomize_time = false) { | |
| 20 base::Time generated_time = | |
| 21 reference_time - base::TimeDelta::FromDays(days_before); | |
| 22 | |
| 23 // Add an hour so that the time is well within the number of days before. | |
| 24 generated_time += base::TimeDelta::FromHours(1); | |
| 25 | |
| 26 // Add a random number of seconds between 0 - 10 hours. | |
| 27 if (randomize_time) | |
| 28 generated_time += base::TimeDelta::FromSeconds(base::RandInt(0, 36000)); | |
| 29 | |
| 30 return generated_time; | |
| 31 } | |
| 32 | |
| 33 } // namespace | |
| 34 | |
| 35 class EphemeralAppServiceTest : public testing::Test { | |
| 36 protected: | |
| 37 typedef EphemeralAppService::LaunchTimeAppMap LaunchTimeAppMap; | |
| 38 | |
| 39 EphemeralAppServiceTest() {} | |
| 40 ~EphemeralAppServiceTest() override {} | |
| 41 | |
| 42 void RunTest(int ephemeral_app_count, | |
| 43 const LaunchTimeAppMap& launch_times, | |
| 44 const std::set<std::string>& expected_removed_ids) { | |
| 45 std::set<std::string> remove_app_ids; | |
| 46 EphemeralAppService::GetAppsToRemove(ephemeral_app_count, | |
| 47 launch_times, | |
| 48 &remove_app_ids); | |
| 49 EXPECT_EQ(expected_removed_ids, remove_app_ids); | |
| 50 } | |
| 51 | |
| 52 void RunTestCheckLRU(int ephemeral_app_count, | |
| 53 LaunchTimeAppMap& launch_times, | |
| 54 int expected_removed_count) { | |
| 55 std::set<std::string> remove_app_ids; | |
| 56 EphemeralAppService::GetAppsToRemove(ephemeral_app_count, | |
| 57 launch_times, | |
| 58 &remove_app_ids); | |
| 59 EXPECT_EQ(expected_removed_count, (int) remove_app_ids.size()); | |
| 60 | |
| 61 // Move the launch times of removed apps to another map. | |
| 62 LaunchTimeAppMap removed_apps; | |
| 63 for (LaunchTimeAppMap::iterator it = launch_times.begin(); | |
| 64 it != launch_times.end(); ) { | |
| 65 if (remove_app_ids.find(it->second) != remove_app_ids.end()) { | |
| 66 removed_apps.insert(*it); | |
| 67 launch_times.erase(it++); | |
| 68 } else { | |
| 69 ++it; | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 if (launch_times.empty()) | |
| 74 return; | |
| 75 | |
| 76 // Verify that the removed apps have launch times earlier than or equal to | |
| 77 // all retained apps. We can actually just compare with the first entry in | |
| 78 // |launch_times| but will make no implementation assumptions. | |
| 79 for (LaunchTimeAppMap::const_iterator removed = removed_apps.begin(); | |
| 80 removed != removed_apps.end(); ++removed) { | |
| 81 for (LaunchTimeAppMap::iterator retained = launch_times.begin(); | |
| 82 retained != launch_times.end(); ++retained) { | |
| 83 EXPECT_LE(removed->first, retained->first); | |
| 84 } | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 // Generate X app launch times, N days before the reference time. | |
| 89 // If |generated_ids| is not NULL, the generated app IDs will be added | |
| 90 // to the set. | |
| 91 void GenerateLaunchTimes(const base::Time& reference_time, | |
| 92 int days_before, | |
| 93 int count, | |
| 94 LaunchTimeAppMap* launch_times, | |
| 95 std::set<std::string>* generated_ids = NULL) { | |
| 96 for (int i = 0; i < count; ++i) { | |
| 97 std::string app_id = base::SizeTToString(launch_times->size()); | |
| 98 launch_times->insert(std::make_pair( | |
| 99 GetPastTime(reference_time, days_before, true), | |
| 100 app_id)); | |
| 101 | |
| 102 if (generated_ids) | |
| 103 generated_ids->insert(app_id); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 // Add inactive apps that should always be removed by garbage collection. | |
| 108 void AddInactiveApps(const base::Time& reference_time, | |
| 109 int count, | |
| 110 LaunchTimeAppMap* launch_times, | |
| 111 std::set<std::string>* generated_ids = NULL) { | |
| 112 GenerateLaunchTimes(reference_time, | |
| 113 EphemeralAppService::kAppInactiveThreshold + 1, | |
| 114 count, | |
| 115 launch_times, | |
| 116 generated_ids); | |
| 117 } | |
| 118 | |
| 119 // Add recently launched apps that should NOT be removed by garbage | |
| 120 // collection regardless of the number of cached ephemeral apps. | |
| 121 void AddRecentlyLaunchedApps(const base::Time& reference_time, | |
| 122 int count, | |
| 123 LaunchTimeAppMap* launch_times, | |
| 124 std::set<std::string>* generated_ids = NULL) { | |
| 125 GenerateLaunchTimes(reference_time, | |
| 126 EphemeralAppService::kAppKeepThreshold, | |
| 127 count, | |
| 128 launch_times, | |
| 129 generated_ids); | |
| 130 } | |
| 131 | |
| 132 // Add apps launched between the kAppInactiveThreshold and kAppKeepThreshold, | |
| 133 // which may or may not be removed by garbage collection depending on the | |
| 134 // number of ephemeral apps in the cache. | |
| 135 void AddIntermediateApps(const base::Time& reference_time, | |
| 136 int count, | |
| 137 LaunchTimeAppMap* launch_times, | |
| 138 std::set<std::string>* generated_ids = NULL) { | |
| 139 int days_before = base::RandInt(EphemeralAppService::kAppKeepThreshold + 1, | |
| 140 EphemeralAppService::kAppInactiveThreshold); | |
| 141 GenerateLaunchTimes(reference_time, | |
| 142 days_before, | |
| 143 count, | |
| 144 launch_times, | |
| 145 generated_ids); | |
| 146 } | |
| 147 }; | |
| 148 | |
| 149 // Verify that inactive apps are removed even if the cache has not reached | |
| 150 // capacity. | |
| 151 // Test case: | inactive | | |
| 152 // Expected output: All inactive apps removed. | |
| 153 TEST_F(EphemeralAppServiceTest, RemoveInactiveApps) { | |
| 154 base::Time time_now = base::Time::Now(); | |
| 155 LaunchTimeAppMap launch_times; | |
| 156 std::set<std::string> expected_removed_ids; | |
| 157 | |
| 158 AddInactiveApps( | |
| 159 time_now, | |
| 160 EphemeralAppService::kMaxEphemeralAppsCount / 5, | |
| 161 &launch_times, | |
| 162 &expected_removed_ids); | |
| 163 RunTest(launch_times.size(), launch_times, expected_removed_ids); | |
| 164 } | |
| 165 | |
| 166 // Verify that inactive apps are removed even if the cache has not reached | |
| 167 // capacity. | |
| 168 // Test case: | inactive | intermediate | recently launched | | |
| 169 // Expected output: All inactive apps removed, other apps retained. | |
| 170 TEST_F(EphemeralAppServiceTest, RemoveInactiveAppsKeepOthers) { | |
| 171 base::Time time_now = base::Time::Now(); | |
| 172 LaunchTimeAppMap launch_times; | |
| 173 std::set<std::string> expected_removed_ids; | |
| 174 | |
| 175 AddInactiveApps( | |
| 176 time_now, | |
| 177 EphemeralAppService::kMaxEphemeralAppsCount / 5, | |
| 178 &launch_times, | |
| 179 &expected_removed_ids); | |
| 180 AddIntermediateApps( | |
| 181 time_now, | |
| 182 EphemeralAppService::kMaxEphemeralAppsCount / 5, | |
| 183 &launch_times); | |
| 184 AddRecentlyLaunchedApps( | |
| 185 time_now, | |
| 186 EphemeralAppService::kMaxEphemeralAppsCount / 5, | |
| 187 &launch_times); | |
| 188 RunTest(launch_times.size(), launch_times, expected_removed_ids); | |
| 189 } | |
| 190 | |
| 191 // Verify that recently launched apps will not be removed, even when the cache | |
| 192 // overflows. | |
| 193 // Test case: | recently launched | | |
| 194 // Expected output: All recently launched apps retained. | |
| 195 TEST_F(EphemeralAppServiceTest, KeepRecentLaunch) { | |
| 196 base::Time time_now = base::Time::Now(); | |
| 197 LaunchTimeAppMap launch_times; | |
| 198 | |
| 199 AddRecentlyLaunchedApps( | |
| 200 time_now, | |
| 201 3, | |
| 202 &launch_times); | |
| 203 RunTest(launch_times.size(), launch_times, std::set<std::string>()); | |
| 204 | |
| 205 AddRecentlyLaunchedApps( | |
| 206 time_now, | |
| 207 EphemeralAppService::kMaxEphemeralAppsCount, | |
| 208 &launch_times); // overflow | |
| 209 RunTest(launch_times.size(), launch_times, std::set<std::string>()); | |
| 210 } | |
| 211 | |
| 212 // Verify that recently launched apps will not be removed, even when the cache | |
| 213 // overflows. | |
| 214 // Test case: | intermediate (overflow) | recently launched (overflow) | | |
| 215 // Expected output: All recently launched apps retained, intermediate apps | |
| 216 // removed. | |
| 217 TEST_F(EphemeralAppServiceTest, KeepRecentLaunchRemoveOthers) { | |
| 218 base::Time time_now = base::Time::Now(); | |
| 219 LaunchTimeAppMap launch_times; | |
| 220 std::set<std::string> expected_removed_ids; | |
| 221 | |
| 222 AddRecentlyLaunchedApps( | |
| 223 time_now, | |
| 224 EphemeralAppService::kMaxEphemeralAppsCount + 3, | |
| 225 &launch_times); // overflow | |
| 226 AddIntermediateApps( | |
| 227 time_now, | |
| 228 3, | |
| 229 &launch_times, | |
| 230 &expected_removed_ids); // overflow | |
| 231 RunTest(launch_times.size(), launch_times, expected_removed_ids); | |
| 232 } | |
| 233 | |
| 234 // Verify that the LRU algorithm is implemented correctly. | |
| 235 // Test case: | intermediate (overflow) | | |
| 236 // Expected output: The least recently launched apps are removed. | |
| 237 TEST_F(EphemeralAppServiceTest, RemoveOverflow) { | |
| 238 base::Time time_now = base::Time::Now(); | |
| 239 LaunchTimeAppMap launch_times; | |
| 240 | |
| 241 const int kOverflow = 3; | |
| 242 AddIntermediateApps( | |
| 243 time_now, | |
| 244 EphemeralAppService::kMaxEphemeralAppsCount + kOverflow, | |
| 245 &launch_times); // overflow | |
| 246 RunTestCheckLRU(launch_times.size(), launch_times, kOverflow); | |
| 247 } | |
| 248 | |
| 249 // Verify that GetAppsToRemove() takes into account the number of running apps, | |
| 250 // since they are not included in the launch times. | |
| 251 // Test case: | intermediate (overflow) | running apps | | |
| 252 // Expected output: The least recently launched apps are removed. | |
| 253 TEST_F(EphemeralAppServiceTest, RemoveOverflowWithRunningApps) { | |
| 254 base::Time time_now = base::Time::Now(); | |
| 255 LaunchTimeAppMap launch_times; | |
| 256 | |
| 257 const int kRunningApps = 3; | |
| 258 AddIntermediateApps( | |
| 259 time_now, | |
| 260 EphemeralAppService::kMaxEphemeralAppsCount, | |
| 261 &launch_times); // overflow | |
| 262 RunTestCheckLRU( | |
| 263 launch_times.size() + kRunningApps, | |
| 264 launch_times, | |
| 265 kRunningApps); | |
| 266 } | |
| OLD | NEW |