1from __future__ import print_function 2 3# lldb test suite imports 4from lldbsuite.test.decorators import * 5from lldbsuite.test.lldbtest import TestBase 6 7# gdb-remote-specific imports 8import lldbgdbserverutils 9from gdbremote_testcase import GdbRemoteTestCaseBase 10 11import binascii 12import stat 13import tempfile 14 15 16class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase): 17 18 mydir = TestBase.compute_mydir(__file__) 19 20 def test_platform_file_rdonly(self): 21 self.vFile_test(read=True) 22 23 def test_platform_file_wronly(self): 24 self.vFile_test(write=True) 25 26 def test_platform_file_rdwr(self): 27 self.vFile_test(read=True, write=True) 28 29 def test_platform_file_wronly_append(self): 30 self.vFile_test(write=True, append=True) 31 32 def test_platform_file_rdwr_append(self): 33 self.vFile_test(read=True, write=True, append=True) 34 35 def test_platform_file_wronly_trunc(self): 36 self.vFile_test(write=True, trunc=True) 37 38 def test_platform_file_rdwr_trunc(self): 39 self.vFile_test(read=True, write=True, trunc=True) 40 41 def test_platform_file_wronly_creat(self): 42 self.vFile_test(write=True, creat=True) 43 44 def test_platform_file_wronly_creat_excl(self): 45 self.vFile_test(write=True, creat=True, excl=True) 46 47 def test_platform_file_wronly_fail(self): 48 server = self.connect_to_debug_monitor() 49 self.assertIsNotNone(server) 50 51 # create a temporary directory 52 with tempfile.TemporaryDirectory() as temp_dir: 53 temp_path = os.path.join(temp_dir, "test") 54 self.assertFalse(os.path.exists(temp_path)) 55 56 # attempt to open the file without O_CREAT 57 self.do_handshake() 58 self.test_sequence.add_log_lines( 59 ["read packet: $vFile:open:%s,1,0#00" % ( 60 binascii.b2a_hex(temp_path.encode()).decode(),), 61 {"direction": "send", 62 "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"}], 63 True) 64 self.expect_gdbremote_sequence() 65 66 def test_platform_file_wronly_creat_excl_fail(self): 67 server = self.connect_to_debug_monitor() 68 self.assertIsNotNone(server) 69 70 with tempfile.NamedTemporaryFile() as temp_file: 71 # attempt to open the file with O_CREAT|O_EXCL 72 self.do_handshake() 73 self.test_sequence.add_log_lines( 74 ["read packet: $vFile:open:%s,a01,0#00" % ( 75 binascii.b2a_hex(temp_file.name.encode()).decode(),), 76 {"direction": "send", 77 "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"}], 78 True) 79 self.expect_gdbremote_sequence() 80 81 def expect_error(self): 82 self.test_sequence.add_log_lines( 83 [{"direction": "send", 84 "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"}], 85 True) 86 self.expect_gdbremote_sequence() 87 88 def vFile_test(self, read=False, write=False, append=False, trunc=False, 89 creat=False, excl=False): 90 if read and write: 91 mode = 2 92 elif write: 93 mode = 1 94 else: # read 95 mode = 0 96 if append: 97 mode |= 8 98 if creat: 99 mode |= 0x200 100 if trunc: 101 mode |= 0x400 102 if excl: 103 mode |= 0x800 104 105 old_umask = os.umask(0o22) 106 try: 107 server = self.connect_to_debug_monitor() 108 finally: 109 os.umask(old_umask) 110 self.assertIsNotNone(server) 111 112 # create a temporary file with some data 113 test_data = 'some test data longer than 16 bytes\n' 114 if creat: 115 temp_dir = tempfile.TemporaryDirectory() 116 else: 117 temp_file = tempfile.NamedTemporaryFile() 118 119 try: 120 if creat: 121 temp_path = os.path.join(temp_dir.name, "test") 122 self.assertFalse(os.path.exists(temp_path)) 123 else: 124 temp_file.write(test_data.encode()) 125 temp_file.flush() 126 temp_path = temp_file.name 127 128 # open the file for reading 129 self.do_handshake() 130 self.test_sequence.add_log_lines( 131 ["read packet: $vFile:open:%s,%x,1a0#00" % ( 132 binascii.b2a_hex(temp_path.encode()).decode(), 133 mode), 134 {"direction": "send", 135 "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$", 136 "capture": {1: "fd"}}], 137 True) 138 139 context = self.expect_gdbremote_sequence() 140 self.assertIsNotNone(context) 141 fd = int(context["fd"], 16) 142 143 # read data from the file 144 self.reset_test_sequence() 145 self.test_sequence.add_log_lines( 146 ["read packet: $vFile:pread:%x,11,10#00" % (fd,)], 147 True) 148 if read: 149 self.test_sequence.add_log_lines( 150 [{"direction": "send", 151 "regex": r"^\$F([0-9a-fA-F]+);(.*)#[0-9a-fA-F]{2}$", 152 "capture": {1: "size", 2: "data"}}], 153 True) 154 context = self.expect_gdbremote_sequence() 155 self.assertIsNotNone(context) 156 if trunc: 157 self.assertEqual(context["size"], "0") 158 self.assertEqual(context["data"], "") 159 else: 160 self.assertEqual(context["size"], "11") # hex 161 self.assertEqual(context["data"], test_data[0x10:0x10 + 0x11]) 162 else: 163 self.expect_error() 164 165 # another offset 166 if read and not trunc: 167 self.reset_test_sequence() 168 self.test_sequence.add_log_lines( 169 ["read packet: $vFile:pread:%x,6,3#00" % (fd,), 170 {"direction": "send", 171 "regex": r"^\$F([0-9a-fA-F]+);(.+)#[0-9a-fA-F]{2}$", 172 "capture": {1: "size", 2: "data"}}], 173 True) 174 context = self.expect_gdbremote_sequence() 175 self.assertIsNotNone(context) 176 self.assertEqual(context["size"], "6") # hex 177 self.assertEqual(context["data"], test_data[3:3 + 6]) 178 179 # write data to the file 180 self.reset_test_sequence() 181 self.test_sequence.add_log_lines( 182 ["read packet: $vFile:pwrite:%x,6,somedata#00" % (fd,)], 183 True) 184 if write: 185 self.test_sequence.add_log_lines( 186 ["send packet: $F8#00"], 187 True) 188 self.expect_gdbremote_sequence() 189 else: 190 self.expect_error() 191 192 # close the file 193 self.reset_test_sequence() 194 self.test_sequence.add_log_lines( 195 ["read packet: $vFile:close:%x#00" % (fd,), 196 "send packet: $F0#00"], 197 True) 198 self.expect_gdbremote_sequence() 199 200 if write: 201 # check if the data was actually written 202 if creat: 203 temp_file = open(temp_path, "rb") 204 self.assertEqual(os.fstat(temp_file.fileno()).st_mode & 0o7777, 205 0o640) 206 temp_file.seek(0) 207 data = test_data.encode() 208 if trunc or creat: 209 data = b"\0" * 6 + b"somedata" 210 elif append: 211 data += b"somedata" 212 else: 213 data = data[:6] + b"somedata" + data[6 + 8:] 214 self.assertEqual(temp_file.read(), data) 215 finally: 216 if creat: 217 temp_dir.cleanup() 218 else: 219 temp_file.close() 220