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