| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // CpuInfoProvider unit tests | 5 // CpuInfoProvider unit tests |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h" | 9 #include "chrome/browser/extensions/api/system_info_cpu/cpu_info_provider.h" |
| 10 #include "content/public/test/test_browser_thread.h" | 10 #include "content/public/test/test_browser_thread.h" |
| 11 #include "content/public/test/test_utils.h" | 11 #include "content/public/test/test_utils.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 | 13 |
| 14 namespace extensions { | 14 namespace extensions { |
| 15 | 15 |
| 16 using api::system_info_cpu::CpuInfo; | 16 using api::system_info_cpu::CpuInfo; |
| 17 using api::system_info_cpu::CpuUpdateInfo; | |
| 18 using content::BrowserThread; | |
| 19 | 17 |
| 20 struct TestCpuInfo { | 18 struct TestCpuInfo { |
| 21 std::string arch_name; | 19 std::string arch_name; |
| 22 std::string model_name; | 20 std::string model_name; |
| 23 int num_of_processors; | 21 int num_of_processors; |
| 24 }; | 22 }; |
| 25 | 23 |
| 26 struct TestCpuTimeInfo { | |
| 27 int64 user; | |
| 28 int64 kernel; | |
| 29 int64 idle; | |
| 30 }; | |
| 31 | |
| 32 struct TestCpuUpdateInfo { | |
| 33 double average_usage; | |
| 34 std::vector<double> usage_per_processor; | |
| 35 }; | |
| 36 | |
| 37 const struct TestCpuInfo kTestingCpuInfoData = { | 24 const struct TestCpuInfo kTestingCpuInfoData = { |
| 38 "x86", "Intel Core", 2 | 25 "x86", "Intel Core", 2 |
| 39 }; | 26 }; |
| 40 | 27 |
| 41 const struct TestCpuTimeInfo kTestingCpuTimeDataForOneProcessor[][3] = { | |
| 42 {{2, 4, 5}, {5, 7, 9}, {5, 7, 9}} | |
| 43 }; | |
| 44 | |
| 45 const struct TestCpuTimeInfo kTestingCpuTimeDataForTwoProcessors[][3] = { | |
| 46 {{2, 4, 5}, {2, 4, 5}, {3, 5, 6}}, // Processor1 cpu time data | |
| 47 {{5, 7, 9}, {5, 7, 9}, {6, 8, 10}} // Processor2 cpu time data | |
| 48 }; | |
| 49 | |
| 50 // The cpu sampling interval in unittest is 1ms. | |
| 51 const int kWatchingIntervalMs = 1; | |
| 52 // The times of doing cpu sampling. | |
| 53 const int kSamplingTimes = 2; | |
| 54 // The size of cpu time data. | |
| 55 const int kCpuTimeDataSize = 3; | |
| 56 | |
| 57 class TestCpuInfoProvider : public CpuInfoProvider { | 28 class TestCpuInfoProvider : public CpuInfoProvider { |
| 58 public: | 29 public: |
| 59 typedef const struct TestCpuTimeInfo (* TestingCpuTimeDataPointer)[3]; | |
| 60 | |
| 61 TestCpuInfoProvider(); | 30 TestCpuInfoProvider(); |
| 62 TestCpuInfoProvider(int num_of_processors, | |
| 63 TestingCpuTimeDataPointer cpu_time_data, | |
| 64 size_t sampling_interval); | |
| 65 virtual bool QueryInfo(CpuInfo* info) OVERRIDE; | 31 virtual bool QueryInfo(CpuInfo* info) OVERRIDE; |
| 66 virtual bool QueryCpuTimePerProcessor(std::vector<CpuTime>* times) OVERRIDE; | |
| 67 | |
| 68 // Check whether finishing cpu sampling. | |
| 69 bool is_complete_sampling() { | |
| 70 return query_times_ >= kCpuTimeDataSize; | |
| 71 } | |
| 72 | |
| 73 int num_of_processors() const { | |
| 74 return num_of_processors_; | |
| 75 } | |
| 76 | |
| 77 TestingCpuTimeDataPointer cpu_time_data() const { | |
| 78 return cpu_time_data_; | |
| 79 } | |
| 80 | 32 |
| 81 private: | 33 private: |
| 82 virtual ~TestCpuInfoProvider(); | 34 virtual ~TestCpuInfoProvider(); |
| 83 | |
| 84 // Record the query times of cpu_time_data_. | |
| 85 int query_times_; | |
| 86 int num_of_processors_; | |
| 87 | |
| 88 // A Pointer to kTestingCpuTimeDataFor*Processors array. | |
| 89 TestingCpuTimeDataPointer cpu_time_data_; | |
| 90 }; | 35 }; |
| 91 | 36 |
| 92 TestCpuInfoProvider::TestCpuInfoProvider() | 37 TestCpuInfoProvider::TestCpuInfoProvider() {} |
| 93 : query_times_(0), | |
| 94 num_of_processors_(1), | |
| 95 cpu_time_data_(NULL) { | |
| 96 } | |
| 97 | |
| 98 TestCpuInfoProvider::TestCpuInfoProvider(int num_of_processors, | |
| 99 TestingCpuTimeDataPointer cpu_time_data, | |
| 100 size_t sampling_interval) | |
| 101 : query_times_(0), | |
| 102 num_of_processors_(num_of_processors), | |
| 103 cpu_time_data_(cpu_time_data) { | |
| 104 sampling_interval_ = sampling_interval; | |
| 105 } | |
| 106 | 38 |
| 107 TestCpuInfoProvider::~TestCpuInfoProvider() {} | 39 TestCpuInfoProvider::~TestCpuInfoProvider() {} |
| 108 | 40 |
| 109 bool TestCpuInfoProvider::QueryInfo(CpuInfo* info) { | 41 bool TestCpuInfoProvider::QueryInfo(CpuInfo* info) { |
| 110 if (info == NULL) | 42 if (info == NULL) |
| 111 return false; | 43 return false; |
| 112 info->arch_name = kTestingCpuInfoData.arch_name; | 44 info->arch_name = kTestingCpuInfoData.arch_name; |
| 113 info->model_name = kTestingCpuInfoData.model_name; | 45 info->model_name = kTestingCpuInfoData.model_name; |
| 114 info->num_of_processors = kTestingCpuInfoData.num_of_processors; | 46 info->num_of_processors = kTestingCpuInfoData.num_of_processors; |
| 115 return true; | 47 return true; |
| 116 } | 48 } |
| 117 | 49 |
| 118 bool TestCpuInfoProvider::QueryCpuTimePerProcessor( | |
| 119 std::vector<CpuTime>* times) { | |
| 120 if (is_complete_sampling()) | |
| 121 return false; | |
| 122 | |
| 123 std::vector<CpuTime> results; | |
| 124 for (int i = 0; i < num_of_processors_; ++i) { | |
| 125 CpuTime cpu_time; | |
| 126 cpu_time.user = cpu_time_data_[i][query_times_].user; | |
| 127 cpu_time.kernel = cpu_time_data_[i][query_times_].kernel; | |
| 128 cpu_time.idle = cpu_time_data_[i][query_times_].idle; | |
| 129 results.push_back(cpu_time); | |
| 130 } | |
| 131 ++query_times_; | |
| 132 times->swap(results); | |
| 133 | |
| 134 return true; | |
| 135 } | |
| 136 | |
| 137 class CpuInfoProviderTest : public testing::Test { | 50 class CpuInfoProviderTest : public testing::Test { |
| 138 public: | 51 public: |
| 139 CpuInfoProviderTest(); | 52 CpuInfoProviderTest(); |
| 140 | 53 |
| 141 // A callback function to be called when CpuInfoProvider completes to sample. | |
| 142 // Called on FILE thread. | |
| 143 void OnCheckCpuSamplingFinishedForTesting(scoped_ptr<CpuUpdateInfo> info); | |
| 144 void CalculateExpectedResult(); | |
| 145 void VerifyResult(); | |
| 146 | |
| 147 protected: | 54 protected: |
| 148 base::MessageLoop message_loop_; | |
| 149 content::TestBrowserThread ui_thread_; | |
| 150 content::TestBrowserThread file_thread_; | |
| 151 scoped_refptr<TestCpuInfoProvider> cpu_info_provider_; | 55 scoped_refptr<TestCpuInfoProvider> cpu_info_provider_; |
| 152 | |
| 153 // Maintain the CpuUpdateInfo results returned by DoSample function. | |
| 154 std::vector<TestCpuUpdateInfo> cpu_update_result_; | |
| 155 | |
| 156 // Maintain the expected CpuUpdateInfo. | |
| 157 std::vector<TestCpuUpdateInfo> expected_cpu_update_result_; | |
| 158 }; | 56 }; |
| 159 | 57 |
| 160 CpuInfoProviderTest::CpuInfoProviderTest() | 58 CpuInfoProviderTest::CpuInfoProviderTest() {} |
| 161 : message_loop_(base::MessageLoop::TYPE_UI), | |
| 162 ui_thread_(BrowserThread::UI, &message_loop_), | |
| 163 file_thread_(BrowserThread::FILE, &message_loop_) { | |
| 164 } | |
| 165 | |
| 166 void CpuInfoProviderTest::OnCheckCpuSamplingFinishedForTesting( | |
| 167 scoped_ptr<CpuUpdateInfo> info) { | |
| 168 // The cpu sampling is doing in FILE thread, so the callback function | |
| 169 // should be also called in FILE thread. | |
| 170 ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 171 | |
| 172 // Once the sampling completed, we need to quit the FILE thread to given | |
| 173 // UI thread a chance to verify results. | |
| 174 if (cpu_info_provider_->is_complete_sampling()) { | |
| 175 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 176 base::MessageLoop::QuitClosure()); | |
| 177 } | |
| 178 | |
| 179 TestCpuUpdateInfo result; | |
| 180 result.average_usage = info->average_usage; | |
| 181 result.usage_per_processor = info->usage_per_processor; | |
| 182 cpu_update_result_.push_back(result); | |
| 183 } | |
| 184 | |
| 185 void CpuInfoProviderTest::CalculateExpectedResult() { | |
| 186 TestCpuInfoProvider::TestingCpuTimeDataPointer cpu_time_testing_data = | |
| 187 cpu_info_provider_->cpu_time_data(); | |
| 188 DCHECK(cpu_time_testing_data != NULL); | |
| 189 | |
| 190 int test_data_index = 0; | |
| 191 std::vector<TestCpuTimeInfo> baseline_cpu_time; | |
| 192 | |
| 193 for (int i = 0; i < cpu_info_provider_->num_of_processors(); ++i) | |
| 194 baseline_cpu_time.push_back(cpu_time_testing_data[i][0]); | |
| 195 ++test_data_index; | |
| 196 | |
| 197 for (int i = 0; i < kSamplingTimes; ++i) { | |
| 198 TestCpuUpdateInfo info; | |
| 199 double total_usage = 0; | |
| 200 std::vector<TestCpuTimeInfo> next_cpu_time; | |
| 201 for (int j = 0; j < cpu_info_provider_->num_of_processors(); ++j) | |
| 202 next_cpu_time.push_back(cpu_time_testing_data[j][test_data_index]); | |
| 203 | |
| 204 for (int j = 0; j < cpu_info_provider_->num_of_processors(); ++j) { | |
| 205 double toal_time = | |
| 206 (next_cpu_time[j].user - baseline_cpu_time[j].user) + | |
| 207 (next_cpu_time[j].idle - baseline_cpu_time[j].idle) + | |
| 208 (next_cpu_time[j].kernel - baseline_cpu_time[j].kernel); | |
| 209 double idle_time = next_cpu_time[j].idle - baseline_cpu_time[j].idle; | |
| 210 double usage = 0; | |
| 211 if (toal_time != 0) | |
| 212 usage = 100 - idle_time * 100 / toal_time; | |
| 213 info.usage_per_processor.push_back(usage); | |
| 214 total_usage += usage; | |
| 215 } | |
| 216 info.average_usage = | |
| 217 total_usage / cpu_info_provider_->num_of_processors(); | |
| 218 expected_cpu_update_result_.push_back(info); | |
| 219 | |
| 220 ++test_data_index; | |
| 221 baseline_cpu_time.swap(next_cpu_time); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 void CpuInfoProviderTest::VerifyResult() { | |
| 226 EXPECT_EQ(expected_cpu_update_result_.size(), cpu_update_result_.size()); | |
| 227 for (size_t i = 0; i < expected_cpu_update_result_.size(); ++i) { | |
| 228 EXPECT_DOUBLE_EQ(expected_cpu_update_result_[i].average_usage, | |
| 229 cpu_update_result_[i].average_usage); | |
| 230 EXPECT_EQ(expected_cpu_update_result_[i].usage_per_processor.size(), | |
| 231 cpu_update_result_[i].usage_per_processor.size()); | |
| 232 for (size_t j = 0; | |
| 233 j < expected_cpu_update_result_[i].usage_per_processor.size(); ++j) { | |
| 234 EXPECT_DOUBLE_EQ(expected_cpu_update_result_[i].usage_per_processor[j], | |
| 235 cpu_update_result_[i].usage_per_processor[j]); | |
| 236 } | |
| 237 } | |
| 238 } | |
| 239 | 59 |
| 240 TEST_F(CpuInfoProviderTest, QueryCpuInfo) { | 60 TEST_F(CpuInfoProviderTest, QueryCpuInfo) { |
| 241 cpu_info_provider_ = new TestCpuInfoProvider(); | 61 cpu_info_provider_ = new TestCpuInfoProvider(); |
| 242 scoped_ptr<CpuInfo> cpu_info(new CpuInfo()); | 62 scoped_ptr<CpuInfo> cpu_info(new CpuInfo()); |
| 243 EXPECT_TRUE(cpu_info_provider_->QueryInfo(cpu_info.get())); | 63 EXPECT_TRUE(cpu_info_provider_->QueryInfo(cpu_info.get())); |
| 244 EXPECT_EQ(kTestingCpuInfoData.arch_name, cpu_info->arch_name); | 64 EXPECT_EQ(kTestingCpuInfoData.arch_name, cpu_info->arch_name); |
| 245 EXPECT_EQ(kTestingCpuInfoData.model_name, cpu_info->model_name); | 65 EXPECT_EQ(kTestingCpuInfoData.model_name, cpu_info->model_name); |
| 246 EXPECT_EQ(kTestingCpuInfoData.num_of_processors, cpu_info->num_of_processors); | 66 EXPECT_EQ(kTestingCpuInfoData.num_of_processors, cpu_info->num_of_processors); |
| 247 } | 67 } |
| 248 | 68 |
| 249 TEST_F(CpuInfoProviderTest, DoOnlyOneProcessorCpuSampling) { | |
| 250 cpu_info_provider_ = | |
| 251 new TestCpuInfoProvider(1, // number of processors | |
| 252 kTestingCpuTimeDataForOneProcessor, | |
| 253 kWatchingIntervalMs); | |
| 254 CalculateExpectedResult(); | |
| 255 cpu_info_provider_->StartSampling( | |
| 256 base::Bind(&CpuInfoProviderTest::OnCheckCpuSamplingFinishedForTesting, | |
| 257 base::Unretained(this))); | |
| 258 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE); | |
| 259 content::RunMessageLoop(); | |
| 260 cpu_info_provider_->StopSampling(); | |
| 261 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE); | |
| 262 VerifyResult(); | |
| 263 } | 69 } |
| 264 | |
| 265 TEST_F(CpuInfoProviderTest, DoTwoProcessorsCpuSampling) { | |
| 266 cpu_info_provider_ = | |
| 267 new TestCpuInfoProvider(2, // number of processors | |
| 268 kTestingCpuTimeDataForTwoProcessors, | |
| 269 kWatchingIntervalMs); | |
| 270 CalculateExpectedResult(); | |
| 271 | |
| 272 cpu_info_provider_->StartSampling( | |
| 273 base::Bind(&CpuInfoProviderTest::OnCheckCpuSamplingFinishedForTesting, | |
| 274 base::Unretained(this))); | |
| 275 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE); | |
| 276 content::RunMessageLoop(); | |
| 277 cpu_info_provider_->StopSampling(); | |
| 278 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE); | |
| 279 VerifyResult(); | |
| 280 } | |
| 281 | |
| 282 } | |
| OLD | NEW |