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