blob: aae79fafc0a6eae4460c90fc89fcb2b2d43408b3 [file] [log] [blame]
Ryan Mitchell479fa392019-01-02 17:15:39 -08001/*
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
35using testing::Eq;
36using testing::Ne;
37
38namespace aapt {
39
40void 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
68void 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
77void TestDirectoryFixture::TearDown() {
78 ClearDirectory(temp_dir_);
79}
80
81bool 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
95bool 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
102bool 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
127std::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
136void 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