Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: extensions/browser/api/lock_screen_data/data_item_unittest.cc

Issue 2934293003: The chrome.lockScreen.data API implementation (Closed)
Patch Set: remove FilePath*UTF8Unsafe methods Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: extensions/browser/api/lock_screen_data/data_item_unittest.cc
diff --git a/extensions/browser/api/lock_screen_data/data_item_unittest.cc b/extensions/browser/api/lock_screen_data/data_item_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e785c03d49593e64927927e237806e6ce8a03cb8
--- /dev/null
+++ b/extensions/browser/api/lock_screen_data/data_item_unittest.cc
@@ -0,0 +1,582 @@
+// Copyright 2017 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 "extensions/browser/api/lock_screen_data/data_item.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
+#include "base/run_loop.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/values.h"
+#include "crypto/symmetric_key.h"
+#include "extensions/browser/api/lock_screen_data/operation_result.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+namespace lock_screen_data {
+
+namespace {
+
+void WriteCallback(const base::Closure& callback,
+ OperationResult* result_out,
+ OperationResult result) {
+ *result_out = result;
+ callback.Run();
+}
+
+void DeleteCallback(const base::Closure& callback,
+ OperationResult* result_out,
+ OperationResult result) {
+ *result_out = result;
+ callback.Run();
+}
+
+void ReadCallback(const base::Closure& callback,
+ OperationResult* result_out,
+ std::unique_ptr<std::vector<char>>* content_out,
+ OperationResult result,
+ std::unique_ptr<std::vector<char>> content) {
+ *result_out = result;
+ *content_out = std::move(content);
+ callback.Run();
+}
+
+void NotCalled(const std::string& message) {
+ ADD_FAILURE() << "Not expected to be called: " << message;
+}
+
+} // namespace
+
+class DataItemTest : public testing::Test {
+ public:
+ DataItemTest() = default;
+ ~DataItemTest() override = default;
+
+ void SetUp() override {
+ task_runner_ =
+ base::CreateSequencedTaskRunnerWithTraits({base::MayBlock()});
+ ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
+ }
+
+ std::string GenerateKey(const std::string& password) {
+ std::unique_ptr<crypto::SymmetricKey> key =
+ crypto::SymmetricKey::DeriveKeyFromPassword(
+ crypto::SymmetricKey::AES, password, "salt", 1000, 256);
+ if (!key) {
+ ADD_FAILURE() << "Failed to create symmetric key";
+ return std::string();
+ }
+
+ return key->key();
+ }
+
+ void DrainTaskRunner() {
+ base::RunLoop run_loop;
+ task_runner()->PostTaskAndReply(FROM_HERE, base::Bind(&base::DoNothing),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ const base::FilePath& test_dir() const { return test_dir_.GetPath(); }
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner() {
+ return task_runner_;
+ }
+
+ private:
+ base::ScopedTempDir test_dir_;
+
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(DataItemTest);
+};
+
+TEST_F(DataItemTest, ValueConversion) {
+ DataItem item("data_id");
+
+ std::unique_ptr<base::DictionaryValue> value = item.ToValue();
+ ASSERT_TRUE(value);
+
+ {
+ DataItem converted("data_id");
+ EXPECT_TRUE(converted.InitFromValue(*value));
+
+ EXPECT_EQ("data_id", converted.id());
+ EXPECT_TRUE(converted.backing_file().empty());
+ }
+
+ item.set_backing_file(test_dir().AppendASCII("test_file"));
+
+ value = item.ToValue();
+ {
+ DataItem converted("data_id");
+ EXPECT_TRUE(converted.InitFromValue(*value));
+
+ EXPECT_EQ("data_id", converted.id());
+ EXPECT_EQ(test_dir().AppendASCII("test_file"), converted.backing_file());
+ }
+
+ {
+ DataItem converted("different_id");
+ EXPECT_FALSE(converted.InitFromValue(*value));
+
+ EXPECT_EQ("different_id", converted.id());
+ EXPECT_TRUE(converted.backing_file().empty());
+ }
+}
+
+TEST_F(DataItemTest, WriteLocation) {
+ DataItem item("data_id");
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, write_result);
+
+ EXPECT_TRUE(
+ base::PathExists(test_dir().AppendASCII("app").AppendASCII("test_file")));
+
+ OperationResult delete_result = OperationResult::kFailed;
+ {
+ base::RunLoop run_loop;
+ item.Delete(
+ task_runner(),
+ base::Bind(&DeleteCallback, run_loop.QuitClosure(), &delete_result));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, delete_result);
+ EXPECT_FALSE(
+ base::PathExists(test_dir().AppendASCII("app").AppendASCII("test_file")));
+}
+
+TEST_F(DataItemTest, ReadWrite) {
+ DataItem item("data_id");
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ EXPECT_EQ(
+ OperationResult::kNoBackingFile,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback,
+ base::Bind(&NotCalled,
+ "Writing item with no backing file"),
+ &write_result)));
+
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, write_result);
+
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Read(key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ ASSERT_EQ(OperationResult::kSuccess, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_EQ(content, *read_content);
+
+ std::string different_key = GenerateKey("key_2");
+ ASSERT_FALSE(different_key.empty());
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Read(different_key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ ASSERT_EQ(OperationResult::kWrongKey, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_TRUE(read_content->empty());
+}
+
+TEST_F(DataItemTest, ReadFromNonexistentSource) {
+ DataItem item("data_id");
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+
+ EXPECT_EQ(
+ OperationResult::kNoBackingFile,
+ item.Read(key, task_runner(),
+ base::Bind(
+ &ReadCallback,
+ base::Bind(&NotCalled, "Reading item with no backing file"),
+ &read_result, &read_content)));
+
+ item.set_backing_file(test_dir().AppendASCII("nonexistent"));
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Read(key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kNotFound, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_TRUE(read_content->empty());
+}
+
+TEST_F(DataItemTest, ReadOldFile) {
+ std::unique_ptr<DataItem> writer = base::MakeUnique<DataItem>("data_id");
+ writer->set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ writer->Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ writer.reset();
+
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+
+ std::unique_ptr<DataItem> reader = base::MakeUnique<DataItem>("data_id");
+ reader->set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ reader->Read(key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_EQ(content, *read_content);
+}
+
+TEST_F(DataItemTest, RepeatedWrite) {
+ DataItem item("data_id");
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> first_write = {'f', 'i', 'l', 'e', '_', '1'};
+ std::vector<char> second_write = {'f', 'i', 'l', 'e', '_', '2'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(
+ OperationResult::kPending,
+ item.Write(first_write, key, task_runner(),
+ base::Bind(&WriteCallback, base::Bind(&base::DoNothing),
+ &write_result)));
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(second_write, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ DataItem reader("data_id");
+ reader.set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ reader.Read(key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_EQ(second_write, *read_content);
+}
+
+TEST_F(DataItemTest, DeleteWithNoBackingFile) {
+ DataItem item("data_id");
+
+ OperationResult delete_result = OperationResult::kFailed;
+ EXPECT_EQ(OperationResult::kNoBackingFile,
+ item.Delete(task_runner(),
+ base::Bind(&DeleteCallback,
+ base::Bind(&NotCalled,
+ "Delete with no backing file"),
+ &delete_result)));
+
+ DrainTaskRunner();
+}
+
+TEST_F(DataItemTest, ReadDeletedItem) {
+ DataItem item("data_id");
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, write_result);
+
+ OperationResult delete_result = OperationResult::kFailed;
+ {
+ base::RunLoop run_loop;
+ item.Delete(
+ task_runner(),
+ base::Bind(&DeleteCallback, run_loop.QuitClosure(), &delete_result));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, delete_result);
+
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+ EXPECT_EQ(
+ OperationResult::kNoBackingFile,
+ item.Read(key, task_runner(),
+ base::Bind(&ReadCallback,
+ base::Bind(&NotCalled, "Read deleted item callback"),
+ &read_result, &read_content)));
+
+ DrainTaskRunner();
+}
+
+TEST_F(DataItemTest, WriteDeletedItem) {
+ DataItem item("data_id");
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, write_result);
+
+ OperationResult delete_result = OperationResult::kFailed;
+ {
+ base::RunLoop run_loop;
+ item.Delete(
+ task_runner(),
+ base::Bind(&DeleteCallback, run_loop.QuitClosure(), &delete_result));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, delete_result);
+
+ EXPECT_EQ(OperationResult::kNoBackingFile,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback,
+ base::Bind(&NotCalled,
+ "Write deleted item callback"),
+ &write_result)));
+
+ DrainTaskRunner();
+}
+
+TEST_F(DataItemTest, WriteWithInvalidKey) {
+ DataItem item("data_id");
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, key, task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, write_result);
+
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Read("invalid", task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kInvalidKey, read_result);
+}
+
+TEST_F(DataItemTest, ReadWithInvalidKey) {
+ DataItem item("data_id");
+ item.set_backing_file(test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ item.Write(content, "invalid", task_runner(),
+ base::Bind(&WriteCallback, run_loop.QuitClosure(),
+ &write_result)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kInvalidKey, write_result);
+}
+
+TEST_F(DataItemTest, ResetBeforeCallback) {
+ std::unique_ptr<DataItem> writer = base::MakeUnique<DataItem>("data_id");
+ writer->set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ std::string key = GenerateKey("key_1");
+ ASSERT_FALSE(key.empty());
+
+ OperationResult write_result = OperationResult::kFailed;
+ std::vector<char> content = {'f', 'i', 'l', 'e', '_', '1'};
+
+ ASSERT_EQ(
+ OperationResult::kPending,
+ writer->Write(content, key, task_runner(),
+ base::Bind(&WriteCallback,
+ base::Bind(&NotCalled, "Reset writer callback"),
+ &write_result)));
+ writer.reset();
+
+ std::unique_ptr<DataItem> reader = base::MakeUnique<DataItem>("data_id");
+ reader->set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+ OperationResult read_result = OperationResult::kFailed;
+ std::unique_ptr<std::vector<char>> read_content;
+
+ {
+ base::RunLoop run_loop;
+ ASSERT_EQ(OperationResult::kPending,
+ reader->Read(key, task_runner(),
+ base::Bind(&ReadCallback, run_loop.QuitClosure(),
+ &read_result, &read_content)));
+ run_loop.Run();
+ }
+
+ EXPECT_EQ(OperationResult::kSuccess, read_result);
+ ASSERT_TRUE(read_content);
+ EXPECT_EQ(content, *read_content);
+
+ ASSERT_EQ(
+ OperationResult::kPending,
+ reader->Read(key, task_runner(),
+ base::Bind(&ReadCallback,
+ base::Bind(&NotCalled, "Reset reader calblack"),
+ &read_result, &read_content)));
+ reader.reset();
+
+ std::unique_ptr<DataItem> deleter = base::MakeUnique<DataItem>("data_id");
+ deleter->set_backing_file(
+ test_dir().AppendASCII("app").AppendASCII("test_file"));
+
+ OperationResult delete_result = OperationResult::kFailed;
+ ASSERT_EQ(OperationResult::kPending,
+ deleter->Delete(
+ task_runner(),
+ base::Bind(&DeleteCallback,
+ base::Bind(&NotCalled, "Reset delete callback"),
+ &delete_result)));
+ deleter.reset();
+
+ DrainTaskRunner();
+
+ EXPECT_FALSE(
+ base::PathExists(test_dir().AppendASCII("app").AppendASCII("test_file")));
+}
+
+} // namespace lock_screen_data
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698