blob: 32eefd035bf679e22e648a058eec0b5d0f694ab7 [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 <windows.h>
#include <atlstr.h>
#include "omaha/common/app_util.h"
#include "omaha/common/error.h"
#include "omaha/common/file.h"
#include "omaha/common/path.h"
#include "omaha/common/scoped_ptr_address.h"
#include "omaha/common/scoped_ptr_cotask.h"
#include "omaha/common/system.h"
#include "omaha/common/user_info.h"
#include "omaha/common/utils.h"
#include "omaha/common/vistautil.h"
#include "omaha/goopdate/config_manager.h"
#include "omaha/goopdate/const_goopdate.h"
#include "omaha/testing/unit_test.h"
#include "omaha/worker/download_manager.h"
#include "omaha/worker/job.h"
#include "omaha/worker/ping.h"
namespace omaha {
namespace {
// Hash = Igq6bYaeXFJCjH770knXyJ6V53s=, size = 479848
const TCHAR kTestExeHash[] = _T("Igq6bYaeXFJCjH770knXyJ6V53s=");
const int kTestExeSize = 479848;
const TCHAR kWrongTestExeHash[] = _T("F006bYaeXFJCjH770knXyJ6V53s=");
// Hash = ImV9skETZqGFMjs32vbZTvzAYJU=, size = 870400
const TCHAR kTestMsiHash[] = _T("ImV9skETZqGFMjs32vbZTvzAYJU=");
const int kTestMsiSize = 870400;
} // namespace
class DownloadManagerTest : public testing::Test {
protected:
static void SetUpTestCase() {
TCHAR module_path[MAX_PATH] = {0};
ASSERT_NE(0, ::GetModuleFileName(NULL, module_path, MAX_PATH));
CString path = GetDirectoryFromPath(module_path);
cache_test_dir_ =
ConcatenatePath(path, _T("unittest_support\\download_cache_test"));
CString expected_path_exe = (_T("{7101D597-3481-4971-AD23-455542964072}")
_T("\\livelysetup.exe"));
expected_file_name_exe_ =
ConcatenatePath(cache_test_dir_, expected_path_exe);
CString expected_path_msi = (_T("{89640431-FE64-4da8-9860-1A1085A60E13}")
_T("\\gears-win32-opt.msi"));
expected_file_name_msi_ =
ConcatenatePath(cache_test_dir_, expected_path_msi);
}
virtual void SetUp() {
job_.reset(CreateJob());
}
void Initialize(bool is_machine) {
download_manager_.reset(new DownloadManager(is_machine));
}
virtual void TearDown() {
download_manager_.reset();
job_.reset();
}
HRESULT BuildDestinationDirectory(CString* dir) {
return download_manager_->BuildDestinationDirectory(dir);
}
HRESULT BuildUniqueDownloadFilePath(CString* file) {
return download_manager_->BuildUniqueDownloadFilePath(file);
}
void SetJob(Job* job) {
download_manager_->job_ = job;
}
bool IsCached(const CString& path) {
return download_manager_->IsCached(path);
}
HRESULT GetFileNameFromDownloadUrl(const CString& url,
CString* out) {
return download_manager_->GetFileNameFromDownloadUrl(url, out);
}
HRESULT ValidateDownloadedFile(const CString& file_name) const {
return download_manager_->ValidateDownloadedFile(file_name);
}
void SetErrorInfo(HRESULT hr) {
download_manager_->SetErrorInfo(hr);
}
Job* CreateJob() {
Initialize(false);
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/update2/UpdateData.bin"));
response_data.set_hash(_T("YF2z/br/S6E3KTca0MT7qziJN44="));
scoped_ptr<Job> job(new Job(true, &ping_));
job->set_is_background(true);
job->set_update_response_data(response_data);
return job.release();
}
Job* CreateJob(const UpdateResponseData& data) {
scoped_ptr<Job> job(new Job(true, &ping_));
job->set_is_background(true);
job->set_update_response_data(data);
return job.release();
}
void SetLocalDownloadFilepath(const CString download_file) {
download_manager_->local_download_file_path_ = download_file;
}
void VerifyCompletionInfo(JobCompletionStatus status,
DWORD error_code,
const CString& text) {
EXPECT_EQ(status, download_manager_->error_info().status);
EXPECT_EQ(error_code, download_manager_->error_info().error_code);
EXPECT_STREQ(text, download_manager_->error_info().text);
}
scoped_ptr<Job> job_;
scoped_ptr<DownloadManager> download_manager_;
Ping ping_;
static CString cache_test_dir_;
static CString expected_file_name_exe_;
static CString expected_file_name_msi_;
};
CString DownloadManagerTest::cache_test_dir_;
CString DownloadManagerTest::expected_file_name_exe_;
CString DownloadManagerTest::expected_file_name_msi_;
// Download a file via an http: URL.
TEST_F(DownloadManagerTest, DownloadViaHttp) {
Initialize(false);
scoped_ptr<Job> job1(CreateJob());
EXPECT_HRESULT_SUCCEEDED(job1->Download(download_manager_.get()));
EXPECT_TRUE(::DeleteFile(job1->download_file_name()));
scoped_ptr<Job> job2(CreateJob());
EXPECT_HRESULT_SUCCEEDED(job2->Download(download_manager_.get()));
EXPECT_TRUE(::DeleteFile(job2->download_file_name()));
}
TEST_F(DownloadManagerTest, BuildDestinationDirectory_User) {
Initialize(false);
CString path = ConfigManager::Instance()->GetUserDownloadStorageDir();
CString dir;
EXPECT_HRESULT_SUCCEEDED(BuildDestinationDirectory(&dir));
CString common_prefix;
int common_path_len = ::PathCommonPrefix(dir,
path,
CStrBuf(common_prefix, MAX_PATH));
EXPECT_EQ(path.GetLength(), common_path_len);
EXPECT_STREQ(common_prefix, path);
CString dir2;
EXPECT_HRESULT_SUCCEEDED(BuildDestinationDirectory(&dir2));
CString common_prefix2;
common_path_len = ::PathCommonPrefix(dir2,
path,
CStrBuf(common_prefix2, MAX_PATH));
EXPECT_EQ(path.GetLength(), common_path_len);
EXPECT_STREQ(common_prefix2, path);
EXPECT_STRNE(dir, dir2);
}
TEST_F(DownloadManagerTest, BuildUniqueDownloadFilePath_User) {
Initialize(false);
CString file;
EXPECT_HRESULT_SUCCEEDED(BuildUniqueDownloadFilePath(&file));
CString str_guid = GetFileFromPath(file);
EXPECT_TRUE(!str_guid.IsEmpty());
GUID guid = StringToGuid(str_guid);
EXPECT_TRUE(!::IsEqualGUID(guid, GUID_NULL));
}
TEST_F(DownloadManagerTest, BuildDestinationDirectory_Machine) {
if (!vista_util::IsUserAdmin()) {
return;
}
Initialize(true);
CString path =
ConfigManager::Instance()->GetMachineSecureDownloadStorageDir();
CString dir;
EXPECT_HRESULT_SUCCEEDED(BuildDestinationDirectory(&dir));
CString common_prefix;
int common_path_len = ::PathCommonPrefix(dir,
path,
CStrBuf(common_prefix, MAX_PATH));
EXPECT_EQ(path.GetLength(), common_path_len);
EXPECT_STREQ(common_prefix, path);
CString dir2;
EXPECT_HRESULT_SUCCEEDED(BuildDestinationDirectory(&dir2));
CString common_prefix2;
common_path_len = ::PathCommonPrefix(dir2,
path,
CStrBuf(common_prefix2, MAX_PATH));
EXPECT_EQ(path.GetLength(), common_path_len);
EXPECT_STREQ(common_prefix2, path);
EXPECT_STRNE(dir, dir2);
}
TEST_F(DownloadManagerTest, BuildUniqueDownloadFilePath_Machine) {
if (!vista_util::IsUserAdmin()) {
return;
}
Initialize(true);
CString file;
EXPECT_HRESULT_SUCCEEDED(BuildUniqueDownloadFilePath(&file));
CString str_guid = GetFileFromPath(file);
EXPECT_TRUE(!str_guid.IsEmpty());
GUID guid = StringToGuid(str_guid);
EXPECT_TRUE(!::IsEqualGUID(guid, GUID_NULL));
}
TEST_F(DownloadManagerTest, IsCached_TestExe) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/livelysetup.exe"));
response_data.set_hash(kTestExeHash);
response_data.set_size(kTestExeSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_TRUE(IsCached(cache_test_dir_));
EXPECT_STREQ(expected_file_name_exe_, job->download_file_name());
}
TEST_F(DownloadManagerTest, IsCached_TestMSI) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/gears-win32-opt.msi"));
response_data.set_hash(kTestMsiHash);
response_data.set_size(kTestMsiSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_TRUE(IsCached(cache_test_dir_));
EXPECT_STREQ(expected_file_name_msi_, job->download_file_name());
}
TEST_F(DownloadManagerTest, IsCached_FileNotPresent) {
UpdateResponseData response_data;
response_data.set_url(_T("dl.google.com/not_present.msi"));
response_data.set_hash(kTestMsiHash);
response_data.set_size(kTestMsiSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_FALSE(IsCached(cache_test_dir_));
EXPECT_TRUE(job->download_file_name().IsEmpty());
}
TEST_F(DownloadManagerTest, IsCached_InvalidHash) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/gears-win32-opt.msi"));
response_data.set_hash(_T("BAADBAADBAADMjs32vbZTvzAYJU="));
response_data.set_size(kTestMsiSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_FALSE(IsCached(cache_test_dir_));
EXPECT_TRUE(job->download_file_name().IsEmpty());
}
TEST_F(DownloadManagerTest, IsCached_NotUpdateJob) {
scoped_ptr<Job> job(new Job(false, &ping_));
UpdateResponseData response_data;
response_data.set_url(_T("dl.google.com/livelysetup.exe"));
response_data.set_hash(kTestExeHash);
response_data.set_size(kTestExeSize);
job->set_update_response_data(response_data);
SetJob(job.get());
EXPECT_FALSE(IsCached(cache_test_dir_));
EXPECT_TRUE(job->download_file_name().IsEmpty());
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_Valid) {
UpdateResponseData response_data;
response_data.set_url(_T("dl.google.com/livelysetup.exe"));
response_data.set_hash(kTestExeHash);
response_data.set_size(kTestExeSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
SetLocalDownloadFilepath(expected_file_name_exe_);
EXPECT_SUCCEEDED(ValidateDownloadedFile(expected_file_name_exe_));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_HashFailsCorrectSize) {
UpdateResponseData response_data;
response_data.set_url(_T("dl.google.com/livelysetup.exe"));
response_data.set_hash(kWrongTestExeHash);
response_data.set_size(kTestExeSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
SetLocalDownloadFilepath(expected_file_name_exe_);
EXPECT_EQ(SIGS_E_INVALID_SIGNATURE,
ValidateDownloadedFile(expected_file_name_exe_));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_ValidHashSizeIncorrect) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/livelysetup.exe"));
response_data.set_hash(kTestExeHash);
response_data.set_size(kTestExeSize + 10);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_SUCCEEDED(ValidateDownloadedFile(expected_file_name_exe_));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_HashFailsSizeZero) {
const TCHAR kEmtpyFileName[] = _T("emptyfile.txt");
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/livelysetup.exe"));
response_data.set_hash(kWrongTestExeHash);
response_data.set_size(kTestExeSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_SUCCEEDED(File::Remove(kEmtpyFileName));
File empty_file;
EXPECT_SUCCEEDED(empty_file.Open(kEmtpyFileName, true, false));
EXPECT_SUCCEEDED(empty_file.Close());
EXPECT_EQ(GOOPDATEDOWNLOAD_E_FILE_SIZE_ZERO,
ValidateDownloadedFile(kEmtpyFileName));
EXPECT_SUCCEEDED(File::Remove(kEmtpyFileName));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_HashFailsSizeSmaller) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/livelysetup.exe"));
response_data.set_hash(kWrongTestExeHash);
response_data.set_size(kTestExeSize + 1);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_EQ(GOOPDATEDOWNLOAD_E_FILE_SIZE_SMALLER,
ValidateDownloadedFile(expected_file_name_exe_));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_HashFailsSizeLarger) {
UpdateResponseData response_data;
response_data.set_url(_T("dl.google.com/livelysetup.exe"));
response_data.set_hash(kWrongTestExeHash);
response_data.set_size(kTestExeSize - 1);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
EXPECT_EQ(GOOPDATEDOWNLOAD_E_FILE_SIZE_LARGER,
ValidateDownloadedFile(expected_file_name_exe_));
}
TEST_F(DownloadManagerTest, ValidateDownloadedFile_FileDoesNotExist) {
UpdateResponseData response_data;
response_data.set_url(_T("http://dl.google.com/livelysetup.exe"));
response_data.set_hash(kWrongTestExeHash);
response_data.set_size(kTestExeSize);
scoped_ptr<Job> job(CreateJob(response_data));
SetJob(job.get());
ExpectAsserts expect_asserts;
EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
ValidateDownloadedFile(_T("nosuchfile.txt")));
}
TEST_F(DownloadManagerTest, GetFileNameFromDownloadUrl_QueryParams) {
SetJob(CreateJob());
CString url = _T("http://foo10.bar.google.com:26190/update2/test/machinefoo/test.msi?tttoken=1.DQAAA3_cykoeVgF7b8ZT1Ycsv_tfjbAofLplQp3xHrwOOJGZkb1ZakYVTIN0QMJvA5IlMzULa0AEP-JWYZVVKz-gQTD35u30pRAirXjKjsEC5KHKQKqBipa00ni8krbzYawfTKQKAAmlTan_eLHDOnH7NiHcrCLkLSE_5Un1S7p5_DegLgFGfUXffwHS6S-Z5LHCHdqUXCW&test=10&hello"); // NOLINT
CString file_name;
ASSERT_HRESULT_SUCCEEDED(GetFileNameFromDownloadUrl(url, &file_name));
ASSERT_STREQ(_T("test.msi"), file_name);
}
TEST_F(DownloadManagerTest, GetFileNameFromDownloadUrl_NoQueryParams) {
SetJob(CreateJob());
CString url = _T("http://foo10.google.com:26190/test/machinefoo/test.msi");
CString file_name;
ASSERT_HRESULT_SUCCEEDED(GetFileNameFromDownloadUrl(url, &file_name));
ASSERT_STREQ(_T("test.msi"), file_name);
url = _T("http://dl.google.com/update2/1.2.121.9/GoogleUpdateSetup.exe");
ASSERT_HRESULT_SUCCEEDED(GetFileNameFromDownloadUrl(url, &file_name));
ASSERT_STREQ(_T("GoogleUpdateSetup.exe"), file_name);
url = _T("http://dl.google.com/foo/plugin/4.3.9543.7852/foo-plugin-win.exe");
ASSERT_HRESULT_SUCCEEDED(GetFileNameFromDownloadUrl(url, &file_name));
ASSERT_STREQ(_T("foo-plugin-win.exe"), file_name);
}
TEST_F(DownloadManagerTest, GetFileNameFromDownloadUrl_WithOutPath) {
SetJob(CreateJob());
CString url = _T("http://foo10.bar.google.com:26190/test.exe");
CString file_name;
ASSERT_HRESULT_SUCCEEDED(GetFileNameFromDownloadUrl(url, &file_name));
ASSERT_STREQ(_T("test.exe"), file_name);
}
TEST_F(DownloadManagerTest, GetFileNameFromDownloadUrl_InvalidPaths) {
SetJob(CreateJob());
CString url = _T("http://foo10.bar.google.com:26190/test/");
CString file_name;
EXPECT_HRESULT_FAILED(GetFileNameFromDownloadUrl(url, &file_name));
url = _T("http://foo10.bar.google.com:26190/test/?");
EXPECT_EQ(GOOPDATEDOWNLOAD_E_FILE_NAME_EMPTY,
GetFileNameFromDownloadUrl(url, &file_name));
url = _T("foo10.bar.google.com:26190test");
EXPECT_HRESULT_FAILED(GetFileNameFromDownloadUrl(url, &file_name));
}
TEST_F(DownloadManagerTest, SetErrorInfo) {
AppData app_data;
app_data.set_display_name(_T("Test App"));
Job job(false, &ping_);
job.set_app_data(app_data);
SetJob(&job);
SetErrorInfo(GOOPDATE_E_NO_NETWORK);
VerifyCompletionInfo(
COMPLETION_ERROR,
static_cast<DWORD>(GOOPDATE_E_NO_NETWORK),
_T("Installation failed. Ensure that your computer is connected to the ")
_T("Internet and that your firewall allows GoogleUpdate.exe to connect ")
_T("and then try again. Error code = 0x80040801."));
SetErrorInfo(GOOPDATE_E_NETWORK_UNAUTHORIZED);
VerifyCompletionInfo(
COMPLETION_ERROR,
static_cast<DWORD>(GOOPDATE_E_NETWORK_UNAUTHORIZED),
_T("The Test App installer could not connect to the Internet because of ")
_T("an HTTP 401 Unauthorized response. This is likely a proxy ")
_T("configuration issue. Please configure the proxy server to allow ")
_T("network access and try again or contact your network administrator. ")
_T("Error code = 0x80042191"));
SetErrorInfo(GOOPDATE_E_NETWORK_FORBIDDEN);
VerifyCompletionInfo(
COMPLETION_ERROR,
static_cast<DWORD>(GOOPDATE_E_NETWORK_FORBIDDEN),
_T("The Test App installer could not connect to the Internet because of ")
_T("an HTTP 403 Forbidden response. This is likely a proxy ")
_T("configuration issue. Please configure the proxy server to allow ")
_T("network access and try again or contact your network administrator. ")
_T("Error code = 0x80042193"));
SetErrorInfo(GOOPDATE_E_NETWORK_PROXYAUTHREQUIRED);
VerifyCompletionInfo(
COMPLETION_ERROR,
static_cast<DWORD>(GOOPDATE_E_NETWORK_PROXYAUTHREQUIRED),
_T("The Test App installer could not connect to the Internet because a ")
_T("proxy server required user authentication. Please configure the ")
_T("proxy server to allow network access and try again or contact your ")
_T("network administrator. Error code = 0x80042197"));
SetErrorInfo(E_FAIL);
VerifyCompletionInfo(
COMPLETION_ERROR,
static_cast<DWORD>(E_FAIL),
_T("Installer download failed. Error code = 0x80004005"));
}
} // namespace omaha