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