blob: 0576e83cf8e8945a126a16c83ec099b1784b97ac [file] [log] [blame]
// Copyright 2008-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
#include "omaha/common/time.h"
#include "omaha/goopdate/stats_uploader.h"
#include "omaha/statsreport/aggregator.h"
#include "omaha/testing/unit_test.h"
#include "omaha/worker/application_manager.h"
#include "omaha/worker/worker.h"
#include "omaha/worker/worker_metrics.h"
#include "omaha/worker/worker-internal.h"
namespace omaha {
namespace {
const TCHAR* const kDailyUsageStatsKeyPath =
_T("HKCU\\Software\\Google\\Update\\UsageStats\\Daily");
// The alphabetical order of these is important for
// RecordUpdateAvailableUsageStatsTest.
const TCHAR* const kApp1 = _T("{0C480772-AC73-418f-9603-66303DA4C7AA}");
const TCHAR* const kApp2 = _T("{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}");
const TCHAR* const kApp3 = _T("{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}");
const uint64 kApp1GuidUpper = 0x0C480772AC73418f;
const uint64 kApp2GuidUpper = 0x89906BCD4D124c9b;
const TCHAR* const kApp1ClientsKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\Clients\\")
_T("{0C480772-AC73-418f-9603-66303DA4C7AA}");
const TCHAR* const kApp2ClientsKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\Clients\\")
_T("{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}");
const TCHAR* const kApp3ClientsKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\Clients\\")
_T("{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}");
const TCHAR* const kApp1ClientStateKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\ClientState\\")
_T("{0C480772-AC73-418f-9603-66303DA4C7AA}");
const TCHAR* const kApp2ClientStateKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\ClientState\\")
_T("{89906BCD-4D12-4c9b-B5BA-8286051CB8D9}");
const TCHAR* const kApp3ClientStateKeyPathUser =
_T("HKCU\\Software\\Google\\Update\\ClientState\\")
_T("{F5A1FE97-CF5A-47b8-8B28-2A72F9A57A45}");
} // namespace
class WorkerTest : public testing::Test {
protected:
Worker worker_;
};
// TODO(omaha): Test all methods of Worker
class RecordUpdateAvailableUsageStatsTest : public testing::Test {
protected:
RecordUpdateAvailableUsageStatsTest() : is_machine_(false) {}
static void SetUpTestCase() {
// Initialize the global metrics collection.
stats_report::g_global_metrics.Initialize();
}
static void TearDownTestCase() {
// The global metrics collection must be uninitialized before the metrics
// destructors are called.
stats_report::g_global_metrics.Uninitialize();
}
virtual void SetUp() {
RegKey::DeleteKey(kRegistryHiveOverrideRoot);
OverrideRegistryHives(kRegistryHiveOverrideRoot);
metric_worker_self_update_responses.Set(0);
metric_worker_self_update_response_time_since_first_ms.Set(0);
metric_worker_app_max_update_responses_app_high.Set(0);
metric_worker_app_max_update_responses.Set(0);
metric_worker_app_max_update_responses_ms_since_first.Set(0);
ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENTS_GOOPDATE,
kRegValueProductVersion,
_T("0.1.0.0")));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientsKeyPathUser,
kRegValueProductVersion,
_T("0.1")));
ASSERT_SUCCEEDED(RegKey::CreateKey(USER_REG_CLIENT_STATE_GOOPDATE));
ASSERT_SUCCEEDED(RegKey::CreateKey(kApp1ClientStateKeyPathUser));
}
int GetNumProducts() {
AppManager app_manager(is_machine_);
ProductDataVector products;
VERIFY1(SUCCEEDED(app_manager.GetRegisteredProducts(&products)));
return products.size();
}
virtual void TearDown() {
RestoreRegistryHives();
RegKey::DeleteKey(kRegistryHiveOverrideRoot);
}
bool is_machine_;
scoped_ptr<AppManager> app_manager_;
};
TEST_F(RecordUpdateAvailableUsageStatsTest, NoData) {
ASSERT_EQ(2, GetNumProducts());
internal::RecordUpdateAvailableUsageStats(is_machine_);
EXPECT_EQ(0, metric_worker_self_update_responses.value());
EXPECT_EQ(0, metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses_app_high.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses_ms_since_first.value());
}
TEST_F(RecordUpdateAvailableUsageStatsTest, OmahaDataOnly) {
ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE,
_T("UpdateAvailableCount"),
static_cast<DWORD>(123456)));
ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE,
_T("UpdateAvailableSince"),
static_cast<DWORD64>(10)));
ASSERT_EQ(2, GetNumProducts());
const time64 current_time_100ns(GetCurrent100NSTime());
const uint64 expected_ms_since_first_update =
(current_time_100ns - 10) / kMillisecsTo100ns;
internal::RecordUpdateAvailableUsageStats(is_machine_);
EXPECT_EQ(123456, metric_worker_self_update_responses.value());
EXPECT_LE(expected_ms_since_first_update,
metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_GT(expected_ms_since_first_update + 10 * kMsPerSec,
metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses_app_high.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses.value());
EXPECT_EQ(0, metric_worker_app_max_update_responses_ms_since_first.value());
}
TEST_F(RecordUpdateAvailableUsageStatsTest, OneAppOnly) {
ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser,
_T("UpdateAvailableCount"),
static_cast<DWORD>(123456)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser,
_T("UpdateAvailableSince"),
static_cast<DWORD64>(10)));
ASSERT_EQ(2, GetNumProducts());
const time64 current_time_100ns(GetCurrent100NSTime());
const uint64 expected_ms_since_first_update =
(current_time_100ns - 10) / kMillisecsTo100ns;
internal::RecordUpdateAvailableUsageStats(is_machine_);
EXPECT_EQ(0, metric_worker_self_update_responses.value());
EXPECT_EQ(0, metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_EQ(kApp1GuidUpper,
metric_worker_app_max_update_responses_app_high.value());
EXPECT_EQ(123456, metric_worker_app_max_update_responses.value());
EXPECT_LE(expected_ms_since_first_update,
metric_worker_app_max_update_responses_ms_since_first.value());
EXPECT_GT(expected_ms_since_first_update + 10 * kMsPerSec,
metric_worker_app_max_update_responses_ms_since_first.value());
}
// It is important that Omaha's count is the largest.
// All app data should be from app 2, which has the greatest count, a middle
// time, and an alphabetically middle GUID
TEST_F(RecordUpdateAvailableUsageStatsTest, OmahaAndSeveralApps) {
const DWORD64 kApp2SinceTime = 1000 * kSecsTo100ns;
ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientsKeyPathUser,
kRegValueProductVersion,
_T("1.2")));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientsKeyPathUser,
kRegValueProductVersion,
_T("2.3")));
ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE,
_T("UpdateAvailableCount"),
static_cast<DWORD>(0x99887766)));
ASSERT_SUCCEEDED(RegKey::SetValue(USER_REG_CLIENT_STATE_GOOPDATE,
_T("UpdateAvailableSince"),
static_cast<DWORD64>(1)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser,
_T("UpdateAvailableCount"),
static_cast<DWORD>(1)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp1ClientStateKeyPathUser,
_T("UpdateAvailableSince"),
static_cast<DWORD64>(1)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientStateKeyPathUser,
_T("UpdateAvailableCount"),
static_cast<DWORD>(9876543)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp2ClientStateKeyPathUser,
_T("UpdateAvailableSince"),
kApp2SinceTime));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientStateKeyPathUser,
_T("UpdateAvailableCount"),
static_cast<DWORD>(234)));
ASSERT_SUCCEEDED(RegKey::SetValue(kApp3ClientStateKeyPathUser,
_T("UpdateAvailableSince"),
static_cast<DWORD64>(128580000000000000)));
ASSERT_EQ(4, GetNumProducts());
const time64 current_time_100ns(GetCurrent100NSTime());
const uint64 goopdate_expected_ms_since_first_update =
(current_time_100ns - 1) / kMillisecsTo100ns;
const uint64 app_expected_ms_since_first_update =
(current_time_100ns - kApp2SinceTime) / kMillisecsTo100ns;
internal::RecordUpdateAvailableUsageStats(is_machine_);
EXPECT_EQ(0x99887766, metric_worker_self_update_responses.value());
EXPECT_LE(goopdate_expected_ms_since_first_update,
metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_GT(goopdate_expected_ms_since_first_update + 10 * kMsPerSec,
metric_worker_self_update_response_time_since_first_ms.value());
EXPECT_EQ(kApp2GuidUpper,
metric_worker_app_max_update_responses_app_high.value());
EXPECT_EQ(9876543, metric_worker_app_max_update_responses.value());
EXPECT_LE(app_expected_ms_since_first_update,
metric_worker_app_max_update_responses_ms_since_first.value());
EXPECT_GT(app_expected_ms_since_first_update + 10 * kMsPerSec,
metric_worker_app_max_update_responses_ms_since_first.value());
}
class SendSelfUpdateFailurePingTest : public testing::Test {
protected:
virtual void SetUp() {
RegKey::DeleteKey(kRegistryHiveOverrideRoot);
// Overriding HKLM prevents the Windows DNS resolver from working.
// Only override HKCU and run the tests as user.
OverrideSpecifiedRegistryHives(kRegistryHiveOverrideRoot, false, true);
}
virtual void TearDown() {
RestoreRegistryHives();
RegKey::DeleteKey(kRegistryHiveOverrideRoot);
}
};
TEST_F(SendSelfUpdateFailurePingTest, UserKeyDoesNotExist) {
ExpectAsserts expect_asserts;
internal::SendSelfUpdateFailurePing(false);
}
TEST_F(SendSelfUpdateFailurePingTest, MachineKeyDoesNotExist) {
OverrideRegistryHives(kRegistryHiveOverrideRoot);
ExpectAsserts expect_asserts;
internal::SendSelfUpdateFailurePing(true);
}
TEST_F(SendSelfUpdateFailurePingTest, UserUpdateErrorCodeDoesNotExist) {
EXPECT_SUCCEEDED(RegKey::CreateKey(USER_REG_UPDATE));
internal::SendSelfUpdateFailurePing(false);
}
TEST_F(SendSelfUpdateFailurePingTest, MachineUpdateErrorCodeDoesNotExist) {
OverrideRegistryHives(kRegistryHiveOverrideRoot);
EXPECT_SUCCEEDED(RegKey::CreateKey(MACHINE_REG_UPDATE));
internal::SendSelfUpdateFailurePing(true);
}
TEST_F(SendSelfUpdateFailurePingTest, UserAllValuesPresent) {
EXPECT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE,
kRegValueSelfUpdateErrorCode,
static_cast<DWORD>(0x87654321)));
EXPECT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE,
kRegValueSelfUpdateExtraCode1,
static_cast<DWORD>(55)));
EXPECT_SUCCEEDED(RegKey::SetValue(USER_REG_UPDATE,
kRegValueSelfUpdateVersion,
_T("0.2.4.8")));
internal::SendSelfUpdateFailurePing(false);
}
TEST_F(SendSelfUpdateFailurePingTest, UserValuesPresentInMachineOnly) {
EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateErrorCode,
static_cast<DWORD>(0x87654321)));
EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateExtraCode1,
static_cast<DWORD>(55)));
EXPECT_SUCCEEDED(RegKey::SetValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateVersion,
_T("0.2.4.8")));
ExpectAsserts expect_asserts;
internal::SendSelfUpdateFailurePing(false);
// Clean up HKLM, which isn't overridden.
EXPECT_SUCCEEDED(RegKey::DeleteValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateErrorCode));
EXPECT_SUCCEEDED(RegKey::DeleteValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateExtraCode1));
EXPECT_SUCCEEDED(RegKey::DeleteValue(MACHINE_REG_UPDATE,
kRegValueSelfUpdateVersion));
}
} // namespace omaha