Home | History | Annotate | Download | only in test
      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 const char* CommandTestFixture::kDefaultPackageName = "com.aapt.command.test";
     41 
     42 void ClearDirectory(const android::StringPiece& path) {
     43   const std::string root_dir = path.to_string();
     44   std::unique_ptr<DIR, decltype(closedir)*> dir(opendir(root_dir.data()), closedir);
     45   if (!dir) {
     46     StdErrDiagnostics().Error(DiagMessage() << android::base::SystemErrorCodeToString(errno));
     47     return;
     48   }
     49 
     50   while (struct dirent* entry = readdir(dir.get())) {
     51     // Do not delete hidden files and do not recurse to the parent of this directory
     52     if (util::StartsWith(entry->d_name, ".")) {
     53       continue;
     54     }
     55 
     56     std::string full_path = file::BuildPath({root_dir, entry->d_name});
     57     if (file::GetFileType(full_path) == file::FileType::kDirectory) {
     58       ClearDirectory(full_path);
     59 #ifdef _WIN32
     60       _rmdir(full_path.c_str());
     61 #else
     62       rmdir(full_path.c_str());
     63 #endif
     64     } else {
     65       android::base::utf8::unlink(full_path.c_str());
     66     }
     67   }
     68 }
     69 
     70 void TestDirectoryFixture::SetUp() {
     71   temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(),
     72                                "_temp",
     73                                testing::UnitTest::GetInstance()->current_test_case()->name(),
     74                                testing::UnitTest::GetInstance()->current_test_info()->name()});
     75   ASSERT_TRUE(file::mkdirs(temp_dir_));
     76   ClearDirectory(temp_dir_);
     77 }
     78 
     79 void TestDirectoryFixture::TearDown() {
     80   ClearDirectory(temp_dir_);
     81 }
     82 
     83 bool TestDirectoryFixture::WriteFile(const std::string& path, const std::string& contents) {
     84   CHECK(util::StartsWith(path, temp_dir_))
     85       << "Attempting to create a file outside of test temporary directory.";
     86 
     87   // Create any intermediate directories specified in the path
     88   auto pos = std::find(path.rbegin(), path.rend(), file::sDirSep);
     89   if (pos != path.rend()) {
     90     std::string dirs = path.substr(0, (&*pos - path.data()));
     91     file::mkdirs(dirs);
     92   }
     93 
     94   return android::base::WriteStringToFile(contents, path);
     95 }
     96 
     97 bool CommandTestFixture::CompileFile(const std::string& path, const std::string& contents,
     98                                      const android::StringPiece& out_dir, IDiagnostics* diag) {
     99   CHECK(WriteFile(path, contents));
    100   CHECK(file::mkdirs(out_dir.data()));
    101   return CompileCommand(diag).Execute({path, "-o", out_dir, "-v"}, &std::cerr) == 0;
    102 }
    103 
    104 bool CommandTestFixture::Link(const std::vector<std::string>& args,
    105                               const android::StringPiece& flat_dir, IDiagnostics* diag) {
    106   std::vector<android::StringPiece> link_args;
    107   for(const std::string& arg : args) {
    108     link_args.emplace_back(arg);
    109   }
    110 
    111   // Link against the android SDK
    112   std::string android_sdk = file::BuildPath({android::base::GetExecutableDirectory(),
    113                                              "integration-tests", "CommandTests",
    114                                              "android-28.jar"});
    115   link_args.insert(link_args.end(), {"-I", android_sdk});
    116 
    117   // Add the files from the compiled resources directory to the link file arguments
    118   Maybe<std::vector<std::string>> compiled_files = file::FindFiles(flat_dir, diag);
    119   if (compiled_files) {
    120     for (std::string& compile_file : compiled_files.value()) {
    121       compile_file = file::BuildPath({flat_dir, compile_file});
    122       link_args.emplace_back(std::move(compile_file));
    123     }
    124   }
    125 
    126   return LinkCommand(diag).Execute(link_args, &std::cerr) == 0;
    127 }
    128 
    129 std::string CommandTestFixture::GetDefaultManifest(const char* package_name) {
    130   const std::string manifest_file = GetTestPath("AndroidManifest.xml");
    131   CHECK(WriteFile(manifest_file, android::base::StringPrintf(R"(
    132       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    133           package="%s">
    134       </manifest>)", package_name)));
    135   return manifest_file;
    136 }
    137 
    138 std::unique_ptr<io::IData> CommandTestFixture::OpenFileAsData(LoadedApk* apk,
    139                                                               const android::StringPiece& path) {
    140   return apk
    141       ->GetFileCollection()
    142       ->FindFile(path)
    143       ->OpenAsData();
    144 }
    145 
    146 void CommandTestFixture::AssertLoadXml(LoadedApk* apk, const io::IData* data,
    147                                        android::ResXMLTree *out_tree) {
    148   ASSERT_THAT(apk, Ne(nullptr));
    149 
    150   out_tree->setTo(data->data(), data->size());
    151   ASSERT_THAT(out_tree->getError(), Eq(android::OK));
    152   while (out_tree->next() != android::ResXMLTree::START_TAG) {
    153     ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
    154     ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
    155   }
    156 }
    157 
    158 } // namespace aapt