1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker * drawElements Quality Program Test Executor
3*35238bceSAndroid Build Coastguard Worker * ------------------------------------------
4*35238bceSAndroid Build Coastguard Worker *
5*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker *
11*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker *
19*35238bceSAndroid Build Coastguard Worker *//*!
20*35238bceSAndroid Build Coastguard Worker * \file
21*35238bceSAndroid Build Coastguard Worker * \brief Merge two test logs.
22*35238bceSAndroid Build Coastguard Worker *
23*35238bceSAndroid Build Coastguard Worker * \todo [2013-11-08 pyry] Write variant that can operate with less memory.
24*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker
26*35238bceSAndroid Build Coastguard Worker #include "xeTestLogParser.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "xeTestResultParser.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "xeTestLogWriter.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deString.h"
30*35238bceSAndroid Build Coastguard Worker
31*35238bceSAndroid Build Coastguard Worker #include <vector>
32*35238bceSAndroid Build Coastguard Worker #include <string>
33*35238bceSAndroid Build Coastguard Worker #include <cstdio>
34*35238bceSAndroid Build Coastguard Worker #include <cstdlib>
35*35238bceSAndroid Build Coastguard Worker #include <fstream>
36*35238bceSAndroid Build Coastguard Worker #include <iostream>
37*35238bceSAndroid Build Coastguard Worker #include <stdexcept>
38*35238bceSAndroid Build Coastguard Worker
39*35238bceSAndroid Build Coastguard Worker using std::map;
40*35238bceSAndroid Build Coastguard Worker using std::set;
41*35238bceSAndroid Build Coastguard Worker using std::string;
42*35238bceSAndroid Build Coastguard Worker using std::vector;
43*35238bceSAndroid Build Coastguard Worker
44*35238bceSAndroid Build Coastguard Worker enum Flags
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker FLAG_USE_LAST_INFO = (1 << 0)
47*35238bceSAndroid Build Coastguard Worker };
48*35238bceSAndroid Build Coastguard Worker
49*35238bceSAndroid Build Coastguard Worker struct CommandLine
50*35238bceSAndroid Build Coastguard Worker {
CommandLineCommandLine51*35238bceSAndroid Build Coastguard Worker CommandLine(void) : flags(0)
52*35238bceSAndroid Build Coastguard Worker {
53*35238bceSAndroid Build Coastguard Worker }
54*35238bceSAndroid Build Coastguard Worker
55*35238bceSAndroid Build Coastguard Worker vector<string> srcFilenames;
56*35238bceSAndroid Build Coastguard Worker string dstFilename;
57*35238bceSAndroid Build Coastguard Worker uint32_t flags;
58*35238bceSAndroid Build Coastguard Worker };
59*35238bceSAndroid Build Coastguard Worker
60*35238bceSAndroid Build Coastguard Worker class LogHandler : public xe::TestLogHandler
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker public:
LogHandler(xe::BatchResult * batchResult,uint32_t flags)63*35238bceSAndroid Build Coastguard Worker LogHandler(xe::BatchResult *batchResult, uint32_t flags) : m_batchResult(batchResult), m_flags(flags)
64*35238bceSAndroid Build Coastguard Worker {
65*35238bceSAndroid Build Coastguard Worker }
66*35238bceSAndroid Build Coastguard Worker
setSessionInfo(const xe::SessionInfo & info)67*35238bceSAndroid Build Coastguard Worker void setSessionInfo(const xe::SessionInfo &info)
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker xe::SessionInfo &combinedInfo = m_batchResult->getSessionInfo();
70*35238bceSAndroid Build Coastguard Worker
71*35238bceSAndroid Build Coastguard Worker if (m_flags & FLAG_USE_LAST_INFO)
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker if (!info.targetName.empty())
74*35238bceSAndroid Build Coastguard Worker combinedInfo.targetName = info.targetName;
75*35238bceSAndroid Build Coastguard Worker if (!info.releaseId.empty())
76*35238bceSAndroid Build Coastguard Worker combinedInfo.releaseId = info.releaseId;
77*35238bceSAndroid Build Coastguard Worker if (!info.releaseName.empty())
78*35238bceSAndroid Build Coastguard Worker combinedInfo.releaseName = info.releaseName;
79*35238bceSAndroid Build Coastguard Worker if (!info.candyTargetName.empty())
80*35238bceSAndroid Build Coastguard Worker combinedInfo.candyTargetName = info.candyTargetName;
81*35238bceSAndroid Build Coastguard Worker if (!info.configName.empty())
82*35238bceSAndroid Build Coastguard Worker combinedInfo.configName = info.configName;
83*35238bceSAndroid Build Coastguard Worker if (!info.resultName.empty())
84*35238bceSAndroid Build Coastguard Worker combinedInfo.resultName = info.resultName;
85*35238bceSAndroid Build Coastguard Worker if (!info.timestamp.empty())
86*35238bceSAndroid Build Coastguard Worker combinedInfo.timestamp = info.timestamp;
87*35238bceSAndroid Build Coastguard Worker }
88*35238bceSAndroid Build Coastguard Worker else
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker if (combinedInfo.targetName.empty())
91*35238bceSAndroid Build Coastguard Worker combinedInfo.targetName = info.targetName;
92*35238bceSAndroid Build Coastguard Worker if (combinedInfo.releaseId.empty())
93*35238bceSAndroid Build Coastguard Worker combinedInfo.releaseId = info.releaseId;
94*35238bceSAndroid Build Coastguard Worker if (combinedInfo.releaseName.empty())
95*35238bceSAndroid Build Coastguard Worker combinedInfo.releaseName = info.releaseName;
96*35238bceSAndroid Build Coastguard Worker if (combinedInfo.candyTargetName.empty())
97*35238bceSAndroid Build Coastguard Worker combinedInfo.candyTargetName = info.candyTargetName;
98*35238bceSAndroid Build Coastguard Worker if (combinedInfo.configName.empty())
99*35238bceSAndroid Build Coastguard Worker combinedInfo.configName = info.configName;
100*35238bceSAndroid Build Coastguard Worker if (combinedInfo.resultName.empty())
101*35238bceSAndroid Build Coastguard Worker combinedInfo.resultName = info.resultName;
102*35238bceSAndroid Build Coastguard Worker if (combinedInfo.timestamp.empty())
103*35238bceSAndroid Build Coastguard Worker combinedInfo.timestamp = info.timestamp;
104*35238bceSAndroid Build Coastguard Worker }
105*35238bceSAndroid Build Coastguard Worker }
106*35238bceSAndroid Build Coastguard Worker
startTestCaseResult(const char * casePath)107*35238bceSAndroid Build Coastguard Worker xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
108*35238bceSAndroid Build Coastguard Worker {
109*35238bceSAndroid Build Coastguard Worker if (m_batchResult->hasTestCaseResult(casePath))
110*35238bceSAndroid Build Coastguard Worker {
111*35238bceSAndroid Build Coastguard Worker xe::TestCaseResultPtr existingResult = m_batchResult->getTestCaseResult(casePath);
112*35238bceSAndroid Build Coastguard Worker existingResult->clear();
113*35238bceSAndroid Build Coastguard Worker return existingResult;
114*35238bceSAndroid Build Coastguard Worker }
115*35238bceSAndroid Build Coastguard Worker else
116*35238bceSAndroid Build Coastguard Worker return m_batchResult->createTestCaseResult(casePath);
117*35238bceSAndroid Build Coastguard Worker }
118*35238bceSAndroid Build Coastguard Worker
testCaseResultUpdated(const xe::TestCaseResultPtr &)119*35238bceSAndroid Build Coastguard Worker void testCaseResultUpdated(const xe::TestCaseResultPtr &)
120*35238bceSAndroid Build Coastguard Worker {
121*35238bceSAndroid Build Coastguard Worker // Ignored.
122*35238bceSAndroid Build Coastguard Worker }
123*35238bceSAndroid Build Coastguard Worker
testCaseResultComplete(const xe::TestCaseResultPtr &)124*35238bceSAndroid Build Coastguard Worker void testCaseResultComplete(const xe::TestCaseResultPtr &)
125*35238bceSAndroid Build Coastguard Worker {
126*35238bceSAndroid Build Coastguard Worker // Ignored.
127*35238bceSAndroid Build Coastguard Worker }
128*35238bceSAndroid Build Coastguard Worker
129*35238bceSAndroid Build Coastguard Worker private:
130*35238bceSAndroid Build Coastguard Worker xe::BatchResult *const m_batchResult;
131*35238bceSAndroid Build Coastguard Worker const uint32_t m_flags;
132*35238bceSAndroid Build Coastguard Worker };
133*35238bceSAndroid Build Coastguard Worker
readLogFile(xe::BatchResult * dstResult,const char * filename,uint32_t flags)134*35238bceSAndroid Build Coastguard Worker static void readLogFile(xe::BatchResult *dstResult, const char *filename, uint32_t flags)
135*35238bceSAndroid Build Coastguard Worker {
136*35238bceSAndroid Build Coastguard Worker std::ifstream in(filename, std::ifstream::binary | std::ifstream::in);
137*35238bceSAndroid Build Coastguard Worker LogHandler resultHandler(dstResult, flags);
138*35238bceSAndroid Build Coastguard Worker xe::TestLogParser parser(&resultHandler);
139*35238bceSAndroid Build Coastguard Worker uint8_t buf[2048];
140*35238bceSAndroid Build Coastguard Worker int numRead = 0;
141*35238bceSAndroid Build Coastguard Worker
142*35238bceSAndroid Build Coastguard Worker if (!in.good())
143*35238bceSAndroid Build Coastguard Worker throw std::runtime_error(string("Failed to open '") + filename + "'");
144*35238bceSAndroid Build Coastguard Worker
145*35238bceSAndroid Build Coastguard Worker for (;;)
146*35238bceSAndroid Build Coastguard Worker {
147*35238bceSAndroid Build Coastguard Worker in.read((char *)&buf[0], DE_LENGTH_OF_ARRAY(buf));
148*35238bceSAndroid Build Coastguard Worker numRead = (int)in.gcount();
149*35238bceSAndroid Build Coastguard Worker
150*35238bceSAndroid Build Coastguard Worker if (numRead <= 0)
151*35238bceSAndroid Build Coastguard Worker break;
152*35238bceSAndroid Build Coastguard Worker
153*35238bceSAndroid Build Coastguard Worker parser.parse(&buf[0], numRead);
154*35238bceSAndroid Build Coastguard Worker }
155*35238bceSAndroid Build Coastguard Worker
156*35238bceSAndroid Build Coastguard Worker in.close();
157*35238bceSAndroid Build Coastguard Worker }
158*35238bceSAndroid Build Coastguard Worker
mergeTestLogs(const CommandLine & cmdLine)159*35238bceSAndroid Build Coastguard Worker static void mergeTestLogs(const CommandLine &cmdLine)
160*35238bceSAndroid Build Coastguard Worker {
161*35238bceSAndroid Build Coastguard Worker xe::BatchResult batchResult;
162*35238bceSAndroid Build Coastguard Worker
163*35238bceSAndroid Build Coastguard Worker for (vector<string>::const_iterator filename = cmdLine.srcFilenames.begin(); filename != cmdLine.srcFilenames.end();
164*35238bceSAndroid Build Coastguard Worker ++filename)
165*35238bceSAndroid Build Coastguard Worker readLogFile(&batchResult, filename->c_str(), cmdLine.flags);
166*35238bceSAndroid Build Coastguard Worker
167*35238bceSAndroid Build Coastguard Worker if (!cmdLine.dstFilename.empty())
168*35238bceSAndroid Build Coastguard Worker xe::writeBatchResultToFile(batchResult, cmdLine.dstFilename.c_str());
169*35238bceSAndroid Build Coastguard Worker else
170*35238bceSAndroid Build Coastguard Worker xe::writeTestLog(batchResult, std::cout);
171*35238bceSAndroid Build Coastguard Worker }
172*35238bceSAndroid Build Coastguard Worker
printHelp(const char * binName)173*35238bceSAndroid Build Coastguard Worker static void printHelp(const char *binName)
174*35238bceSAndroid Build Coastguard Worker {
175*35238bceSAndroid Build Coastguard Worker printf("%s: [filename] [[filename 2] ...]\n", binName);
176*35238bceSAndroid Build Coastguard Worker printf(" --dst=[filename] Write final log to file, otherwise written to stdout.\n");
177*35238bceSAndroid Build Coastguard Worker printf(" --info=[first|last] Select which session info to use (default: first).\n");
178*35238bceSAndroid Build Coastguard Worker }
179*35238bceSAndroid Build Coastguard Worker
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)180*35238bceSAndroid Build Coastguard Worker static bool parseCommandLine(CommandLine &cmdLine, int argc, const char *const *argv)
181*35238bceSAndroid Build Coastguard Worker {
182*35238bceSAndroid Build Coastguard Worker for (int argNdx = 1; argNdx < argc; argNdx++)
183*35238bceSAndroid Build Coastguard Worker {
184*35238bceSAndroid Build Coastguard Worker const char *arg = argv[argNdx];
185*35238bceSAndroid Build Coastguard Worker
186*35238bceSAndroid Build Coastguard Worker if (!deStringBeginsWith(arg, "--"))
187*35238bceSAndroid Build Coastguard Worker cmdLine.srcFilenames.push_back(arg);
188*35238bceSAndroid Build Coastguard Worker else if (deStringBeginsWith(arg, "--dst="))
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker if (!cmdLine.dstFilename.empty())
191*35238bceSAndroid Build Coastguard Worker return false;
192*35238bceSAndroid Build Coastguard Worker cmdLine.dstFilename = arg + 6;
193*35238bceSAndroid Build Coastguard Worker }
194*35238bceSAndroid Build Coastguard Worker else if (deStringEqual(arg, "--info=first"))
195*35238bceSAndroid Build Coastguard Worker cmdLine.flags &= ~FLAG_USE_LAST_INFO;
196*35238bceSAndroid Build Coastguard Worker else if (deStringEqual(arg, "--info=last"))
197*35238bceSAndroid Build Coastguard Worker cmdLine.flags |= FLAG_USE_LAST_INFO;
198*35238bceSAndroid Build Coastguard Worker else
199*35238bceSAndroid Build Coastguard Worker return false;
200*35238bceSAndroid Build Coastguard Worker }
201*35238bceSAndroid Build Coastguard Worker
202*35238bceSAndroid Build Coastguard Worker if (cmdLine.srcFilenames.empty())
203*35238bceSAndroid Build Coastguard Worker return false;
204*35238bceSAndroid Build Coastguard Worker
205*35238bceSAndroid Build Coastguard Worker return true;
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker
main(int argc,const char * const * argv)208*35238bceSAndroid Build Coastguard Worker int main(int argc, const char *const *argv)
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker try
211*35238bceSAndroid Build Coastguard Worker {
212*35238bceSAndroid Build Coastguard Worker CommandLine cmdLine;
213*35238bceSAndroid Build Coastguard Worker
214*35238bceSAndroid Build Coastguard Worker if (!parseCommandLine(cmdLine, argc, argv))
215*35238bceSAndroid Build Coastguard Worker {
216*35238bceSAndroid Build Coastguard Worker printHelp(argv[0]);
217*35238bceSAndroid Build Coastguard Worker return -1;
218*35238bceSAndroid Build Coastguard Worker }
219*35238bceSAndroid Build Coastguard Worker
220*35238bceSAndroid Build Coastguard Worker mergeTestLogs(cmdLine);
221*35238bceSAndroid Build Coastguard Worker }
222*35238bceSAndroid Build Coastguard Worker catch (const std::exception &e)
223*35238bceSAndroid Build Coastguard Worker {
224*35238bceSAndroid Build Coastguard Worker printf("FATAL ERROR: %s\n", e.what());
225*35238bceSAndroid Build Coastguard Worker return -1;
226*35238bceSAndroid Build Coastguard Worker }
227*35238bceSAndroid Build Coastguard Worker
228*35238bceSAndroid Build Coastguard Worker return 0;
229*35238bceSAndroid Build Coastguard Worker }
230