1/* Self tests for scoped_mmap for GDB, the GNU debugger. 2 3 Copyright (C) 2018-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21 22#include "gdbsupport/filestuff.h" 23#include "gdbsupport/scoped_mmap.h" 24#include "config.h" 25 26#if defined(HAVE_SYS_MMAN_H) 27 28#include "gdbsupport/selftest.h" 29#include "gdbsupport/gdb_unlinker.h" 30 31#include <unistd.h> 32 33namespace selftests { 34namespace scoped_mmap { 35 36/* Test that the file is unmapped. */ 37static void 38test_destroy () 39{ 40 void *mem; 41 42 errno = 0; 43 { 44 ::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE, 45 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 46 47 mem = smmap.get (); 48 SELF_CHECK (mem != nullptr); 49 } 50 51 SELF_CHECK (msync (mem, sysconf (_SC_PAGESIZE), 0) == -1 && errno == ENOMEM); 52} 53 54/* Test that the memory can be released. */ 55static void 56test_release () 57{ 58 void *mem; 59 60 errno = 0; 61 { 62 ::scoped_mmap smmap (nullptr, sysconf (_SC_PAGESIZE), PROT_WRITE, 63 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 64 65 mem = smmap.release (); 66 SELF_CHECK (mem != nullptr); 67 } 68 69 SELF_CHECK (msync (mem, sysconf (_SC_PAGESIZE), 0) == 0 || errno != ENOMEM); 70 71 munmap (mem, sysconf (_SC_PAGESIZE)); 72} 73 74/* Run selftests. */ 75static void 76run_tests () 77{ 78 test_destroy (); 79 test_release (); 80} 81 82} /* namespace scoped_mmap */ 83 84namespace mmap_file 85{ 86 87/* Test the standard usage of mmap_file. */ 88static void 89test_normal () 90{ 91 char filename[] = "scoped_mmapped_file-selftest-XXXXXX"; 92 { 93 scoped_fd fd = gdb_mkostemp_cloexec (filename); 94 SELF_CHECK (fd.get () >= 0); 95 96 SELF_CHECK (write (fd.get (), "Hello!", 7) == 7); 97 } 98 99 gdb::unlinker unlink_test_file (filename); 100 101 { 102 ::scoped_mmap m = ::mmap_file (filename); 103 104 SELF_CHECK (m.get () != MAP_FAILED); 105 SELF_CHECK (m.size () == 7); 106 SELF_CHECK (0 == strcmp ((char *) m.get (), "Hello!")); 107 } 108} 109 110/* Calling mmap_file with a non-existent file should throw an exception. */ 111static void 112test_invalid_filename () 113{ 114 bool threw = false; 115 116 try { 117 ::scoped_mmap m = ::mmap_file ("/this/file/should/not/exist"); 118 } catch (gdb_exception &e) { 119 threw = true; 120 } 121 122 SELF_CHECK (threw); 123} 124 125 126/* Run selftests. */ 127static void 128run_tests () 129{ 130 test_normal (); 131 test_invalid_filename (); 132} 133 134} /* namespace mmap_file */ 135} /* namespace selftests */ 136 137#endif /* !defined(HAVE_SYS_MMAN_H) */ 138 139void _initialize_scoped_mmap_selftests (); 140void 141_initialize_scoped_mmap_selftests () 142{ 143#if defined(HAVE_SYS_MMAN_H) 144 selftests::register_test ("scoped_mmap", 145 selftests::scoped_mmap::run_tests); 146 selftests::register_test ("mmap_file", 147 selftests::mmap_file::run_tests); 148#endif 149} 150