This source file includes following definitions.
- SetUp
- TearDown
- CompareBuffers
- WStringPairListSize
- TEST_F
- TEST_F
- TEST_F
#include <windows.h>
#include <shlobj.h>
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_util.h"
#include "base/win/registry.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class DeleteAfterRebootHelperTest : public testing::Test {
protected:
virtual void SetUp() {
base::CreateNewTempDirectory(base::FilePath::StringType(), &temp_dir_);
base::CreateTemporaryFileInDir(temp_dir_, &temp_file_);
temp_subdir_ = temp_dir_.Append(L"subdir");
base::CreateDirectory(temp_subdir_);
base::CreateTemporaryFileInDir(temp_subdir_, &temp_subdir_file_);
if (IsUserAnAdmin()) {
GetPendingMovesValue(&original_pending_moves_);
}
}
virtual void TearDown() {
base::DeleteFile(temp_dir_, true);
if (IsUserAnAdmin() && original_pending_moves_.size() > 1) {
base::win::RegKey session_manager_key(
HKEY_LOCAL_MACHINE, kSessionManagerKey,
KEY_CREATE_SUB_KEY | KEY_SET_VALUE);
if (!session_manager_key.Handle()) {
DLOG(ERROR) << "Failed to open session manager key for writing.";
}
std::vector<char> buffer;
StringArrayToMultiSZBytes(original_pending_moves_, &buffer);
session_manager_key.WriteValue(kPendingFileRenameOps, &buffer[0],
buffer.size(), REG_MULTI_SZ);
}
}
template<class Type>
bool CompareBuffers(Type* buf1, Type* buf2, int len) {
Type* comp1 = buf1;
Type* comp2 = buf2;
for (int i = 0; i < len; i++) {
if (*comp1 != *comp2)
return false;
comp1++;
comp2++;
}
return true;
}
virtual size_t WStringPairListSize(
const std::vector<PendingMove>& string_list) {
size_t length = 0;
std::vector<PendingMove>::const_iterator iter(string_list.begin());
for (; iter != string_list.end(); ++iter) {
length += iter->first.size() + 1;
length += iter->second.size() + 1;
}
length++;
return length * sizeof(wchar_t);
}
std::vector<PendingMove> original_pending_moves_;
base::FilePath temp_dir_;
base::FilePath temp_file_;
base::FilePath temp_subdir_;
base::FilePath temp_subdir_file_;
};
}
TEST_F(DeleteAfterRebootHelperTest, TestStringListToMultiSZConversions) {
struct StringTest {
wchar_t* test_name;
wchar_t* str;
DWORD length;
size_t count;
} tests[] = {
{ L"basic", L"foo\0bar\0fee\0bee\0boo\0bong\0\0", 26 * sizeof(wchar_t), 3 },
{ L"empty", L"\0\0", 2 * sizeof(wchar_t), 1 },
{ L"deletes", L"foo\0\0bar\0\0bizz\0\0", 16 * sizeof(wchar_t), 3 },
};
for (int i = 0; i < arraysize(tests); i++) {
std::vector<PendingMove> string_list;
EXPECT_TRUE(SUCCEEDED(
MultiSZBytesToStringArray(reinterpret_cast<char*>(tests[i].str),
tests[i].length, &string_list)))
<< tests[i].test_name;
EXPECT_EQ(tests[i].count, string_list.size()) << tests[i].test_name;
std::vector<char> buffer;
buffer.resize(WStringPairListSize(string_list));
StringArrayToMultiSZBytes(string_list, &buffer);
EXPECT_TRUE(CompareBuffers(&buffer[0],
reinterpret_cast<char*>(tests[i].str),
tests[i].length)) << tests[i].test_name;
}
StringTest failures[] =
{ L"malformed", reinterpret_cast<wchar_t*>("oddnumb\0\0"), 9, 1 };
for (int i = 0; i < arraysize(failures); i++) {
std::vector<PendingMove> string_list;
EXPECT_FALSE(SUCCEEDED(
MultiSZBytesToStringArray(reinterpret_cast<char*>(failures[i].str),
failures[i].length, &string_list)))
<< failures[i].test_name;
}
}
TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteScheduleAndUnschedule) {
if (!IsUserAnAdmin()) {
return;
}
EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
EXPECT_GT(pending_moves.size(), 3U);
base::FilePath short_temp_file(GetShortPathName(temp_file_));
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
base::FilePath move_path(iter->first);
if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
base::FilePath expected_paths[] =
{ temp_file_, temp_subdir_file_, temp_subdir_, temp_dir_ };
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
base::FilePath move_path(iter->first);
EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
base::FilePath move_path(check_iter->first);
EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}
TEST_F(DeleteAfterRebootHelperTest, TestFileDeleteSchedulingWithActualDeletes) {
if (!IsUserAnAdmin()) {
return;
}
std::vector<PendingMove> initial_pending_moves;
GetPendingMovesValue(&initial_pending_moves);
size_t initial_pending_moves_size = initial_pending_moves.size();
EXPECT_TRUE(ScheduleDirectoryForDeletion(temp_dir_));
std::vector<PendingMove> pending_moves;
EXPECT_TRUE(SUCCEEDED(GetPendingMovesValue(&pending_moves)));
EXPECT_TRUE(pending_moves.size() > 3);
base::FilePath short_temp_file(GetShortPathName(temp_file_));
std::vector<PendingMove>::const_iterator iter(pending_moves.begin());
for (; iter != pending_moves.end(); iter++) {
base::FilePath move_path(iter->first);
if (MatchPendingDeletePath(short_temp_file, move_path))
break;
}
base::FilePath expected_paths[] =
{ temp_file_, temp_subdir_file_, temp_subdir_, temp_dir_ };
for (int i = 0; i < arraysize(expected_paths); ++i) {
EXPECT_FALSE(iter == pending_moves.end());
if (iter != pending_moves.end()) {
base::FilePath short_path_name(GetShortPathName(expected_paths[i]));
base::FilePath move_path(iter->first);
EXPECT_TRUE(MatchPendingDeletePath(short_path_name, move_path));
++iter;
}
}
base::DeleteFile(temp_dir_, true);
EXPECT_TRUE(RemoveFromMovesPendingReboot(temp_dir_));
HRESULT hr = GetPendingMovesValue(&pending_moves);
EXPECT_TRUE(hr == S_OK || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
EXPECT_EQ(initial_pending_moves_size, pending_moves.size());
std::vector<PendingMove>::const_iterator check_iter(pending_moves.begin());
for (; check_iter != pending_moves.end(); ++check_iter) {
base::FilePath move_path(check_iter->first);
EXPECT_FALSE(MatchPendingDeletePath(short_temp_file, move_path));
}
}