Chromium Code Reviews| Index: components/os_crypt/os_crypt_util_linux_unittest.cc |
| diff --git a/components/os_crypt/os_crypt_util_linux_unittest.cc b/components/os_crypt/os_crypt_util_linux_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d425dc944e8e5ab3022423ce98a4adbc43e0b057 |
| --- /dev/null |
| +++ b/components/os_crypt/os_crypt_util_linux_unittest.cc |
| @@ -0,0 +1,239 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <memory> |
| +#include <string> |
| +#include <utility> |
| + |
| +#include "base/logging.h" |
| +#include "base/macros.h" |
| +#include "components/os_crypt/key_storage_libsecret.h" |
| +#include "components/os_crypt/key_storage_linux.h" |
| +#include "components/os_crypt/key_storage_mock.h" |
| +#include "components/os_crypt/libsecret_util_linux.h" |
| +#include "components/os_crypt/os_crypt.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace { |
| + |
| +typedef std::string MockSecretValue; |
|
Lei Zhang
2016/05/19 22:45:38
using foo = bar, instead of typedef bar foo.
cfroussios
2016/05/20 16:44:52
Done.
|
| + |
| +// Replaces some of LibsecretLoader's methods with mocked ones. |
| +class MockLibsecretLoader : public LibsecretLoader { |
| + public: |
| + // Sets up the minimum mock implementation necessary for |Libsecret| to work. |
| + // Also resets the state to mock a clean database. |
| + static bool ResetForOSCrypt(); |
| + |
| + // Set OSCrypt's password in the libsecret mock to a specific value |
|
Lei Zhang
2016/05/19 22:45:38
Sets
cfroussios
2016/05/20 16:44:52
Done.
|
| + static void SetOSCryptPassword(const char*); |
| + |
| + // Releases memory and restores LibsecretLoader to an uninitialized state. |
| + static void TearDown(); |
| + |
| + private: |
| + static std::string* stored_password_mock_ptr_; |
| + |
| + // These methods are used to redirect calls through LibsecretLoader |
| + static const gchar* mock_secret_value_get_text(MockSecretValue* value); |
| + |
| + static gboolean mock_secret_password_store_sync(const SecretSchema* schema, |
| + const gchar* collection, |
| + const gchar* label, |
| + const gchar* password, |
| + GCancellable* cancellable, |
| + GError** error, |
| + ...); |
| + |
| + static MockSecretValue* mock_secret_service_lookup_sync( |
| + SecretService* service, |
| + const SecretSchema* schema, |
| + GHashTable* attributes, |
| + GCancellable* cancellable, |
| + GError** error); |
| + |
| + static void mock_secret_value_unref(gpointer value); |
| + |
| + static GList* mock_secret_service_search_sync(SecretService* service, |
| + const SecretSchema* schema, |
| + GHashTable* attributes, |
| + SecretSearchFlags flags, |
| + GCancellable* cancellable, |
| + GError** error); |
| +}; |
| + |
| +MockSecretValue* MockLibsecretLoader::stored_password_mock_ptr_ = nullptr; |
| + |
| +const gchar* MockLibsecretLoader::mock_secret_value_get_text( |
| + MockSecretValue* value) { |
| + return value->c_str(); |
| +} |
| + |
| +gboolean MockLibsecretLoader::mock_secret_password_store_sync( |
| + const SecretSchema* schema, |
| + const gchar* collection, |
| + const gchar* label, |
| + const gchar* password, |
| + GCancellable* cancellable, |
| + GError** error, |
| + ...) { |
| + delete stored_password_mock_ptr_; |
| + stored_password_mock_ptr_ = new MockSecretValue(password); |
| + return true; |
| +} |
| + |
| +MockSecretValue* MockLibsecretLoader::mock_secret_service_lookup_sync( |
| + SecretService* service, |
| + const SecretSchema* schema, |
| + GHashTable* attributes, |
| + GCancellable* cancellable, |
| + GError** error) { |
| + return stored_password_mock_ptr_; |
| +} |
| + |
| +void MockLibsecretLoader::mock_secret_value_unref(gpointer value) {} |
| + |
| +GList* MockLibsecretLoader::mock_secret_service_search_sync( |
| + SecretService* service, |
| + const SecretSchema* schema, |
| + GHashTable* attributes, |
| + SecretSearchFlags flags, |
| + GCancellable* cancellable, |
| + GError** error) { |
| + *error = nullptr; |
| + return nullptr; |
| +} |
| + |
| +// static |
| +bool MockLibsecretLoader::ResetForOSCrypt() { |
| + // 4 methods used by Libsecret.GetPassword(); |
| + secret_password_store_sync = |
| + &MockLibsecretLoader::mock_secret_password_store_sync; |
| + secret_value_get_text = (decltype(&::secret_value_get_text)) & |
| + MockLibsecretLoader::mock_secret_value_get_text; |
| + secret_value_unref = &MockLibsecretLoader::mock_secret_value_unref; |
| + secret_service_lookup_sync = |
| + (decltype(&::secret_service_lookup_sync)) & |
| + MockLibsecretLoader::mock_secret_service_lookup_sync; |
| + // 1 method used by LibsecretLoader::EnsureLibsecretLoaded |
| + secret_service_search_sync = |
| + &MockLibsecretLoader::mock_secret_service_search_sync; |
| + |
| + delete stored_password_mock_ptr_; |
| + stored_password_mock_ptr_ = nullptr; |
| + libsecret_loaded_ = true; |
| + |
| + return true; |
| +} |
| + |
| +void MockLibsecretLoader::SetOSCryptPassword(const char* value) { |
| + delete stored_password_mock_ptr_; |
| + stored_password_mock_ptr_ = new MockSecretValue(value); |
| +} |
| + |
| +void MockLibsecretLoader::TearDown() { |
| + delete stored_password_mock_ptr_; |
| + stored_password_mock_ptr_ = nullptr; |
| + libsecret_loaded_ = false; // function pointers will be restored when loading |
| +} |
| + |
| +class OSCryptLinuxTest : public testing::Test { |
| + public: |
| + OSCryptLinuxTest() = default; |
| + ~OSCryptLinuxTest() override = default; |
| + |
| + void SetUp() override { |
| + key_storage_static_ = &key_storage_; |
| + UseMockKeyStorageForTesting(true, &GetKeyStorage, &GetPassword); |
| + } |
| + |
| + void TearDown() override { |
| + key_storage_static_ = nullptr; |
| + UseMockKeyStorageForTesting(false, nullptr, nullptr); |
| + } |
| + |
| + protected: |
| + KeyStorageMock key_storage_; |
| + |
| + private: |
| + // Needed, so that we can return our |key_storage_| through static methods |
| + static KeyStorageMock* key_storage_static_; |
| + |
| + static KeyStorageLinux* GetKeyStorage() { return key_storage_static_; } |
| + |
| + static std::string* GetPassword() { return key_storage_static_->GetKeyPtr(); } |
| + |
| + DISALLOW_COPY_AND_ASSIGN(OSCryptLinuxTest); |
| +}; |
| + |
| +KeyStorageMock* OSCryptLinuxTest::key_storage_static_ = nullptr; |
| + |
| +TEST_F(OSCryptLinuxTest, VerifyV0) { |
| + const std::string originaltext = "hello"; |
| + std::string ciphertext; |
| + std::string decipheredtext; |
| + |
| + key_storage_.ResetTo(""); |
| + ciphertext = originaltext; // No encryption |
| + ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decipheredtext)); |
| + ASSERT_EQ(originaltext, decipheredtext); |
| +} |
| + |
| +TEST_F(OSCryptLinuxTest, VerifyV10) { |
| + const std::string originaltext = "hello"; |
| + std::string ciphertext; |
| + std::string decipheredtext; |
| + |
| + key_storage_.ResetTo("peanuts"); |
| + ASSERT_TRUE(OSCrypt::EncryptString(originaltext, &ciphertext)); |
| + key_storage_.ResetTo("not_peanuts"); |
| + ciphertext = ciphertext.substr(3).insert(0, "v10"); |
| + ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decipheredtext)); |
| + ASSERT_EQ(originaltext, decipheredtext); |
| +} |
| + |
| +TEST_F(OSCryptLinuxTest, VerifyV11) { |
| + const std::string originaltext = "hello"; |
| + std::string ciphertext; |
| + std::string decipheredtext; |
| + |
| + key_storage_.ResetTo(""); |
| + ASSERT_TRUE(OSCrypt::EncryptString(originaltext, &ciphertext)); |
| + ASSERT_EQ(ciphertext.substr(0, 3), "v11"); |
| + ASSERT_TRUE(OSCrypt::DecryptString(ciphertext, &decipheredtext)); |
| + ASSERT_EQ(originaltext, decipheredtext); |
| +} |
| + |
| +class LibsecretTest : public testing::Test { |
| + public: |
| + LibsecretTest() = default; |
| + ~LibsecretTest() override = default; |
| + |
| + void SetUp() override { MockLibsecretLoader::ResetForOSCrypt(); } |
| + |
| + void TearDown() override { MockLibsecretLoader::TearDown(); } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(LibsecretTest); |
| +}; |
| + |
| +TEST_F(LibsecretTest, LibsecretRepeats) { |
| + KeyStorageLibsecret libsecret; |
| + MockLibsecretLoader::ResetForOSCrypt(); |
| + std::string password = libsecret.GetKey(); |
| + EXPECT_FALSE(password.empty()); |
| + std::string password_repeat = libsecret.GetKey(); |
| + EXPECT_EQ(password, password_repeat); |
| +} |
| + |
| +TEST_F(LibsecretTest, LibsecretCreatesRandomised) { |
| + KeyStorageLibsecret libsecret; |
| + MockLibsecretLoader::ResetForOSCrypt(); |
| + std::string password = libsecret.GetKey(); |
| + MockLibsecretLoader::ResetForOSCrypt(); |
| + std::string password_new = libsecret.GetKey(); |
| + EXPECT_NE(password, password_new); |
| +} |
| + |
| +} // namespace |