Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / tools / lldb-server / TestGdbRemotePlatformFile.py
blob4c8ce01e8ba314f13dd2c70e6ebca059c7377cf5
1 # lldb test suite imports
2 from lldbsuite.test.decorators import *
3 from lldbsuite.test.lldbtest import TestBase
5 # gdb-remote-specific imports
6 import lldbgdbserverutils
7 from gdbremote_testcase import GdbRemoteTestCaseBase
9 import binascii
10 import os
11 import stat
12 import struct
13 import typing
16 class GDBStat(typing.NamedTuple):
17 st_dev: int
18 st_ino: int
19 st_mode: int
20 st_nlink: int
21 st_uid: int
22 st_gid: int
23 st_rdev: int
24 st_size: int
25 st_blksize: int
26 st_blocks: int
27 st_atime: int
28 st_mtime: int
29 st_ctime: int
32 def uint32_or_zero(x):
33 return x if x < 2**32 and x >= 0 else 0
36 def uint32_or_max(x):
37 return x if x < 2**32 and x >= 0 else 2**32 - 1
40 def uint32_trunc(x):
41 return x & (2**32 - 1)
44 class TestGdbRemotePlatformFile(GdbRemoteTestCaseBase):
45 @skipIfWindows
46 @add_test_categories(["llgs"])
47 def test_platform_file_rdonly(self):
48 self.vFile_test(read=True)
50 @skipIfWindows
51 @add_test_categories(["llgs"])
52 def test_platform_file_wronly(self):
53 self.vFile_test(write=True)
55 @skipIfWindows
56 @add_test_categories(["llgs"])
57 def test_platform_file_rdwr(self):
58 self.vFile_test(read=True, write=True)
60 @skipIfWindows
61 @add_test_categories(["llgs"])
62 def test_platform_file_wronly_append(self):
63 self.vFile_test(write=True, append=True)
65 @skipIfWindows
66 @add_test_categories(["llgs"])
67 def test_platform_file_rdwr_append(self):
68 self.vFile_test(read=True, write=True, append=True)
70 @skipIfWindows
71 @add_test_categories(["llgs"])
72 def test_platform_file_wronly_trunc(self):
73 self.vFile_test(write=True, trunc=True)
75 @skipIfWindows
76 @add_test_categories(["llgs"])
77 def test_platform_file_rdwr_trunc(self):
78 self.vFile_test(read=True, write=True, trunc=True)
80 @skipIfWindows
81 @add_test_categories(["llgs"])
82 def test_platform_file_wronly_creat(self):
83 self.vFile_test(write=True, creat=True)
85 @skipIfWindows
86 @add_test_categories(["llgs"])
87 def test_platform_file_wronly_creat_excl(self):
88 self.vFile_test(write=True, creat=True, excl=True)
90 @skipIfWindows
91 @add_test_categories(["llgs"])
92 def test_platform_file_wronly_fail(self):
93 server = self.connect_to_debug_monitor()
94 self.assertIsNotNone(server)
96 temp_path = self.getBuildArtifact("test")
97 self.assertFalse(os.path.exists(temp_path))
99 # attempt to open the file without O_CREAT
100 self.do_handshake()
101 self.test_sequence.add_log_lines(
103 "read packet: $vFile:open:%s,1,0#00"
104 % (binascii.b2a_hex(temp_path.encode()).decode(),),
105 {"direction": "send", "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"},
107 True,
109 self.expect_gdbremote_sequence()
111 @skipIfWindows
112 @add_test_categories(["llgs"])
113 def test_platform_file_wronly_creat_excl_fail(self):
114 server = self.connect_to_debug_monitor()
115 self.assertIsNotNone(server)
117 temp_file = self.getBuildArtifact("test")
118 with open(temp_file, "wb"):
119 pass
121 # attempt to open the file with O_CREAT|O_EXCL
122 self.do_handshake()
123 self.test_sequence.add_log_lines(
125 "read packet: $vFile:open:%s,a01,0#00"
126 % (binascii.b2a_hex(temp_file.encode()).decode(),),
127 {"direction": "send", "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"},
129 True,
131 self.expect_gdbremote_sequence()
133 @skipIfWindows
134 @add_test_categories(["llgs"])
135 def test_platform_file_size(self):
136 server = self.connect_to_debug_monitor()
137 self.assertIsNotNone(server)
139 temp_path = self.getBuildArtifact("test")
140 test_data = b"test data of some length"
141 with open(temp_path, "wb") as temp_file:
142 temp_file.write(test_data)
144 self.do_handshake()
145 self.test_sequence.add_log_lines(
147 "read packet: $vFile:size:%s#00"
148 % (binascii.b2a_hex(temp_path.encode()).decode(),),
150 "direction": "send",
151 "regex": r"^\$F([0-9a-fA-F]+)+#[0-9a-fA-F]{2}$",
152 "capture": {1: "size"},
155 True,
157 context = self.expect_gdbremote_sequence()
158 self.assertEqual(int(context["size"], 16), len(test_data))
160 @skipIfWindows
161 @add_test_categories(["llgs"])
162 def test_platform_file_mode(self):
163 server = self.connect_to_debug_monitor()
164 self.assertIsNotNone(server)
166 temp_path = self.getBuildArtifact("test")
167 test_mode = 0o751
169 with open(temp_path, "wb") as temp_file:
170 os.chmod(temp_file.fileno(), test_mode)
172 self.do_handshake()
173 self.test_sequence.add_log_lines(
175 "read packet: $vFile:mode:%s#00"
176 % (binascii.b2a_hex(temp_path.encode()).decode(),),
178 "direction": "send",
179 "regex": r"^\$F([0-9a-fA-F]+)+#[0-9a-fA-F]{2}$",
180 "capture": {1: "mode"},
183 True,
185 context = self.expect_gdbremote_sequence()
186 self.assertEqual(int(context["mode"], 16), test_mode)
188 @skipIfWindows
189 @add_test_categories(["llgs"])
190 def test_platform_file_mode_fail(self):
191 server = self.connect_to_debug_monitor()
192 self.assertIsNotNone(server)
194 temp_path = self.getBuildArtifact("nonexist")
196 self.do_handshake()
197 self.test_sequence.add_log_lines(
199 "read packet: $vFile:mode:%s#00"
200 % (binascii.b2a_hex(temp_path.encode()).decode(),),
201 {"direction": "send", "regex": r"^\$F-1,0*2+#[0-9a-fA-F]{2}$"},
203 True,
205 self.expect_gdbremote_sequence()
207 @skipIfWindows
208 @add_test_categories(["llgs"])
209 def test_platform_file_exists(self):
210 server = self.connect_to_debug_monitor()
211 self.assertIsNotNone(server)
213 temp_path = self.getBuildArtifact("test")
214 with open(temp_path, "wb"):
215 pass
217 self.do_handshake()
218 self.test_sequence.add_log_lines(
220 "read packet: $vFile:exists:%s#00"
221 % (binascii.b2a_hex(temp_path.encode()).decode(),),
222 "send packet: $F,1#00",
224 True,
226 self.expect_gdbremote_sequence()
228 @skipIfWindows
229 @add_test_categories(["llgs"])
230 def test_platform_file_exists_not(self):
231 server = self.connect_to_debug_monitor()
232 self.assertIsNotNone(server)
234 test_path = self.getBuildArtifact("nonexist")
235 self.do_handshake()
236 self.test_sequence.add_log_lines(
238 "read packet: $vFile:exists:%s#00"
239 % (binascii.b2a_hex(test_path.encode()).decode(),),
240 "send packet: $F,0#00",
242 True,
244 self.expect_gdbremote_sequence()
246 @skipIfWindows
247 @add_test_categories(["llgs"])
248 def test_platform_file_fstat(self):
249 server = self.connect_to_debug_monitor()
250 self.assertIsNotNone(server)
252 with tempfile.NamedTemporaryFile() as temp_file:
253 temp_file.write(b"some test data for stat")
254 temp_file.flush()
256 self.do_handshake()
257 self.test_sequence.add_log_lines(
259 "read packet: $vFile:open:%s,0,0#00"
260 % (binascii.b2a_hex(temp_file.name.encode()).decode(),),
262 "direction": "send",
263 "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$",
264 "capture": {1: "fd"},
267 True,
270 context = self.expect_gdbremote_sequence()
271 self.assertIsNotNone(context)
272 fd = int(context["fd"], 16)
274 self.reset_test_sequence()
275 self.test_sequence.add_log_lines(
277 "read packet: $vFile:fstat:%x#00" % (fd,),
279 "direction": "send",
280 "regex": r"^\$F([0-9a-fA-F]+);(.*)#[0-9a-fA-F]{2}$",
281 "capture": {1: "size", 2: "data"},
284 True,
286 context = self.expect_gdbremote_sequence()
287 self.assertEqual(int(context["size"], 16), 64)
288 # NB: we're using .encode() as a hack because the test suite
289 # is wrongly using (unicode) str instead of bytes
290 gdb_stat = GDBStat(
291 *struct.unpack(
292 ">IIIIIIIQQQIII",
293 self.decode_gdbremote_binary(context["data"]).encode("iso-8859-1"),
296 sys_stat = os.fstat(temp_file.fileno())
298 self.assertEqual(gdb_stat.st_dev, uint32_or_zero(sys_stat.st_dev))
299 self.assertEqual(gdb_stat.st_ino, uint32_or_zero(sys_stat.st_ino))
300 self.assertEqual(gdb_stat.st_mode, uint32_trunc(sys_stat.st_mode))
301 self.assertEqual(gdb_stat.st_nlink, uint32_or_max(sys_stat.st_nlink))
302 self.assertEqual(gdb_stat.st_uid, uint32_or_zero(sys_stat.st_uid))
303 self.assertEqual(gdb_stat.st_gid, uint32_or_zero(sys_stat.st_gid))
304 self.assertEqual(gdb_stat.st_rdev, uint32_or_zero(sys_stat.st_rdev))
305 self.assertEqual(gdb_stat.st_size, sys_stat.st_size)
306 self.assertEqual(gdb_stat.st_blksize, sys_stat.st_blksize)
307 self.assertEqual(gdb_stat.st_blocks, sys_stat.st_blocks)
308 self.assertEqual(gdb_stat.st_atime, uint32_or_zero(int(sys_stat.st_atime)))
309 self.assertEqual(gdb_stat.st_mtime, uint32_or_zero(int(sys_stat.st_mtime)))
310 self.assertEqual(gdb_stat.st_ctime, uint32_or_zero(int(sys_stat.st_ctime)))
312 self.reset_test_sequence()
313 self.test_sequence.add_log_lines(
314 ["read packet: $vFile:close:%x#00" % (fd,), "send packet: $F0#00"], True
316 self.expect_gdbremote_sequence()
318 def expect_error(self):
319 self.test_sequence.add_log_lines(
320 [{"direction": "send", "regex": r"^\$F-1,[0-9a-fA-F]+#[0-9a-fA-F]{2}$"}],
321 True,
323 self.expect_gdbremote_sequence()
325 def vFile_test(
326 self,
327 read=False,
328 write=False,
329 append=False,
330 trunc=False,
331 creat=False,
332 excl=False,
334 if read and write:
335 mode = 2
336 elif write:
337 mode = 1
338 else: # read
339 mode = 0
340 if append:
341 mode |= 8
342 if creat:
343 mode |= 0x200
344 if trunc:
345 mode |= 0x400
346 if excl:
347 mode |= 0x800
349 old_umask = os.umask(0o22)
350 try:
351 server = self.connect_to_debug_monitor()
352 finally:
353 os.umask(old_umask)
354 self.assertIsNotNone(server)
356 # create a temporary file with some data
357 temp_path = self.getBuildArtifact("test")
358 test_data = "some test data longer than 16 bytes\n"
360 if creat:
361 self.assertFalse(os.path.exists(temp_path))
362 else:
363 with open(temp_path, "wb") as temp_file:
364 temp_file.write(test_data.encode())
366 # open the file for reading
367 self.do_handshake()
368 self.test_sequence.add_log_lines(
370 "read packet: $vFile:open:%s,%x,1a0#00"
371 % (binascii.b2a_hex(temp_path.encode()).decode(), mode),
373 "direction": "send",
374 "regex": r"^\$F([0-9a-fA-F]+)#[0-9a-fA-F]{2}$",
375 "capture": {1: "fd"},
378 True,
381 context = self.expect_gdbremote_sequence()
382 self.assertIsNotNone(context)
383 fd = int(context["fd"], 16)
385 # read data from the file
386 self.reset_test_sequence()
387 self.test_sequence.add_log_lines(
388 ["read packet: $vFile:pread:%x,11,10#00" % (fd,)], True
390 if read:
391 self.test_sequence.add_log_lines(
394 "direction": "send",
395 "regex": r"^\$F([0-9a-fA-F]+);(.*)#[0-9a-fA-F]{2}$",
396 "capture": {1: "size", 2: "data"},
399 True,
401 context = self.expect_gdbremote_sequence()
402 self.assertIsNotNone(context)
403 if trunc:
404 self.assertEqual(context["size"], "0")
405 self.assertEqual(context["data"], "")
406 else:
407 self.assertEqual(context["size"], "11") # hex
408 self.assertEqual(context["data"], test_data[0x10 : 0x10 + 0x11])
409 else:
410 self.expect_error()
412 # another offset
413 if read and not trunc:
414 self.reset_test_sequence()
415 self.test_sequence.add_log_lines(
417 "read packet: $vFile:pread:%x,6,3#00" % (fd,),
419 "direction": "send",
420 "regex": r"^\$F([0-9a-fA-F]+);(.+)#[0-9a-fA-F]{2}$",
421 "capture": {1: "size", 2: "data"},
424 True,
426 context = self.expect_gdbremote_sequence()
427 self.assertIsNotNone(context)
428 self.assertEqual(context["size"], "6") # hex
429 self.assertEqual(context["data"], test_data[3 : 3 + 6])
431 # write data to the file
432 self.reset_test_sequence()
433 self.test_sequence.add_log_lines(
434 ["read packet: $vFile:pwrite:%x,6,somedata#00" % (fd,)], True
436 if write:
437 self.test_sequence.add_log_lines(["send packet: $F8#00"], True)
438 self.expect_gdbremote_sequence()
439 else:
440 self.expect_error()
442 # close the file
443 self.reset_test_sequence()
444 self.test_sequence.add_log_lines(
445 ["read packet: $vFile:close:%x#00" % (fd,), "send packet: $F0#00"], True
447 self.expect_gdbremote_sequence()
449 if write:
450 # check if the data was actually written
451 with open(temp_path, "rb") as temp_file:
452 if creat:
453 self.assertEqual(
454 os.fstat(temp_file.fileno()).st_mode & 0o7777, 0o640
456 data = test_data.encode()
457 if trunc or creat:
458 data = b"\0" * 6 + b"somedata"
459 elif append:
460 data += b"somedata"
461 else:
462 data = data[:6] + b"somedata" + data[6 + 8 :]
463 self.assertEqual(temp_file.read(), data)