Add support for EGL_EXT_pixel_format_float am: 521bf8a7c3 am: 4b7baeace7 am: 86683f95...
[platform/upstream/VK-GL-CTS.git] / execserver / tools / xsClient.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Execution Server
3  * ---------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief ExecServer Client.
22  *//*--------------------------------------------------------------------*/
23
24 #include "xsDefs.hpp"
25 #include "xsProtocol.hpp"
26 #include "deSocket.hpp"
27
28 #include "deString.h"
29
30 #include <memory>
31 #include <sstream>
32 #include <fstream>
33 #include <cstdio>
34 #include <cstdlib>
35
36 using std::string;
37 using std::vector;
38
39 namespace xs
40 {
41
42 typedef std::auto_ptr<Message> ScopedMsgPtr;
43
44 class SocketError : public Error
45 {
46 public:
47         SocketError (deSocketResult result, const char* message, const char* file, int line)
48                 : Error         (message, deGetSocketResultName(result), file, line)
49                 , m_result      (result)
50         {
51         }
52
53         deSocketResult getResult (void) const
54         {
55                 return m_result;
56         }
57
58 private:
59         deSocketResult m_result;
60 };
61
62 // Helpers.
63 void sendMessage (de::Socket& socket, const Message& message)
64 {
65         // Format message.
66         vector<deUint8> buf;
67         message.write(buf);
68
69         // Write to socket.
70         size_t pos = 0;
71         while (pos < buf.size())
72         {
73                 size_t                  numLeft         = buf.size() - pos;
74                 size_t                  numSent         = 0;
75                 deSocketResult  result          = socket.send(&buf[pos], numLeft, &numSent);
76
77                 if (result != DE_SOCKETRESULT_SUCCESS)
78                         throw SocketError(result, "send() failed", __FILE__, __LINE__);
79
80                 pos += numSent;
81         }
82 }
83
84 void readBytes (de::Socket& socket, vector<deUint8>& dst, size_t numBytes)
85 {
86         size_t numRead = 0;
87         dst.resize(numBytes);
88         while (numRead < numBytes)
89         {
90                 size_t                  numLeft         = numBytes - numRead;
91                 size_t                  curNumRead      = 0;
92                 deSocketResult  result          = socket.receive(&dst[numRead], numLeft, &curNumRead);
93
94                 if (result != DE_SOCKETRESULT_SUCCESS)
95                         throw SocketError(result, "receive() failed", __FILE__, __LINE__);
96
97                 numRead += curNumRead;
98         }
99 }
100
101 Message* readMessage (de::Socket& socket)
102 {
103         // Header.
104         vector<deUint8> header;
105         readBytes(socket, header, MESSAGE_HEADER_SIZE);
106
107         MessageType     type;
108         size_t          messageSize;
109         Message::parseHeader(&header[0], (int)header.size(), type, messageSize);
110
111         // Simple messages without any data.
112         switch (type)
113         {
114                 case MESSAGETYPE_KEEPALIVE:                             return new KeepAliveMessage();
115                 case MESSAGETYPE_PROCESS_STARTED:               return new ProcessStartedMessage();
116                 default:
117                         break; // Read message with data.
118         }
119
120         vector<deUint8> messageBuf;
121         readBytes(socket, messageBuf, messageSize-MESSAGE_HEADER_SIZE);
122
123         switch (type)
124         {
125                 case MESSAGETYPE_HELLO:                                 return new HelloMessage(&messageBuf[0], (int)messageBuf.size());
126                 case MESSAGETYPE_TEST:                                  return new TestMessage(&messageBuf[0], (int)messageBuf.size());
127                 case MESSAGETYPE_PROCESS_LOG_DATA:              return new ProcessLogDataMessage(&messageBuf[0], (int)messageBuf.size());
128                 case MESSAGETYPE_INFO:                                  return new InfoMessage(&messageBuf[0], (int)messageBuf.size());
129                 case MESSAGETYPE_PROCESS_LAUNCH_FAILED: return new ProcessLaunchFailedMessage(&messageBuf[0], (int)messageBuf.size());
130                 case MESSAGETYPE_PROCESS_FINISHED:              return new ProcessFinishedMessage(&messageBuf[0], (int)messageBuf.size());
131                 default:
132                         XS_FAIL("Unknown message");
133         }
134 }
135
136 class CommandLine
137 {
138 public:
139         de::SocketAddress       address;
140         std::string                     program;
141         std::string                     params;
142         std::string                     workingDir;
143         std::string                     caseList;
144         std::string                     dstFileName;
145 };
146
147 class Client
148 {
149 public:
150                                                 Client          (const CommandLine& cmdLine);
151                                                 ~Client         (void);
152
153         void                            run                     (void);
154
155 private:
156         const CommandLine&      m_cmdLine;
157         de::Socket                      m_socket;
158 };
159
160 Client::Client (const CommandLine& cmdLine)
161         : m_cmdLine(cmdLine)
162 {
163 }
164
165 Client::~Client (void)
166 {
167 }
168
169 void Client::run (void)
170 {
171         // Connect to server.
172         m_socket.connect(m_cmdLine.address);
173
174         printf("Connected to %s:%d!\n", m_cmdLine.address.getHost(), m_cmdLine.address.getPort());
175
176         // Open result file.
177         std::fstream out(m_cmdLine.dstFileName.c_str(), std::fstream::out|std::fstream::binary);
178
179         printf("  writing to %s\n", m_cmdLine.dstFileName.c_str());
180
181         // Send execution request.
182         {
183                 ExecuteBinaryMessage msg;
184
185                 msg.name                = m_cmdLine.program;
186                 msg.params              = m_cmdLine.params;
187                 msg.workDir             = m_cmdLine.workingDir;
188                 msg.caseList    = m_cmdLine.caseList;
189
190                 sendMessage(m_socket, msg);
191                 printf("  execution request sent.\n");
192         }
193
194         // Run client loop.
195         bool isRunning = true;
196         while (isRunning)
197         {
198                 ScopedMsgPtr msg(readMessage(m_socket));
199
200                 switch (msg->type)
201                 {
202                         case MESSAGETYPE_HELLO:
203                                 printf("  HelloMessage\n");
204                                 break;
205
206                         case MESSAGETYPE_KEEPALIVE:
207                         {
208                                 printf("  KeepAliveMessage\n");
209
210                                 // Reply with keepalive.
211                                 sendMessage(m_socket, KeepAliveMessage());
212                                 break;
213                         }
214
215                         case MESSAGETYPE_INFO:
216                                 printf("  InfoMessage: '%s'\n", static_cast<InfoMessage*>(msg.get())->info.c_str());
217                                 break;
218
219                         case MESSAGETYPE_PROCESS_STARTED:
220                                 printf("  ProcessStartedMessage\n");
221                                 break;
222
223                         case MESSAGETYPE_PROCESS_FINISHED:
224                                 printf("  ProcessFinished: exit code = %d\n", static_cast<ProcessFinishedMessage*>(msg.get())->exitCode);
225                                 isRunning = false;
226                                 break;
227
228                         case MESSAGETYPE_PROCESS_LAUNCH_FAILED:
229                                 printf("  ProcessLaunchFailed: '%s'\n", static_cast<ProcessLaunchFailedMessage*>(msg.get())->reason.c_str());
230                                 isRunning = false;
231                                 break;
232
233                         case MESSAGETYPE_PROCESS_LOG_DATA:
234                         {
235                                 ProcessLogDataMessage* logDataMsg = static_cast<ProcessLogDataMessage*>(msg.get());
236                                 printf("  ProcessLogDataMessage: %d bytes\n", (int)logDataMsg->logData.length());
237                                 out << logDataMsg->logData;
238                                 break;
239                         }
240
241                         default:
242                                 XS_FAIL("Unknown message");
243                                 break;
244                 }
245         }
246
247         // Close output file.
248         out.close();
249
250         // Close connection.
251         m_socket.shutdown();
252         m_socket.close();
253
254         printf("Done!\n");
255 }
256
257 string parseString (const char* str)
258 {
259         if (str[0] == '\'' || str[0] == '"')
260         {
261                 const char*                     p               = str;
262                 char                            endChar = *p++;
263                 std::ostringstream      o;
264
265                 while (*p != endChar && *p)
266                 {
267                         if (*p == '\\')
268                         {
269                                 switch (p[1])
270                                 {
271                                         case 0:         DE_ASSERT(DE_FALSE);    break;
272                                         case 'n':       o << '\n';                              break;
273                                         case 't':       o << '\t';                              break;
274                                         default:        o << p[1];                              break;
275                                 }
276
277                                 p += 2;
278                         }
279                         else
280                                 o << *p++;
281                 }
282
283                 return o.str();
284         }
285         else
286                 return string(str);
287 }
288
289 void printHelp (const char* binName)
290 {
291         printf("%s:\n", binName);
292         printf("  --host=[host]          Connect to host [host]\n");
293         printf("  --port=[name]          Use port [port]\n");
294         printf("  --program=[program]    Test program\n");
295         printf("  --params=[params]      Test program params\n");
296         printf("  --workdir=[dir]        Working directory\n");
297         printf("  --caselist=[caselist]  Test case list\n");
298         printf("  --out=filename         Test result file\n");
299 }
300
301 int runClient (int argc, const char* const* argv)
302 {
303         CommandLine cmdLine;
304
305         // Defaults.
306         cmdLine.address.setHost("127.0.0.1");
307         cmdLine.address.setPort(50016);
308         cmdLine.dstFileName = "TestResults.qpa";
309
310         // Parse command line.
311         for (int argNdx = 1; argNdx < argc; argNdx++)
312         {
313                 const char* arg = argv[argNdx];
314
315                 if (deStringBeginsWith(arg, "--port="))
316                         cmdLine.address.setPort(atoi(arg+7));
317                 else if (deStringBeginsWith(arg, "--host="))
318                         cmdLine.address.setHost(parseString(arg+7).c_str());
319                 else if (deStringBeginsWith(arg, "--program="))
320                         cmdLine.program = parseString(arg+10);
321                 else if (deStringBeginsWith(arg, "--params="))
322                         cmdLine.params = parseString(arg+9);
323                 else if (deStringBeginsWith(arg, "--workdir="))
324                         cmdLine.workingDir = parseString(arg+10);
325                 else if (deStringBeginsWith(arg, "--caselist="))
326                         cmdLine.caseList = parseString(arg+11);
327                 else if  (deStringBeginsWith(arg, "--out="))
328                         cmdLine.dstFileName = parseString(arg+6);
329                 else
330                 {
331                         printHelp(argv[0]);
332                         return -1;
333                 }
334         }
335
336         // Run client.
337         try
338         {
339                 Client client(cmdLine);
340                 client.run();
341         }
342         catch (const std::exception& e)
343         {
344                 printf("%s\n", e.what());
345                 return -1;
346         }
347
348         return 0;
349 }
350
351 } // xs
352
353 int main (int argc, const char* const* argv)
354 {
355         return xs::runClient(argc, argv);
356 }