Ryan Mitchell | 479fa39 | 2019-01-02 17:15:39 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "test/Fixture.h" |
| 18 | |
| 19 | #include <dirent.h> |
| 20 | |
| 21 | #include "android-base/errors.h" |
| 22 | #include "android-base/file.h" |
| 23 | #include "android-base/stringprintf.h" |
| 24 | #include "android-base/utf8.h" |
| 25 | #include "androidfw/StringPiece.h" |
| 26 | #include "gmock/gmock.h" |
| 27 | #include "gtest/gtest.h" |
| 28 | |
| 29 | #include "cmd/Compile.h" |
| 30 | #include "cmd/Link.h" |
| 31 | #include "io/FileStream.h" |
| 32 | #include "io/Util.h" |
| 33 | #include "util/Files.h" |
| 34 | |
| 35 | using testing::Eq; |
| 36 | using testing::Ne; |
| 37 | |
| 38 | namespace aapt { |
| 39 | |
| 40 | void ClearDirectory(const android::StringPiece& path) { |
| 41 | const std::string root_dir = path.to_string(); |
| 42 | std::unique_ptr<DIR, decltype(closedir)*> dir(opendir(root_dir.data()), closedir); |
| 43 | if (!dir) { |
| 44 | StdErrDiagnostics().Error(DiagMessage() << android::base::SystemErrorCodeToString(errno)); |
| 45 | return; |
| 46 | } |
| 47 | |
| 48 | while (struct dirent* entry = readdir(dir.get())) { |
| 49 | // Do not delete hidden files and do not recurse to the parent of this directory |
| 50 | if (util::StartsWith(entry->d_name, ".")) { |
| 51 | continue; |
| 52 | } |
| 53 | |
| 54 | std::string full_path = file::BuildPath({root_dir, entry->d_name}); |
| 55 | if (file::GetFileType(full_path) == file::FileType::kDirectory) { |
| 56 | ClearDirectory(full_path); |
| 57 | #ifdef _WIN32 |
| 58 | _rmdir(full_path.c_str()); |
| 59 | #else |
| 60 | rmdir(full_path.c_str()); |
| 61 | #endif |
| 62 | } else { |
| 63 | android::base::utf8::unlink(full_path.c_str()); |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | void TestDirectoryFixture::SetUp() { |
| 69 | temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(), |
| 70 | "_temp", |
| 71 | testing::UnitTest::GetInstance()->current_test_case()->name(), |
| 72 | testing::UnitTest::GetInstance()->current_test_info()->name()}); |
| 73 | ASSERT_TRUE(file::mkdirs(temp_dir_)); |
| 74 | ClearDirectory(temp_dir_); |
| 75 | } |
| 76 | |
| 77 | void TestDirectoryFixture::TearDown() { |
| 78 | ClearDirectory(temp_dir_); |
| 79 | } |
| 80 | |
| 81 | bool TestDirectoryFixture::WriteFile(const std::string& path, const std::string& contents) { |
| 82 | CHECK(util::StartsWith(path, temp_dir_)) |
| 83 | << "Attempting to create a file outside of test temporary directory."; |
| 84 | |
| 85 | // Create any intermediate directories specified in the path |
| 86 | auto pos = std::find(path.rbegin(), path.rend(), file::sDirSep); |
| 87 | if (pos != path.rend()) { |
| 88 | std::string dirs = path.substr(0, (&*pos - path.data())); |
| 89 | file::mkdirs(dirs); |
| 90 | } |
| 91 | |
| 92 | return android::base::WriteStringToFile(contents, path); |
| 93 | } |
| 94 | |
| 95 | bool CommandTestFixture::CompileFile(const std::string& path, const std::string& contents, |
| 96 | const android::StringPiece& out_dir, IDiagnostics* diag) { |
| 97 | CHECK(WriteFile(path, contents)); |
| 98 | CHECK(file::mkdirs(out_dir.data())); |
| 99 | return CompileCommand(diag).Execute({path, "-o", out_dir, "-v"}, &std::cerr) == 0; |
| 100 | } |
| 101 | |
| 102 | bool CommandTestFixture::Link(const std::vector<std::string>& args, |
| 103 | const android::StringPiece& flat_dir, IDiagnostics* diag) { |
| 104 | std::vector<android::StringPiece> link_args; |
| 105 | for(const std::string& arg : args) { |
| 106 | link_args.emplace_back(arg); |
| 107 | } |
| 108 | |
| 109 | // Link against the android SDK |
| 110 | std::string android_sdk = file::BuildPath({android::base::GetExecutableDirectory(), |
| 111 | "integration-tests", "CommandTests", |
| 112 | "android-28.jar"}); |
| 113 | link_args.insert(link_args.end(), {"-I", android_sdk}); |
| 114 | |
| 115 | // Add the files from the compiled resources directory to the link file arguments |
| 116 | Maybe<std::vector<std::string>> compiled_files = file::FindFiles(flat_dir, diag); |
| 117 | if (compiled_files) { |
| 118 | for (std::string& compile_file : compiled_files.value()) { |
| 119 | compile_file = file::BuildPath({flat_dir, compile_file}); |
| 120 | link_args.emplace_back(std::move(compile_file)); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | return LinkCommand(diag).Execute(link_args, &std::cerr) == 0; |
| 125 | } |
| 126 | |
| 127 | std::string CommandTestFixture::GetDefaultManifest() { |
| 128 | const std::string manifest_file = GetTestPath("AndroidManifest.xml"); |
| 129 | CHECK(WriteFile(manifest_file, R"( |
| 130 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| 131 | package="com.aapt.command.test"> |
| 132 | </manifest>)")); |
| 133 | return manifest_file; |
| 134 | } |
| 135 | |
| 136 | void CommandTestFixture::AssertLoadXml(LoadedApk *apk, const android::StringPiece &xml_path, |
| 137 | android::ResXMLTree *out_tree) { |
| 138 | ASSERT_THAT(apk, Ne(nullptr)); |
| 139 | |
| 140 | io::IFile* file = apk->GetFileCollection()->FindFile(xml_path); |
| 141 | ASSERT_THAT(file, Ne(nullptr)); |
| 142 | |
| 143 | std::unique_ptr<io::IData> data = file->OpenAsData(); |
| 144 | ASSERT_THAT(data, Ne(nullptr)); |
| 145 | |
| 146 | out_tree->setTo(data->data(), data->size()); |
| 147 | ASSERT_THAT(out_tree->getError(), Eq(android::OK)); |
| 148 | while (out_tree->next() != android::ResXMLTree::START_TAG) { |
| 149 | ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT)); |
| 150 | ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::END_DOCUMENT)); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | } // namespace aapt |