utils.h revision beb3eb1790dffc6e2f57a670aec89364944f66c4
1/* 2 * Copyright (C) 2012 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 __TEST_UTILS_H 18#define __TEST_UTILS_H 19 20#include <inttypes.h> 21#include <sys/mman.h> 22#include <sys/types.h> 23#include <sys/wait.h> 24#include <unistd.h> 25 26#include <atomic> 27#include <string> 28#include <regex> 29 30#include <android-base/file.h> 31#include <android-base/stringprintf.h> 32 33#include "private/ScopeGuard.h" 34 35#if defined(__BIONIC__) 36#define KNOWN_FAILURE_ON_BIONIC(x) xfail_ ## x 37#else 38#define KNOWN_FAILURE_ON_BIONIC(x) x 39#endif 40 41#if defined(__linux__) 42 43struct map_record { 44 uintptr_t addr_start; 45 uintptr_t addr_end; 46 47 int perms; 48 49 size_t offset; 50 51 dev_t device; 52 ino_t inode; 53 54 std::string pathname; 55}; 56 57class Maps { 58 public: 59 static bool parse_maps(std::vector<map_record>* maps) { 60 FILE* fp = fopen("/proc/self/maps", "re"); 61 if (fp == nullptr) { 62 return false; 63 } 64 65 auto fp_guard = make_scope_guard([&]() { 66 fclose(fp); 67 }); 68 69 char line[BUFSIZ]; 70 while (fgets(line, sizeof(line), fp) != nullptr) { 71 map_record record; 72 uint32_t dev_major, dev_minor; 73 int path_offset; 74 char prot[5]; // sizeof("rwxp") 75 if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %x:%x %lu %n", 76 &record.addr_start, &record.addr_end, prot, &record.offset, 77 &dev_major, &dev_minor, &record.inode, &path_offset) == 7) { 78 record.perms = 0; 79 if (prot[0] == 'r') { 80 record.perms |= PROT_READ; 81 } 82 if (prot[1] == 'w') { 83 record.perms |= PROT_WRITE; 84 } 85 if (prot[2] == 'x') { 86 record.perms |= PROT_EXEC; 87 } 88 89 // TODO: parse shared/private? 90 91 record.device = makedev(dev_major, dev_minor); 92 record.pathname = line + path_offset; 93 if (!record.pathname.empty() && record.pathname.back() == '\n') { 94 record.pathname.pop_back(); 95 } 96 maps->push_back(record); 97 } 98 } 99 100 return true; 101 } 102}; 103 104extern "C" pid_t gettid(); 105 106#endif 107 108static inline void WaitUntilThreadSleep(std::atomic<pid_t>& tid) { 109 while (tid == 0) { 110 usleep(1000); 111 } 112 std::string filename = android::base::StringPrintf("/proc/%d/stat", tid.load()); 113 std::regex regex {R"(\s+S\s+)"}; 114 115 while (true) { 116 std::string content; 117 ASSERT_TRUE(android::base::ReadFileToString(filename, &content)); 118 if (std::regex_search(content, regex)) { 119 break; 120 } 121 usleep(1000); 122 } 123} 124 125static inline void AssertChildExited(int pid, int expected_exit_status) { 126 int status; 127 ASSERT_EQ(pid, waitpid(pid, &status, 0)); 128 ASSERT_TRUE(WIFEXITED(status)); 129 ASSERT_EQ(expected_exit_status, WEXITSTATUS(status)); 130} 131 132// The absolute path to the executable 133const std::string& get_executable_path(); 134 135// Get realpath 136bool get_realpath(const std::string& path, std::string* realpath); 137// Get dirname 138std::string get_dirname(const char* path); 139 140// Access to argc/argv/envp 141int get_argc(); 142char** get_argv(); 143char** get_envp(); 144 145#endif 146