| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "test/Fixture.h" |
| |
| #include <dirent.h> |
| |
| #include "android-base/errors.h" |
| #include "android-base/file.h" |
| #include "android-base/stringprintf.h" |
| #include "android-base/utf8.h" |
| #include "androidfw/StringPiece.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| |
| #include "cmd/Compile.h" |
| #include "cmd/Link.h" |
| #include "io/FileStream.h" |
| #include "io/Util.h" |
| #include "util/Files.h" |
| |
| using testing::Eq; |
| using testing::Ne; |
| |
| namespace aapt { |
| |
| const char* CommandTestFixture::kDefaultPackageName = "com.aapt.command.test"; |
| |
| void ClearDirectory(const android::StringPiece& path) { |
| const std::string root_dir = path.to_string(); |
| std::unique_ptr<DIR, decltype(closedir)*> dir(opendir(root_dir.data()), closedir); |
| if (!dir) { |
| StdErrDiagnostics().Error(DiagMessage() << android::base::SystemErrorCodeToString(errno)); |
| return; |
| } |
| |
| while (struct dirent* entry = readdir(dir.get())) { |
| // Do not delete hidden files and do not recurse to the parent of this directory |
| if (util::StartsWith(entry->d_name, ".")) { |
| continue; |
| } |
| |
| std::string full_path = file::BuildPath({root_dir, entry->d_name}); |
| if (file::GetFileType(full_path) == file::FileType::kDirectory) { |
| ClearDirectory(full_path); |
| #ifdef _WIN32 |
| _rmdir(full_path.c_str()); |
| #else |
| rmdir(full_path.c_str()); |
| #endif |
| } else { |
| android::base::utf8::unlink(full_path.c_str()); |
| } |
| } |
| } |
| |
| void TestDirectoryFixture::SetUp() { |
| temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(), |
| "_temp", |
| testing::UnitTest::GetInstance()->current_test_case()->name(), |
| testing::UnitTest::GetInstance()->current_test_info()->name()}); |
| ASSERT_TRUE(file::mkdirs(temp_dir_)); |
| ClearDirectory(temp_dir_); |
| } |
| |
| void TestDirectoryFixture::TearDown() { |
| ClearDirectory(temp_dir_); |
| } |
| |
| bool TestDirectoryFixture::WriteFile(const std::string& path, const std::string& contents) { |
| CHECK(util::StartsWith(path, temp_dir_)) |
| << "Attempting to create a file outside of test temporary directory."; |
| |
| // Create any intermediate directories specified in the path |
| auto pos = std::find(path.rbegin(), path.rend(), file::sDirSep); |
| if (pos != path.rend()) { |
| std::string dirs = path.substr(0, (&*pos - path.data())); |
| file::mkdirs(dirs); |
| } |
| |
| return android::base::WriteStringToFile(contents, path); |
| } |
| |
| bool CommandTestFixture::CompileFile(const std::string& path, const std::string& contents, |
| const android::StringPiece& out_dir, IDiagnostics* diag) { |
| CHECK(WriteFile(path, contents)); |
| CHECK(file::mkdirs(out_dir.data())); |
| return CompileCommand(diag).Execute({path, "-o", out_dir, "-v"}, &std::cerr) == 0; |
| } |
| |
| bool CommandTestFixture::Link(const std::vector<std::string>& args, |
| const android::StringPiece& flat_dir, IDiagnostics* diag) { |
| std::vector<android::StringPiece> link_args; |
| for(const std::string& arg : args) { |
| link_args.emplace_back(arg); |
| } |
| |
| // Link against the android SDK |
| std::string android_sdk = file::BuildPath({android::base::GetExecutableDirectory(), |
| "integration-tests", "CommandTests", |
| "android-28.jar"}); |
| link_args.insert(link_args.end(), {"-I", android_sdk}); |
| |
| // Add the files from the compiled resources directory to the link file arguments |
| Maybe<std::vector<std::string>> compiled_files = file::FindFiles(flat_dir, diag); |
| if (compiled_files) { |
| for (std::string& compile_file : compiled_files.value()) { |
| compile_file = file::BuildPath({flat_dir, compile_file}); |
| link_args.emplace_back(std::move(compile_file)); |
| } |
| } |
| |
| return LinkCommand(diag).Execute(link_args, &std::cerr) == 0; |
| } |
| |
| std::string CommandTestFixture::GetDefaultManifest(const char* package_name) { |
| const std::string manifest_file = GetTestPath("AndroidManifest.xml"); |
| CHECK(WriteFile(manifest_file, android::base::StringPrintf(R"( |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| package="%s"> |
| </manifest>)", package_name))); |
| return manifest_file; |
| } |
| |
| std::unique_ptr<io::IData> CommandTestFixture::OpenFileAsData(LoadedApk* apk, |
| const android::StringPiece& path) { |
| return apk |
| ->GetFileCollection() |
| ->FindFile(path) |
| ->OpenAsData(); |
| } |
| |
| void CommandTestFixture::AssertLoadXml(LoadedApk* apk, const io::IData* data, |
| android::ResXMLTree *out_tree) { |
| ASSERT_THAT(apk, Ne(nullptr)); |
| |
| out_tree->setTo(data->data(), data->size()); |
| ASSERT_THAT(out_tree->getError(), Eq(android::OK)); |
| while (out_tree->next() != android::ResXMLTree::START_TAG) { |
| ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT)); |
| ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::END_DOCUMENT)); |
| } |
| } |
| |
| } // namespace aapt |