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