• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
18 #define ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
19 
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 
23 #include <functional>
24 #include <string>
25 #include <vector>
26 
27 #include "android-base/logging.h"
28 #include "android-base/scopeguard.h"
29 #include "base/file_utils.h"
30 #include "base/globals.h"
31 #include "base/memory_tool.h"
32 #include "base/mutex.h"
33 #include "base/os.h"
34 #include "base/unix_file/fd_file.h"
35 #include "dex/art_dex_file_loader.h"
36 #include "dex/compact_dex_file.h"
37 #include "dex/compact_dex_level.h"
38 #include "gtest/gtest.h"
39 
40 namespace art {
41 
42 using LogSeverity = android::base::LogSeverity;
43 using ScopedLogSeverity = android::base::ScopedLogSeverity;
44 
45 class DexFile;
46 
47 class ScratchDir {
48  public:
49   explicit ScratchDir(bool keep_files = false);
50 
51   ~ScratchDir();
52 
GetPath()53   const std::string& GetPath() const {
54     return path_;
55   }
56 
57  private:
58   std::string path_;
59   bool keep_files_;  // Useful for debugging.
60 
61   DISALLOW_COPY_AND_ASSIGN(ScratchDir);
62 };
63 
64 class ScratchFile {
65  public:
66   ScratchFile();
67 
68   explicit ScratchFile(const std::string& filename);
69 
70   ScratchFile(const ScratchFile& other, const char* suffix);
71 
72   ScratchFile(ScratchFile&& other) noexcept;
73 
74   ScratchFile& operator=(ScratchFile&& other) noexcept;
75 
76   explicit ScratchFile(File* file);
77 
78   ~ScratchFile();
79 
GetFilename()80   const std::string& GetFilename() const {
81     return filename_;
82   }
83 
GetFile()84   File* GetFile() const {
85     return file_.get();
86   }
87 
88   int GetFd() const;
89 
90   void Close();
91   void Unlink();
92 
93  private:
94   std::string filename_;
95   std::unique_ptr<File> file_;
96 };
97 
98 // Helper class that removes an environment variable whilst in scope.
99 class ScopedUnsetEnvironmentVariable {
100  public:
ScopedUnsetEnvironmentVariable(const char * variable)101   explicit ScopedUnsetEnvironmentVariable(const char* variable)
102       : variable_{variable}, old_value_{GetOldValue(variable)} {
103     unsetenv(variable);
104   }
105 
~ScopedUnsetEnvironmentVariable()106   ~ScopedUnsetEnvironmentVariable() {
107     if (old_value_.has_value()) {
108       static constexpr int kReplace = 1;  // tidy-issue: replace argument has libc dependent name.
109       setenv(variable_, old_value_.value().c_str(), kReplace);
110     } else {
111       unsetenv(variable_);
112     }
113   }
114 
115  private:
GetOldValue(const char * variable)116   static std::optional<std::string> GetOldValue(const char* variable) {
117     const char* value = getenv(variable);
118     return value != nullptr ? std::optional<std::string>{value} : std::nullopt;
119   }
120 
121   const char* variable_;
122   std::optional<std::string> old_value_;
123   DISALLOW_COPY_AND_ASSIGN(ScopedUnsetEnvironmentVariable);
124 };
125 
126 // Temporarily drops all root capabilities when the test is run as root. This is a noop otherwise.
127 android::base::ScopeGuard<std::function<void()>> ScopedUnroot();
128 
129 // Temporarily drops all permissions on a file/directory.
130 android::base::ScopeGuard<std::function<void()>> ScopedInaccessible(const std::string& path);
131 
132 class CommonArtTestImpl {
133  public:
134   CommonArtTestImpl() = default;
135   virtual ~CommonArtTestImpl() = default;
136 
137   // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_I18N_ROOT,
138   // ANDROID_ART_ROOT, and ANDROID_TZDATA_ROOT environment variables using sensible defaults
139   // if not already set.
140   static void SetUpAndroidRootEnvVars();
141 
142   // Set up the ANDROID_DATA environment variable, creating the directory if required.
143   // Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
144   // non-derived class, be sure to also call the corresponding tear-down below.
145   static void SetUpAndroidDataDir(std::string& android_data);
146 
147   static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
148 
149   static void ClearDirectory(const char* dirpath, bool recursive = true);
150 
151   // Get the names of the libcore modules.
152   virtual std::vector<std::string> GetLibCoreModuleNames() const;
153 
154   // Gets the paths of the libcore dex files for given modules.
155   std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) const;
156 
157   // Gets the paths of the libcore dex files.
158   std::vector<std::string> GetLibCoreDexFileNames() const;
159 
160   // Gets the locations of the libcore dex files for given modules.
161   std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) const;
162 
163   // Gets the locations of the libcore dex files.
164   std::vector<std::string> GetLibCoreDexLocations() const;
165 
166   static std::string GetClassPathOption(const char* option,
167                                         const std::vector<std::string>& class_path);
168 
169   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
170   std::string GetTestDexFileName(const char* name) const;
171 
172   template <typename Mutator>
MutateDexFile(File * output_dex,const std::string & input_jar,const Mutator & mutator)173   bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) {
174     std::vector<std::unique_ptr<const DexFile>> dex_files;
175     std::string error_msg;
176     ArtDexFileLoader dex_file_loader(input_jar);
177     CHECK(dex_file_loader.Open(/*verify*/ true,
178                                /*verify_checksum*/ true,
179                                &error_msg,
180                                &dex_files))
181         << error_msg;
182     EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported";
183     const std::unique_ptr<const DexFile>& dex = dex_files[0];
184     CHECK(dex->EnableWrite()) << "Failed to enable write";
185     DexFile* dex_file = const_cast<DexFile*>(dex.get());
186     mutator(dex_file);
187     const_cast<DexFile::Header&>(dex_file->GetHeader()).checksum_ = dex_file->CalculateChecksum();
188     if (!output_dex->WriteFully(dex->Begin(), dex->Size())) {
189       return false;
190     }
191     if (output_dex->Flush() != 0) {
192       PLOG(FATAL) << "Could not flush the output file.";
193     }
194     return true;
195   }
196 
197   struct ForkAndExecResult {
198     enum Stage {
199       kLink,
200       kFork,
201       kWaitpid,
202       kFinished,
203     };
204     Stage stage;
205     int status_code;
206 
StandardSuccessForkAndExecResult207     bool StandardSuccess() {
208       return stage == kFinished && WIFEXITED(status_code) && WEXITSTATUS(status_code) == 0;
209     }
210   };
211   using OutputHandlerFn = std::function<void(char*, size_t)>;
212   using PostForkFn = std::function<bool()>;
213   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
214                                        const PostForkFn& post_fork,
215                                        const OutputHandlerFn& handler);
216   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
217                                        const PostForkFn& post_fork,
218                                        std::string* output);
219 
220   // Helper - find prebuilt tool (e.g. objdump).
221   static std::string GetAndroidTool(const char* name, InstructionSet isa = InstructionSet::kX86_64);
222 
223  protected:
IsHost()224   static bool IsHost() {
225     return !kIsTargetBuild;
226   }
227 
228   // Returns ${ANDROID_BUILD_TOP}. Ensure it has tailing /.
229   static std::string GetAndroidBuildTop();
230 
231   // Returns ${ANDROID_HOST_OUT}.
232   static std::string GetAndroidHostOut();
233 
234   // File location to boot.art, e.g. /apex/com.android.art/javalib/boot.art
235   static std::string GetCoreArtLocation();
236 
237   // File location to boot.oat, e.g. /apex/com.android.art/javalib/boot.oat
238   static std::string GetCoreOatLocation();
239 
240   std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
241 
242   // Open a file (allows reading of framework jars).
243   std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
244 
245   // Open a single dex file (aborts if there are more than one).
246   std::unique_ptr<const DexFile> OpenDexFile(const char* filename);
247 
248   // Open a test file (art-gtest-*.jar).
249   std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name);
250 
251   std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
252 
253   std::string android_data_;
254   std::string android_system_ext_;
255   std::string dalvik_cache_;
256 
257   virtual void SetUp();
258 
259   virtual void TearDown();
260 
261   // Creates the class path string for the given dex files (the list of dex file locations
262   // separated by ':').
263   std::string CreateClassPath(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
264   // Same as CreateClassPath but add the dex file checksum after each location. The separator
265   // is '*'.
266   std::string CreateClassPathWithChecksums(
267       const std::vector<std::unique_ptr<const DexFile>>& dex_files);
268 
269   static std::string GetImageDirectory();
270   static std::string GetCoreFileLocation(const char* suffix);
271 
272   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
273 };
274 
275 template <typename TestType>
276 class CommonArtTestBase : public TestType, public CommonArtTestImpl {
277  public:
CommonArtTestBase()278   CommonArtTestBase() {}
~CommonArtTestBase()279   virtual ~CommonArtTestBase() {}
280 
281  protected:
SetUp()282   void SetUp() override {
283     CommonArtTestImpl::SetUp();
284   }
285 
TearDown()286   void TearDown() override {
287     CommonArtTestImpl::TearDown();
288   }
289 };
290 
291 using CommonArtTest = CommonArtTestBase<testing::Test>;
292 
293 template <typename Param>
294 using CommonArtTestWithParam = CommonArtTestBase<testing::TestWithParam<Param>>;
295 
296 // Returns a list of PIDs of the processes whose process name (the first commandline argument) fully
297 // matches the given name.
298 std::vector<pid_t> GetPidByName(const std::string& process_name);
299 
300 #define TEST_DISABLED_FOR_TARGET() \
301   if (kIsTargetBuild) { \
302     printf("WARNING: TEST DISABLED FOR TARGET\n"); \
303     return; \
304   }
305 
306 #define TEST_DISABLED_FOR_HOST() \
307   if (!kIsTargetBuild) { \
308     printf("WARNING: TEST DISABLED FOR HOST\n"); \
309     return; \
310   }
311 
312 #define TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS() \
313   if (!kHostStaticBuildEnabled) { \
314     printf("WARNING: TEST DISABLED FOR NON-STATIC HOST BUILDS\n"); \
315     return; \
316   }
317 
318 #define TEST_DISABLED_FOR_MEMORY_TOOL() \
319   if (kRunningOnMemoryTool) { \
320     printf("WARNING: TEST DISABLED FOR MEMORY TOOL\n"); \
321     return; \
322   }
323 
324 #define TEST_DISABLED_FOR_HEAP_POISONING() \
325   if (kPoisonHeapReferences) { \
326     printf("WARNING: TEST DISABLED FOR HEAP POISONING\n"); \
327     return; \
328   }
329 }  // namespace art
330 
331 #define TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING() \
332   if (kRunningOnMemoryTool && kPoisonHeapReferences) { \
333     printf("WARNING: TEST DISABLED FOR MEMORY TOOL WITH HEAP POISONING\n"); \
334     return; \
335   }
336 
337 #endif  // ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
338