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