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