1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Test Executor
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 Merge two test logs.
22 *
23 * \todo [2013-11-08 pyry] Write variant that can operate with less memory.
24 *//*--------------------------------------------------------------------*/
25
26 #include "xeTestLogParser.hpp"
27 #include "xeTestResultParser.hpp"
28 #include "xeTestLogWriter.hpp"
29 #include "deString.h"
30
31 #include <vector>
32 #include <string>
33 #include <cstdio>
34 #include <cstdlib>
35 #include <fstream>
36 #include <iostream>
37 #include <stdexcept>
38
39 using std::vector;
40 using std::string;
41 using std::set;
42 using std::map;
43
44 enum Flags
45 {
46 FLAG_USE_LAST_INFO = (1<<0)
47 };
48
49 struct CommandLine
50 {
CommandLineCommandLine51 CommandLine (void)
52 : flags(0)
53 {
54 }
55
56 vector<string> srcFilenames;
57 string dstFilename;
58 deUint32 flags;
59 };
60
61 class LogHandler : public xe::TestLogHandler
62 {
63 public:
LogHandler(xe::BatchResult * batchResult,deUint32 flags)64 LogHandler (xe::BatchResult* batchResult, deUint32 flags)
65 : m_batchResult (batchResult)
66 , m_flags (flags)
67 {
68 }
69
setSessionInfo(const xe::SessionInfo & info)70 void setSessionInfo (const xe::SessionInfo& info)
71 {
72 xe::SessionInfo& combinedInfo = m_batchResult->getSessionInfo();
73
74 if (m_flags & FLAG_USE_LAST_INFO)
75 {
76 if (!info.targetName.empty()) combinedInfo.targetName = info.targetName;
77 if (!info.releaseId.empty()) combinedInfo.releaseId = info.releaseId;
78 if (!info.releaseName.empty()) combinedInfo.releaseName = info.releaseName;
79 if (!info.candyTargetName.empty()) combinedInfo.candyTargetName = info.candyTargetName;
80 if (!info.configName.empty()) combinedInfo.configName = info.configName;
81 if (!info.resultName.empty()) combinedInfo.resultName = info.resultName;
82 if (!info.timestamp.empty()) combinedInfo.timestamp = info.timestamp;
83 }
84 else
85 {
86 if (combinedInfo.targetName.empty()) combinedInfo.targetName = info.targetName;
87 if (combinedInfo.releaseId.empty()) combinedInfo.releaseId = info.releaseId;
88 if (combinedInfo.releaseName.empty()) combinedInfo.releaseName = info.releaseName;
89 if (combinedInfo.candyTargetName.empty()) combinedInfo.candyTargetName = info.candyTargetName;
90 if (combinedInfo.configName.empty()) combinedInfo.configName = info.configName;
91 if (combinedInfo.resultName.empty()) combinedInfo.resultName = info.resultName;
92 if (combinedInfo.timestamp.empty()) combinedInfo.timestamp = info.timestamp;
93 }
94 }
95
startTestCaseResult(const char * casePath)96 xe::TestCaseResultPtr startTestCaseResult (const char* casePath)
97 {
98 if (m_batchResult->hasTestCaseResult(casePath))
99 {
100 xe::TestCaseResultPtr existingResult = m_batchResult->getTestCaseResult(casePath);
101 existingResult->clear();
102 return existingResult;
103 }
104 else
105 return m_batchResult->createTestCaseResult(casePath);
106 }
107
testCaseResultUpdated(const xe::TestCaseResultPtr &)108 void testCaseResultUpdated (const xe::TestCaseResultPtr&)
109 {
110 // Ignored.
111 }
112
testCaseResultComplete(const xe::TestCaseResultPtr &)113 void testCaseResultComplete (const xe::TestCaseResultPtr&)
114 {
115 // Ignored.
116 }
117
118 private:
119 xe::BatchResult* const m_batchResult;
120 const deUint32 m_flags;
121 };
122
readLogFile(xe::BatchResult * dstResult,const char * filename,deUint32 flags)123 static void readLogFile (xe::BatchResult* dstResult, const char* filename, deUint32 flags)
124 {
125 std::ifstream in (filename, std::ifstream::binary|std::ifstream::in);
126 LogHandler resultHandler (dstResult, flags);
127 xe::TestLogParser parser (&resultHandler);
128 deUint8 buf [2048];
129 int numRead = 0;
130
131 if (!in.good())
132 throw std::runtime_error(string("Failed to open '") + filename + "'");
133
134 for (;;)
135 {
136 in.read((char*)&buf[0], DE_LENGTH_OF_ARRAY(buf));
137 numRead = (int)in.gcount();
138
139 if (numRead <= 0)
140 break;
141
142 parser.parse(&buf[0], numRead);
143 }
144
145 in.close();
146 }
147
mergeTestLogs(const CommandLine & cmdLine)148 static void mergeTestLogs (const CommandLine& cmdLine)
149 {
150 xe::BatchResult batchResult;
151
152 for (vector<string>::const_iterator filename = cmdLine.srcFilenames.begin(); filename != cmdLine.srcFilenames.end(); ++filename)
153 readLogFile(&batchResult, filename->c_str(), cmdLine.flags);
154
155 if (!cmdLine.dstFilename.empty())
156 xe::writeBatchResultToFile(batchResult, cmdLine.dstFilename.c_str());
157 else
158 xe::writeTestLog(batchResult, std::cout);
159 }
160
printHelp(const char * binName)161 static void printHelp (const char* binName)
162 {
163 printf("%s: [filename] [[filename 2] ...]\n", binName);
164 printf(" --dst=[filename] Write final log to file, otherwise written to stdout.\n");
165 printf(" --info=[first|last] Select which session info to use (default: first).\n");
166 }
167
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)168 static bool parseCommandLine (CommandLine& cmdLine, int argc, const char* const* argv)
169 {
170 for (int argNdx = 1; argNdx < argc; argNdx++)
171 {
172 const char* arg = argv[argNdx];
173
174 if (!deStringBeginsWith(arg, "--"))
175 cmdLine.srcFilenames.push_back(arg);
176 else if (deStringBeginsWith(arg, "--dst="))
177 {
178 if (!cmdLine.dstFilename.empty())
179 return false;
180 cmdLine.dstFilename = arg+6;
181 }
182 else if (deStringEqual(arg, "--info=first"))
183 cmdLine.flags &= ~FLAG_USE_LAST_INFO;
184 else if (deStringEqual(arg, "--info=last"))
185 cmdLine.flags |= FLAG_USE_LAST_INFO;
186 else
187 return false;
188 }
189
190 if (cmdLine.srcFilenames.empty())
191 return false;
192
193 return true;
194 }
195
main(int argc,const char * const * argv)196 int main (int argc, const char* const* argv)
197 {
198 try
199 {
200 CommandLine cmdLine;
201
202 if (!parseCommandLine(cmdLine, argc, argv))
203 {
204 printHelp(argv[0]);
205 return -1;
206 }
207
208 mergeTestLogs(cmdLine);
209 }
210 catch (const std::exception& e)
211 {
212 printf("FATAL ERROR: %s\n", e.what());
213 return -1;
214 }
215
216 return 0;
217 }
218