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 server = self.connect_to_debug_monitor() 106 self.assertIsNotNone(server) 107 108 # create a temporary file with some data 109 test_data = 'some test data longer than 16 bytes\n' 110 if creat: 111 temp_dir = tempfile.TemporaryDirectory() 112 else: 113 temp_file = tempfile.NamedTemporaryFile() 114 115 try: 116 if creat: 117 temp_path = os.path.join(temp_dir.name, "test") 118 self.assertFalse(os.path.exists(temp_path)) 119 else: 120 temp_file.write(test_data.encode()) 121 temp_file.flush() 122 temp_path = temp_file.name 123 124 # open the file for reading 125 self.do_handshake() 126 self.test_sequence.add_log_lines( 127 ["read packet: $vFile:open:%s,%x,1a0#00" % ( 128 binascii.b2a_hex(temp_path.encode()).decode(), 129 mode), 130 {"direction": "send", 131 "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$", 132 "capture": {1: "fd"}}], 133 True) 134 135 context = self.expect_gdbremote_sequence() 136 self.assertIsNotNone(context) 137 fd = int(context["fd"], 16) 138 139 # read data from the file 140 self.reset_test_sequence() 141 self.test_sequence.add_log_lines( 142 ["read packet: $vFile:pread:%x,11,10#00" % (fd,)], 143 True) 144 if read: 145 self.test_sequence.add_log_lines( 146 [{"direction": "send", 147 "regex": r"^\$F([0-9a-fA-F]+);(.*)#[0-9a-fA-F]{2}$", 148 "capture": {1: "size", 2: "data"}}], 149 True) 150 context = self.expect_gdbremote_sequence() 151 self.assertIsNotNone(context) 152 if trunc: 153 self.assertEqual(context["size"], "0") 154 self.assertEqual(context["data"], "") 155 else: 156 self.assertEqual(context["size"], "11") # hex 157 self.assertEqual(context["data"], test_data[0x10:0x10 + 0x11]) 158 else: 159 self.expect_error() 160 161 # another offset 162 if read and not trunc: 163 self.reset_test_sequence() 164 self.test_sequence.add_log_lines( 165 ["read packet: $vFile:pread:%x,6,3#00" % (fd,), 166 {"direction": "send", 167 "regex": r"^\$F([0-9a-fA-F]+);(.+)#[0-9a-fA-F]{2}$", 168 "capture": {1: "size", 2: "data"}}], 169 True) 170 context = self.expect_gdbremote_sequence() 171 self.assertIsNotNone(context) 172 self.assertEqual(context["size"], "6") # hex 173 self.assertEqual(context["data"], test_data[3:3 + 6]) 174 175 # write data to the file 176 self.reset_test_sequence() 177 self.test_sequence.add_log_lines( 178 ["read packet: $vFile:pwrite:%x,6,somedata#00" % (fd,)], 179 True) 180 if write: 181 self.test_sequence.add_log_lines( 182 ["send packet: $F8#00"], 183 True) 184 self.expect_gdbremote_sequence() 185 else: 186 self.expect_error() 187 188 # close the file 189 self.reset_test_sequence() 190 self.test_sequence.add_log_lines( 191 ["read packet: $vFile:close:%x#00" % (fd,), 192 "send packet: $F0#00"], 193 True) 194 self.expect_gdbremote_sequence() 195 196 if write: 197 # check if the data was actually written 198 if creat: 199 temp_file = open(temp_path, "rb") 200 self.assertEqual(os.fstat(temp_file.fileno()).st_mode & 0o7777, 201 0o640) 202 temp_file.seek(0) 203 data = test_data.encode() 204 if trunc or creat: 205 data = b"\0" * 6 + b"somedata" 206 elif append: 207 data += b"somedata" 208 else: 209 data = data[:6] + b"somedata" + data[6 + 8:] 210 self.assertEqual(temp_file.read(), data) 211 finally: 212 if creat: 213 temp_dir.cleanup() 214 else: 215 temp_file.close() 216