| // Copyright (c) 2012 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/extension_creator_filter.h" |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| |
| #include "base/cxx17_backports.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/macros.h" |
| #include "build/build_config.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/platform_test.h" |
| |
| #if defined(OS_WIN) |
| #include <windows.h> |
| #endif |
| |
| namespace { |
| |
| class ExtensionCreatorFilterTest : public PlatformTest { |
| protected: |
| void SetUp() override { |
| PlatformTest::SetUp(); |
| |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| extension_dir_ = temp_dir_.GetPath(); |
| |
| filter_ = base::MakeRefCounted<extensions::ExtensionCreatorFilter>( |
| extension_dir_); |
| } |
| |
| base::FilePath CreateTestFile(const base::FilePath& file_path) { |
| return CreateRelativeFilePath(file_path); |
| } |
| |
| // Creates an empty file with the given relative path. Creates parent |
| // directories if needed. |
| base::FilePath CreateRelativeFilePath( |
| const base::FilePath& relative_file_path) { |
| base::FilePath path = extension_dir_.Append(relative_file_path); |
| EXPECT_TRUE(base::CreateDirectory(path.DirName())); |
| |
| std::string contents = "test"; |
| EXPECT_EQ(static_cast<int>(contents.size()), |
| base::WriteFile(path, contents.c_str(), contents.size())); |
| return path; |
| } |
| |
| base::FilePath CreateTestFileInDir( |
| const base::FilePath::StringType& file_name, |
| const base::FilePath::StringType& dir) { |
| return CreateRelativeFilePath(base::FilePath(dir).Append(file_name)); |
| } |
| |
| scoped_refptr<extensions::ExtensionCreatorFilter> filter_; |
| |
| base::ScopedTempDir temp_dir_; |
| |
| base::FilePath extension_dir_; |
| }; |
| |
| struct UnaryBooleanTestData { |
| const base::FilePath::CharType* input; |
| bool expected; |
| }; |
| |
| TEST_F(ExtensionCreatorFilterTest, NormalCases) { |
| const struct UnaryBooleanTestData cases[] = { |
| {FILE_PATH_LITERAL("foo"), true}, |
| {FILE_PATH_LITERAL(".foo"), false}, |
| {FILE_PATH_LITERAL("~foo"), true}, |
| {FILE_PATH_LITERAL("foo~"), false}, |
| {FILE_PATH_LITERAL("#foo"), true}, |
| {FILE_PATH_LITERAL("foo#"), true}, |
| {FILE_PATH_LITERAL("#foo#"), false}, |
| {FILE_PATH_LITERAL(".svn"), false}, |
| {FILE_PATH_LITERAL("__MACOSX"), false}, |
| {FILE_PATH_LITERAL(".DS_Store"), false}, |
| {FILE_PATH_LITERAL("desktop.ini"), false}, |
| {FILE_PATH_LITERAL("Thumbs.db"), false}, |
| }; |
| |
| for (size_t i = 0; i < base::size(cases); ++i) { |
| base::FilePath input(cases[i].input); |
| base::FilePath test_file(CreateTestFile(input)); |
| bool observed = filter_->ShouldPackageFile(test_file); |
| |
| EXPECT_EQ(cases[i].expected, observed) |
| << "i: " << i << ", input: " << test_file.value(); |
| } |
| } |
| |
| TEST_F(ExtensionCreatorFilterTest, MetadataFolderExcluded) { |
| const struct UnaryBooleanTestData cases[] = { |
| {FILE_PATH_LITERAL("_metadata/foo"), false}, |
| {FILE_PATH_LITERAL("_metadata/abc/foo"), false}, |
| {FILE_PATH_LITERAL("_metadata/abc/xyz/foo"), false}, |
| {FILE_PATH_LITERAL("abc/_metadata/xyz"), true}, |
| {FILE_PATH_LITERAL("xyz/_metadata"), true}, |
| }; |
| |
| // Create and test the filepaths. |
| for (size_t i = 0; i < base::size(cases); ++i) { |
| base::FilePath test_file = |
| CreateRelativeFilePath(base::FilePath(cases[i].input)); |
| bool observed = filter_->ShouldPackageFile(test_file); |
| |
| EXPECT_EQ(cases[i].expected, observed) |
| << "i: " << i << ", input: " << test_file.value(); |
| } |
| |
| // Also test directories. |
| const struct UnaryBooleanTestData directory_cases[] = { |
| {FILE_PATH_LITERAL("_metadata"), false}, |
| {FILE_PATH_LITERAL("_metadata/abc"), false}, |
| {FILE_PATH_LITERAL("_metadata/abc/xyz"), false}, |
| {FILE_PATH_LITERAL("abc"), true}, |
| {FILE_PATH_LITERAL("abc/_metadata"), true}, |
| {FILE_PATH_LITERAL("xyz"), true}, |
| }; |
| for (size_t i = 0; i < base::size(directory_cases); ++i) { |
| base::FilePath directory = extension_dir_.Append(directory_cases[i].input); |
| bool observed = filter_->ShouldPackageFile(directory); |
| |
| EXPECT_EQ(directory_cases[i].expected, observed) |
| << "i: " << i << ", input: " << directory.value(); |
| } |
| } |
| |
| struct StringStringWithBooleanTestData { |
| const base::FilePath::StringType file_name; |
| const base::FilePath::StringType dir; |
| bool expected; |
| }; |
| |
| // Ignore the files in special directories, including ".git", ".svn", |
| // "__MACOSX". |
| TEST_F(ExtensionCreatorFilterTest, IgnoreFilesInSpecialDir) { |
| const struct StringStringWithBooleanTestData cases[] = { |
| {FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL(".git"), false}, |
| {FILE_PATH_LITERAL("goo"), FILE_PATH_LITERAL(".svn"), false}, |
| {FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("__MACOSX"), false}, |
| {FILE_PATH_LITERAL("foo"), FILE_PATH_LITERAL("foo"), true}, |
| {FILE_PATH_LITERAL("index.js"), FILE_PATH_LITERAL("scripts"), true}, |
| }; |
| |
| for (size_t i = 0; i < base::size(cases); ++i) { |
| base::FilePath test_file( |
| CreateTestFileInDir(cases[i].file_name, cases[i].dir)); |
| bool observed = filter_->ShouldPackageFile(test_file); |
| EXPECT_EQ(cases[i].expected, observed) |
| << "i: " << i << ", input: " << test_file.value(); |
| } |
| } |
| |
| #if defined(OS_WIN) |
| struct StringBooleanWithBooleanTestData { |
| const base::FilePath::CharType* input_char; |
| bool input_bool; |
| bool expected; |
| }; |
| |
| TEST_F(ExtensionCreatorFilterTest, WindowsHiddenFiles) { |
| const struct StringBooleanWithBooleanTestData cases[] = { |
| {FILE_PATH_LITERAL("a-normal-file"), false, true}, |
| {FILE_PATH_LITERAL(".a-dot-file"), false, false}, |
| {FILE_PATH_LITERAL(".a-dot-file-that-we-have-set-to-hidden"), true, |
| false}, |
| {FILE_PATH_LITERAL("a-file-that-we-have-set-to-hidden"), true, false}, |
| {FILE_PATH_LITERAL("a-file-that-we-have-not-set-to-hidden"), false, true}, |
| }; |
| |
| for (size_t i = 0; i < base::size(cases); ++i) { |
| base::FilePath input(cases[i].input_char); |
| bool should_hide = cases[i].input_bool; |
| base::FilePath test_file(CreateTestFile(input)); |
| |
| if (should_hide) { |
| SetFileAttributes(test_file.value().c_str(), FILE_ATTRIBUTE_HIDDEN); |
| } |
| bool observed = filter_->ShouldPackageFile(test_file); |
| EXPECT_EQ(cases[i].expected, observed) |
| << "i: " << i << ", input: " << test_file.value(); |
| } |
| } |
| #endif |
| |
| } // namespace |