Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome_elf / blacklist / test / blacklist_test.cc
index 07623cd..22edf6e 100644 (file)
@@ -15,6 +15,7 @@
 #include "base/win/registry.h"
 #include "chrome_elf/blacklist/blacklist.h"
 #include "chrome_elf/blacklist/test/blacklist_test_main_dll.h"
+#include "chrome_elf/chrome_elf_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "version.h"  // NOLINT
 
@@ -31,15 +32,35 @@ extern "C" {
 // When modifying the blacklist in the test process, use the exported test dll
 // functions on the test blacklist dll, not the ones linked into the test
 // executable itself.
+__declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist();
 __declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name);
+__declspec(dllimport) bool TestDll_IsBlacklistInitialized();
 __declspec(dllimport) bool TestDll_RemoveDllFromBlacklist(
     const wchar_t* dll_name);
+__declspec(dllimport) bool TestDll_SuccessfullyBlocked(
+    const wchar_t** blocked_dlls,
+    int* size);
 }
 
+namespace {
+
 class BlacklistTest : public testing::Test {
+ protected:
+  BlacklistTest() : override_manager_() {
+    override_manager_.OverrideRegistry(HKEY_CURRENT_USER, L"beacon_test");
+  }
+
+  scoped_ptr<base::win::RegKey> blacklist_registry_key_;
+  registry_util::RegistryOverrideManager override_manager_;
+
+ private:
   virtual void SetUp() {
     // Force an import from blacklist_test_main_dll.
     InitBlacklistTestDll();
+    blacklist_registry_key_.reset(
+        new base::win::RegKey(HKEY_CURRENT_USER,
+                              blacklist::kRegistryBeaconPath,
+                              KEY_QUERY_VALUE | KEY_SET_VALUE));
   }
 
   virtual void TearDown() {
@@ -49,21 +70,29 @@ class BlacklistTest : public testing::Test {
   }
 };
 
-TEST_F(BlacklistTest, Beacon) {
-  registry_util::RegistryOverrideManager override_manager;
-  override_manager.OverrideRegistry(HKEY_CURRENT_USER, L"beacon_test");
-
-  base::win::RegKey blacklist_registry_key(HKEY_CURRENT_USER,
-                                           blacklist::kRegistryBeaconPath,
-                                           KEY_QUERY_VALUE | KEY_SET_VALUE);
+struct TestData {
+  const wchar_t* dll_name;
+  const wchar_t* dll_beacon;
+} test_data[] = {
+    {kTestDllName2, kDll2Beacon},
+#if !defined(_WIN64)
+    // The third test dll is special in that it does not contain an export
+    // table. This prevents SafeGetImageInfo from extracting the name from there
+    // AND for some reason NtQueryVirtualMemory with MemorySectionName returns
+    // STATUS_ACCESS_VIOLATION in 64 bit builds for reasons still unknown.
+    // http://crbug.com/397137
+    {kTestDllName3, kDll3Beacon}
+#endif
+};
 
-  // Ensure that the beacon state starts off enabled for this version.
-  LONG result = blacklist_registry_key.WriteValue(blacklist::kBeaconState,
-                                                  blacklist::BLACKLIST_ENABLED);
+TEST_F(BlacklistTest, Beacon) {
+  // Ensure that the beacon state starts off 'running' for this version.
+  LONG result = blacklist_registry_key_->WriteValue(
+      blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING);
   EXPECT_EQ(ERROR_SUCCESS, result);
 
-  result = blacklist_registry_key.WriteValue(blacklist::kBeaconVersion,
-                                             TEXT(CHROME_VERSION_STRING));
+  result = blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
+                                               TEXT(CHROME_VERSION_STRING));
   EXPECT_EQ(ERROR_SUCCESS, result);
 
   // First call should find the beacon and reset it.
@@ -71,23 +100,6 @@ TEST_F(BlacklistTest, Beacon) {
 
   // First call should succeed as the beacon is enabled.
   EXPECT_TRUE(blacklist::LeaveSetupBeacon());
-
-  // Second call should fail indicating the beacon wasn't set as enabled.
-  EXPECT_FALSE(blacklist::LeaveSetupBeacon());
-
-  // Resetting the beacon should work when setup beacon is present.
-  EXPECT_TRUE(blacklist::ResetBeacon());
-
-  // Change the version and ensure that the setup fails due to the version
-  // mismatch.
-  base::string16 different_version(L"other_version");
-  ASSERT_NE(different_version, TEXT(CHROME_VERSION_STRING));
-
-  result = blacklist_registry_key.WriteValue(blacklist::kBeaconVersion,
-                                             different_version.c_str());
-  EXPECT_EQ(ERROR_SUCCESS, result);
-
-  EXPECT_FALSE(blacklist::LeaveSetupBeacon());
 }
 
 TEST_F(BlacklistTest, AddAndRemoveModules) {
@@ -116,35 +128,55 @@ TEST_F(BlacklistTest, AddAndRemoveModules) {
     added_dlls[empty_spaces - 1].c_str()));
 }
 
-TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
-// TODO(robertshield): Add 64-bit support.
-#if !defined(_WIN64)
+TEST_F(BlacklistTest, SuccessfullyBlocked) {
+  // Ensure that we have at least 5 dlls to blacklist.
+  int blacklist_size = blacklist::BlacklistSize();
+  const int kDesiredBlacklistSize = 5;
+  for (int i = blacklist_size; i < kDesiredBlacklistSize; ++i) {
+    base::string16 new_dll_name(base::IntToString16(i) + L".dll");
+    EXPECT_TRUE(blacklist::AddDllToBlacklist(new_dll_name.c_str()));
+  }
+
+  // Block 5 dlls, one at a time, starting from the end of the list, and
+  // ensuring SuccesfullyBlocked correctly passes the list of blocked dlls.
+  for (int i = 0; i < kDesiredBlacklistSize; ++i) {
+    blacklist::BlockedDll(i);
+
+    int size = 0;
+    blacklist::SuccessfullyBlocked(NULL, &size);
+    EXPECT_EQ(i + 1, size);
+
+    std::vector<const wchar_t*> blocked_dlls(size);
+    blacklist::SuccessfullyBlocked(&(blocked_dlls[0]), &size);
+    EXPECT_EQ(i + 1, size);
+
+    for (size_t j = 0; j < blocked_dlls.size(); ++j) {
+      EXPECT_EQ(blocked_dlls[j], blacklist::g_troublesome_dlls[j]);
+    }
+  }
+}
+
+void CheckBlacklistedDllsNotLoaded() {
   base::FilePath current_dir;
   ASSERT_TRUE(PathService::Get(base::DIR_EXE, &current_dir));
 
-  // Test that an un-blacklisted DLL can load correctly.
-  base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1));
-  EXPECT_TRUE(dll1.is_valid());
-  dll1.Reset(NULL);
-
-  struct TestData {
-    const wchar_t* dll_name;
-    const wchar_t* dll_beacon;
-  } test_data[] = {
-    { kTestDllName2, kDll2Beacon },
-    { kTestDllName3, kDll3Beacon }
-  };
-  for (int i = 0 ; i < arraysize(test_data); ++i) {
-    // Add the DLL to the blacklist, ensure that it is not loaded both by
-    // inspecting the handle returned by LoadLibrary and by looking for an
-    // environment variable that is set when the DLL's entry point is called.
-    EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name));
+  for (int i = 0; i < arraysize(test_data); ++i) {
+    // Ensure that the dll has not been loaded both by inspecting the handle
+    // returned by LoadLibrary and by looking for an environment variable that
+    // is set when the DLL's entry point is called.
     base::ScopedNativeLibrary dll_blacklisted(
         current_dir.Append(test_data[i].dll_name));
     EXPECT_FALSE(dll_blacklisted.is_valid());
     EXPECT_EQ(0u, ::GetEnvironmentVariable(test_data[i].dll_beacon, NULL, 0));
     dll_blacklisted.Reset(NULL);
 
+    // Ensure that the dll is recorded as blocked.
+    int array_size = 1;
+    const wchar_t* blocked_dll = NULL;
+    TestDll_SuccessfullyBlocked(&blocked_dll, &array_size);
+    EXPECT_EQ(1, array_size);
+    EXPECT_EQ(test_data[i].dll_name, base::string16(blocked_dll));
+
     // Remove the DLL from the blacklist. Ensure that it loads and that its
     // entry point was called.
     EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(test_data[i].dll_name));
@@ -166,6 +198,139 @@ TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
     dll_blacklisted_different_case.Reset(NULL);
 
     EXPECT_TRUE(TestDll_RemoveDllFromBlacklist(uppercase_name.c_str()));
+
+    // The blocked dll was removed, so we shouldn't get anything returned
+    // here.
+    int num_blocked_dlls = 0;
+    TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls);
+    EXPECT_EQ(0, num_blocked_dlls);
   }
-#endif
 }
+
+TEST_F(BlacklistTest, LoadBlacklistedLibrary) {
+  base::FilePath current_dir;
+  ASSERT_TRUE(PathService::Get(base::DIR_EXE, &current_dir));
+
+  // Ensure that the blacklist is loaded.
+  ASSERT_TRUE(TestDll_IsBlacklistInitialized());
+
+  // Test that an un-blacklisted DLL can load correctly.
+  base::ScopedNativeLibrary dll1(current_dir.Append(kTestDllName1));
+  EXPECT_TRUE(dll1.is_valid());
+  dll1.Reset(NULL);
+
+  int num_blocked_dlls = 0;
+  TestDll_SuccessfullyBlocked(NULL, &num_blocked_dlls);
+  EXPECT_EQ(0, num_blocked_dlls);
+
+  // Add all DLLs to the blacklist then check they are blocked.
+  for (int i = 0; i < arraysize(test_data); ++i) {
+    EXPECT_TRUE(TestDll_AddDllToBlacklist(test_data[i].dll_name));
+  }
+  CheckBlacklistedDllsNotLoaded();
+}
+
+TEST_F(BlacklistTest, AddDllsFromRegistryToBlacklist) {
+  // Ensure that the blacklist is loaded.
+  ASSERT_TRUE(TestDll_IsBlacklistInitialized());
+
+  // Delete the finch registry key to clear its values.
+  base::win::RegKey key(HKEY_CURRENT_USER,
+                        blacklist::kRegistryFinchListPath,
+                        KEY_QUERY_VALUE | KEY_SET_VALUE);
+  key.DeleteKey(L"");
+
+  // Add the test dlls to the registry (with their name as both key and value).
+  base::win::RegKey finch_blacklist_registry_key(
+      HKEY_CURRENT_USER,
+      blacklist::kRegistryFinchListPath,
+      KEY_QUERY_VALUE | KEY_SET_VALUE);
+  for (int i = 0; i < arraysize(test_data); ++i) {
+    finch_blacklist_registry_key.WriteValue(test_data[i].dll_name,
+                                            test_data[i].dll_name);
+  }
+
+  TestDll_AddDllsFromRegistryToBlacklist();
+  CheckBlacklistedDllsNotLoaded();
+}
+
+void TestResetBeacon(scoped_ptr<base::win::RegKey>& key,
+                     DWORD input_state,
+                     DWORD expected_output_state) {
+  LONG result = key->WriteValue(blacklist::kBeaconState, input_state);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+
+  EXPECT_TRUE(blacklist::ResetBeacon());
+  DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
+  result = key->ReadValueDW(blacklist::kBeaconState, &blacklist_state);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+  EXPECT_EQ(expected_output_state, blacklist_state);
+}
+
+TEST_F(BlacklistTest, ResetBeacon) {
+  // Ensure that ResetBeacon resets properly on successful runs and not on
+  // failed or disabled runs.
+  TestResetBeacon(blacklist_registry_key_,
+                  blacklist::BLACKLIST_SETUP_RUNNING,
+                  blacklist::BLACKLIST_ENABLED);
+
+  TestResetBeacon(blacklist_registry_key_,
+                  blacklist::BLACKLIST_SETUP_FAILED,
+                  blacklist::BLACKLIST_SETUP_FAILED);
+
+  TestResetBeacon(blacklist_registry_key_,
+                  blacklist::BLACKLIST_DISABLED,
+                  blacklist::BLACKLIST_DISABLED);
+}
+
+TEST_F(BlacklistTest, SetupFailed) {
+  // Ensure that when the number of failed tries reaches the maximum allowed,
+  // the blacklist state is set to failed.
+  LONG result = blacklist_registry_key_->WriteValue(
+      blacklist::kBeaconState, blacklist::BLACKLIST_SETUP_RUNNING);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+
+  // Set the attempt count so that on the next failure the blacklist is
+  // disabled.
+  result = blacklist_registry_key_->WriteValue(
+      blacklist::kBeaconAttemptCount, blacklist::kBeaconMaxAttempts - 1);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+
+  EXPECT_FALSE(blacklist::LeaveSetupBeacon());
+
+  DWORD attempt_count = 0;
+  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
+                                       &attempt_count);
+  EXPECT_EQ(attempt_count, blacklist::kBeaconMaxAttempts);
+
+  DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
+  result = blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
+                                                &blacklist_state);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+  EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_FAILED);
+}
+
+TEST_F(BlacklistTest, SetupSucceeded) {
+  // Starting with the enabled beacon should result in the setup running state
+  // and the attempt counter reset to zero.
+  LONG result = blacklist_registry_key_->WriteValue(
+      blacklist::kBeaconState, blacklist::BLACKLIST_ENABLED);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+  result = blacklist_registry_key_->WriteValue(blacklist::kBeaconAttemptCount,
+                                               blacklist::kBeaconMaxAttempts);
+  EXPECT_EQ(ERROR_SUCCESS, result);
+
+  EXPECT_TRUE(blacklist::LeaveSetupBeacon());
+
+  DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
+  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
+                                       &blacklist_state);
+  EXPECT_EQ(blacklist_state, blacklist::BLACKLIST_SETUP_RUNNING);
+
+  DWORD attempt_count = blacklist::kBeaconMaxAttempts;
+  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
+                                       &attempt_count);
+  EXPECT_EQ(static_cast<DWORD>(0), attempt_count);
+}
+
+}  // namespace