1from lldbsuite.test.gdbclientutils import * 2from lldbsuite.test.decorators import * 3from lldbsuite.test.lldbgdbclient import GDBPlatformClientTestBase 4 5class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): 6 7 mydir = GDBPlatformClientTestBase.compute_mydir(__file__) 8 9 def test_file(self): 10 """Test mock operations on a remote file""" 11 12 class Responder(MockGDBServerResponder): 13 def vFile(self, packet): 14 if packet.startswith("vFile:open:"): 15 return "F10" 16 elif packet.startswith("vFile:pread:"): 17 return "Fd;frobnicator" 18 elif packet.startswith("vFile:pwrite:"): 19 return "Fa" 20 elif packet.startswith("vFile:close:"): 21 return "F0" 22 return "F-1,58" 23 24 self.server.responder = Responder() 25 26 self.match("platform file open /some/file.txt -v 0755", 27 [r"File Descriptor = 16"]) 28 self.match("platform file read 16 -o 11 -c 13", 29 [r"Return = 11\nData = \"frobnicator\""]) 30 self.match("platform file write 16 -o 11 -d teststring", 31 [r"Return = 10"]) 32 self.match("platform file close 16", 33 [r"file 16 closed."]) 34 self.assertPacketLogContains([ 35 "vFile:open:2f736f6d652f66696c652e747874,00000202,000001ed", 36 "vFile:pread:10,d,b", 37 "vFile:pwrite:10,b,teststring", 38 "vFile:close:10", 39 ]) 40 41 def test_file_fail(self): 42 """Test mocked failures of remote operations""" 43 44 class Responder(MockGDBServerResponder): 45 def vFile(self, packet): 46 # use ENOSYS as this constant differs between GDB Remote 47 # Protocol and Linux, so we can test the translation 48 return "F-1,58" 49 50 self.server.responder = Responder() 51 52 self.match("platform file open /some/file.txt -v 0755", 53 [r"error: Function not implemented"], 54 error=True) 55 self.match("platform file read 16 -o 11 -c 13", 56 [r"error: Function not implemented"], 57 error=True) 58 self.match("platform file write 16 -o 11 -d teststring", 59 [r"error: Function not implemented"], 60 error=True) 61 self.match("platform file close 16", 62 [r"error: Function not implemented"], 63 error=True) 64 self.assertPacketLogContains([ 65 "vFile:open:2f736f6d652f66696c652e747874,00000202,000001ed", 66 "vFile:pread:10,d,b", 67 "vFile:pwrite:10,b,teststring", 68 "vFile:close:10", 69 ]) 70 71 def test_file_size(self): 72 """Test 'platform get-size'""" 73 74 class Responder(MockGDBServerResponder): 75 def vFile(self, packet): 76 return "F1000" 77 78 self.server.responder = Responder() 79 80 self.match("platform get-size /some/file.txt", 81 [r"File size of /some/file\.txt \(remote\): 4096"]) 82 self.assertPacketLogContains([ 83 "vFile:size:2f736f6d652f66696c652e747874", 84 ]) 85 86 def test_file_size_fallback(self): 87 """Test 'platform get-size fallback to vFile:fstat'""" 88 89 class Responder(MockGDBServerResponder): 90 def vFile(self, packet): 91 if packet.startswith("vFile:open:"): 92 return "F5" 93 elif packet.startswith("vFile:fstat:"): 94 return "F40;" + 28 * "\0" + "\0\0\0\0\0\1\2\3" + 28 * "\0" 95 if packet.startswith("vFile:close:"): 96 return "F0" 97 return "" 98 99 self.server.responder = Responder() 100 101 self.match("platform get-size /some/file.txt", 102 [r"File size of /some/file\.txt \(remote\): 66051"]) 103 self.assertPacketLogContains([ 104 "vFile:size:2f736f6d652f66696c652e747874", 105 "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", 106 "vFile:fstat:5", 107 "vFile:close:5", 108 ]) 109 110 self.runCmd("platform disconnect") 111 112 # For a new onnection, we should attempt vFile:size once again. 113 server2 = MockGDBServer(self.server_socket_class()) 114 server2.responder = Responder() 115 server2.start() 116 self.addTearDownHook(lambda:server2.stop()) 117 self.runCmd("platform connect " + server2.get_connect_url()) 118 self.match("platform get-size /other/file.txt", 119 [r"File size of /other/file\.txt \(remote\): 66051"]) 120 121 self.assertPacketLogContains([ 122 "vFile:size:2f6f746865722f66696c652e747874", 123 "vFile:open:2f6f746865722f66696c652e747874,00000000,00000000", 124 "vFile:fstat:5", 125 "vFile:close:5", 126 ], 127 log=server2.responder.packetLog) 128 129 @skipIfWindows 130 def test_file_permissions(self): 131 """Test 'platform get-permissions'""" 132 133 class Responder(MockGDBServerResponder): 134 def vFile(self, packet): 135 return "F1a4" 136 137 self.server.responder = Responder() 138 139 self.match("platform get-permissions /some/file.txt", 140 [r"File permissions of /some/file\.txt \(remote\): 0o0644"]) 141 self.assertPacketLogContains([ 142 "vFile:mode:2f736f6d652f66696c652e747874", 143 ]) 144 145 @skipIfWindows 146 def test_file_permissions_fallback(self): 147 """Test 'platform get-permissions' fallback to fstat""" 148 149 class Responder(MockGDBServerResponder): 150 def vFile(self, packet): 151 if packet.startswith("vFile:open:"): 152 return "F5" 153 elif packet.startswith("vFile:fstat:"): 154 return "F40;" + 8 * "\0" + "\0\0\1\xA4" + 52 * "\0" 155 if packet.startswith("vFile:close:"): 156 return "F0" 157 return "" 158 159 self.server.responder = Responder() 160 161 try: 162 self.match("platform get-permissions /some/file.txt", 163 [r"File permissions of /some/file\.txt \(remote\): 0o0644"]) 164 self.assertPacketLogContains([ 165 "vFile:mode:2f736f6d652f66696c652e747874", 166 "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", 167 "vFile:fstat:5", 168 "vFile:close:5", 169 ]) 170 finally: 171 self.dbg.GetSelectedPlatform().DisconnectRemote() 172 173 def test_file_exists(self): 174 """Test 'platform file-exists'""" 175 176 class Responder(MockGDBServerResponder): 177 def vFile(self, packet): 178 return "F,1" 179 180 self.server.responder = Responder() 181 182 self.match("platform file-exists /some/file.txt", 183 [r"File /some/file\.txt \(remote\) exists"]) 184 self.assertPacketLogContains([ 185 "vFile:exists:2f736f6d652f66696c652e747874", 186 ]) 187 188 def test_file_exists_not(self): 189 """Test 'platform file-exists' with non-existing file""" 190 191 class Responder(MockGDBServerResponder): 192 def vFile(self, packet): 193 return "F,0" 194 195 self.server.responder = Responder() 196 197 self.match("platform file-exists /some/file.txt", 198 [r"File /some/file\.txt \(remote\) does not exist"]) 199 self.assertPacketLogContains([ 200 "vFile:exists:2f736f6d652f66696c652e747874", 201 ]) 202 203 def test_file_exists_fallback(self): 204 """Test 'platform file-exists' fallback to open""" 205 206 class Responder(MockGDBServerResponder): 207 def vFile(self, packet): 208 if packet.startswith("vFile:open:"): 209 return "F5" 210 if packet.startswith("vFile:close:"): 211 return "F0" 212 return "" 213 214 self.server.responder = Responder() 215 216 self.match("platform file-exists /some/file.txt", 217 [r"File /some/file\.txt \(remote\) exists"]) 218 self.assertPacketLogContains([ 219 "vFile:exists:2f736f6d652f66696c652e747874", 220 "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", 221 "vFile:close:5", 222 ]) 223 224 def test_file_exists_not_fallback(self): 225 """Test 'platform file-exists' fallback to open with non-existing file""" 226 227 class Responder(MockGDBServerResponder): 228 def vFile(self, packet): 229 if packet.startswith("vFile:open:"): 230 return "F-1,2" 231 return "" 232 233 self.server.responder = Responder() 234 235 self.match("platform file-exists /some/file.txt", 236 [r"File /some/file\.txt \(remote\) does not exist"]) 237 self.assertPacketLogContains([ 238 "vFile:exists:2f736f6d652f66696c652e747874", 239 "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", 240 ]) 241