xref: /aosp_15_r20/external/deqp/executor/tools/xeTestLogCompare.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 Test log compare utility.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "xeTestLogParser.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "xeTestResultParser.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "deFilePath.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deString.h"
28*35238bceSAndroid Build Coastguard Worker #include "deThread.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deCommandLine.hpp"
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 <set>
38*35238bceSAndroid Build Coastguard Worker #include <map>
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker using std::map;
41*35238bceSAndroid Build Coastguard Worker using std::set;
42*35238bceSAndroid Build Coastguard Worker using std::string;
43*35238bceSAndroid Build Coastguard Worker using std::vector;
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker enum OutputMode
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_ALL = 0,
48*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_DIFF,
49*35238bceSAndroid Build Coastguard Worker 
50*35238bceSAndroid Build Coastguard Worker     OUTPUTMODE_LAST
51*35238bceSAndroid Build Coastguard Worker };
52*35238bceSAndroid Build Coastguard Worker 
53*35238bceSAndroid Build Coastguard Worker enum OutputFormat
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker     OUTPUTFORMAT_TEXT = 0,
56*35238bceSAndroid Build Coastguard Worker     OUTPUTFORMAT_CSV,
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker     OUTPUTFORMAT_LAST
59*35238bceSAndroid Build Coastguard Worker };
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker enum OutputValue
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker     OUTPUTVALUE_STATUS_CODE = 0,
64*35238bceSAndroid Build Coastguard Worker     OUTPUTVALUE_STATUS_DETAILS,
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker     OUTPUTVALUE_LAST
67*35238bceSAndroid Build Coastguard Worker };
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker namespace opt
70*35238bceSAndroid Build Coastguard Worker {
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker DE_DECLARE_COMMAND_LINE_OPT(OutMode, OutputMode);
73*35238bceSAndroid Build Coastguard Worker DE_DECLARE_COMMAND_LINE_OPT(OutFormat, OutputFormat);
74*35238bceSAndroid Build Coastguard Worker DE_DECLARE_COMMAND_LINE_OPT(OutValue, OutputValue);
75*35238bceSAndroid Build Coastguard Worker 
registerOptions(de::cmdline::Parser & parser)76*35238bceSAndroid Build Coastguard Worker static void registerOptions(de::cmdline::Parser &parser)
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker     using de::cmdline::NamedValue;
79*35238bceSAndroid Build Coastguard Worker     using de::cmdline::Option;
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker     static const NamedValue<OutputMode> s_outputModes[]     = {{"all", OUTPUTMODE_ALL}, {"diff", OUTPUTMODE_DIFF}};
82*35238bceSAndroid Build Coastguard Worker     static const NamedValue<OutputFormat> s_outputFormats[] = {{"text", OUTPUTFORMAT_TEXT}, {"csv", OUTPUTFORMAT_CSV}};
83*35238bceSAndroid Build Coastguard Worker     static const NamedValue<OutputValue> s_outputValues[]   = {{"code", OUTPUTVALUE_STATUS_CODE},
84*35238bceSAndroid Build Coastguard Worker                                                                {"details", OUTPUTVALUE_STATUS_DETAILS}};
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker     parser << Option<OutFormat>("f", "format", "Output format", s_outputFormats, "csv")
87*35238bceSAndroid Build Coastguard Worker            << Option<OutMode>("m", "mode", "Output mode", s_outputModes, "all")
88*35238bceSAndroid Build Coastguard Worker            << Option<OutValue>("v", "value", "Value to extract", s_outputValues, "code");
89*35238bceSAndroid Build Coastguard Worker }
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker } // namespace opt
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker struct CommandLine
94*35238bceSAndroid Build Coastguard Worker {
CommandLineCommandLine95*35238bceSAndroid Build Coastguard Worker     CommandLine(void) : outMode(OUTPUTMODE_ALL), outFormat(OUTPUTFORMAT_CSV), outValue(OUTPUTVALUE_STATUS_CODE)
96*35238bceSAndroid Build Coastguard Worker     {
97*35238bceSAndroid Build Coastguard Worker     }
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker     OutputMode outMode;
100*35238bceSAndroid Build Coastguard Worker     OutputFormat outFormat;
101*35238bceSAndroid Build Coastguard Worker     OutputValue outValue;
102*35238bceSAndroid Build Coastguard Worker     vector<string> filenames;
103*35238bceSAndroid Build Coastguard Worker };
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker struct ShortBatchResult
106*35238bceSAndroid Build Coastguard Worker {
107*35238bceSAndroid Build Coastguard Worker     vector<xe::TestCaseResultHeader> resultHeaders;
108*35238bceSAndroid Build Coastguard Worker     map<string, int> resultMap;
109*35238bceSAndroid Build Coastguard Worker };
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker class ShortResultHandler : public xe::TestLogHandler
112*35238bceSAndroid Build Coastguard Worker {
113*35238bceSAndroid Build Coastguard Worker public:
ShortResultHandler(ShortBatchResult & result)114*35238bceSAndroid Build Coastguard Worker     ShortResultHandler(ShortBatchResult &result) : m_result(result)
115*35238bceSAndroid Build Coastguard Worker     {
116*35238bceSAndroid Build Coastguard Worker     }
117*35238bceSAndroid Build Coastguard Worker 
setSessionInfo(const xe::SessionInfo &)118*35238bceSAndroid Build Coastguard Worker     void setSessionInfo(const xe::SessionInfo &)
119*35238bceSAndroid Build Coastguard Worker     {
120*35238bceSAndroid Build Coastguard Worker         // Ignored.
121*35238bceSAndroid Build Coastguard Worker     }
122*35238bceSAndroid Build Coastguard Worker 
startTestCaseResult(const char * casePath)123*35238bceSAndroid Build Coastguard Worker     xe::TestCaseResultPtr startTestCaseResult(const char *casePath)
124*35238bceSAndroid Build Coastguard Worker     {
125*35238bceSAndroid Build Coastguard Worker         return xe::TestCaseResultPtr(new xe::TestCaseResultData(casePath));
126*35238bceSAndroid Build Coastguard Worker     }
127*35238bceSAndroid Build Coastguard Worker 
testCaseResultUpdated(const xe::TestCaseResultPtr &)128*35238bceSAndroid Build Coastguard Worker     void testCaseResultUpdated(const xe::TestCaseResultPtr &)
129*35238bceSAndroid Build Coastguard Worker     {
130*35238bceSAndroid Build Coastguard Worker         // Ignored.
131*35238bceSAndroid Build Coastguard Worker     }
132*35238bceSAndroid Build Coastguard Worker 
testCaseResultComplete(const xe::TestCaseResultPtr & caseData)133*35238bceSAndroid Build Coastguard Worker     void testCaseResultComplete(const xe::TestCaseResultPtr &caseData)
134*35238bceSAndroid Build Coastguard Worker     {
135*35238bceSAndroid Build Coastguard Worker         xe::TestCaseResultHeader header;
136*35238bceSAndroid Build Coastguard Worker         int caseNdx = (int)m_result.resultHeaders.size();
137*35238bceSAndroid Build Coastguard Worker 
138*35238bceSAndroid Build Coastguard Worker         header.casePath      = caseData->getTestCasePath();
139*35238bceSAndroid Build Coastguard Worker         header.caseType      = xe::TESTCASETYPE_SELF_VALIDATE;
140*35238bceSAndroid Build Coastguard Worker         header.statusCode    = caseData->getStatusCode();
141*35238bceSAndroid Build Coastguard Worker         header.statusDetails = caseData->getStatusDetails();
142*35238bceSAndroid Build Coastguard Worker 
143*35238bceSAndroid Build Coastguard Worker         if (header.statusCode == xe::TESTSTATUSCODE_LAST)
144*35238bceSAndroid Build Coastguard Worker         {
145*35238bceSAndroid Build Coastguard Worker             xe::TestCaseResult fullResult;
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker             xe::parseTestCaseResultFromData(&m_testResultParser, &fullResult, *caseData.get());
148*35238bceSAndroid Build Coastguard Worker 
149*35238bceSAndroid Build Coastguard Worker             header = xe::TestCaseResultHeader(fullResult);
150*35238bceSAndroid Build Coastguard Worker         }
151*35238bceSAndroid Build Coastguard Worker 
152*35238bceSAndroid Build Coastguard Worker         // Insert into result list & map.
153*35238bceSAndroid Build Coastguard Worker         m_result.resultHeaders.push_back(header);
154*35238bceSAndroid Build Coastguard Worker         m_result.resultMap[header.casePath] = caseNdx;
155*35238bceSAndroid Build Coastguard Worker     }
156*35238bceSAndroid Build Coastguard Worker 
157*35238bceSAndroid Build Coastguard Worker private:
158*35238bceSAndroid Build Coastguard Worker     ShortBatchResult &m_result;
159*35238bceSAndroid Build Coastguard Worker     xe::TestResultParser m_testResultParser;
160*35238bceSAndroid Build Coastguard Worker };
161*35238bceSAndroid Build Coastguard Worker 
readLogFile(ShortBatchResult & batchResult,const char * filename)162*35238bceSAndroid Build Coastguard Worker static void readLogFile(ShortBatchResult &batchResult, const char *filename)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker     std::ifstream in(filename, std::ifstream::binary | std::ifstream::in);
165*35238bceSAndroid Build Coastguard Worker     ShortResultHandler resultHandler(batchResult);
166*35238bceSAndroid Build Coastguard Worker     xe::TestLogParser parser(&resultHandler);
167*35238bceSAndroid Build Coastguard Worker     uint8_t buf[1024];
168*35238bceSAndroid Build Coastguard Worker     int numRead = 0;
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     for (;;)
171*35238bceSAndroid Build Coastguard Worker     {
172*35238bceSAndroid Build Coastguard Worker         in.read((char *)&buf[0], DE_LENGTH_OF_ARRAY(buf));
173*35238bceSAndroid Build Coastguard Worker         numRead = (int)in.gcount();
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker         if (numRead <= 0)
176*35238bceSAndroid Build Coastguard Worker             break;
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker         parser.parse(&buf[0], numRead);
179*35238bceSAndroid Build Coastguard Worker     }
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     in.close();
182*35238bceSAndroid Build Coastguard Worker }
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker class LogFileReader : public de::Thread
185*35238bceSAndroid Build Coastguard Worker {
186*35238bceSAndroid Build Coastguard Worker public:
LogFileReader(ShortBatchResult & batchResult,const char * filename)187*35238bceSAndroid Build Coastguard Worker     LogFileReader(ShortBatchResult &batchResult, const char *filename)
188*35238bceSAndroid Build Coastguard Worker         : m_batchResult(batchResult)
189*35238bceSAndroid Build Coastguard Worker         , m_filename(filename)
190*35238bceSAndroid Build Coastguard Worker     {
191*35238bceSAndroid Build Coastguard Worker     }
192*35238bceSAndroid Build Coastguard Worker 
run(void)193*35238bceSAndroid Build Coastguard Worker     void run(void)
194*35238bceSAndroid Build Coastguard Worker     {
195*35238bceSAndroid Build Coastguard Worker         readLogFile(m_batchResult, m_filename.c_str());
196*35238bceSAndroid Build Coastguard Worker     }
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker private:
199*35238bceSAndroid Build Coastguard Worker     ShortBatchResult &m_batchResult;
200*35238bceSAndroid Build Coastguard Worker     std::string m_filename;
201*35238bceSAndroid Build Coastguard Worker };
202*35238bceSAndroid Build Coastguard Worker 
computeCaseList(vector<string> & cases,const vector<ShortBatchResult> & batchResults)203*35238bceSAndroid Build Coastguard Worker static void computeCaseList(vector<string> &cases, const vector<ShortBatchResult> &batchResults)
204*35238bceSAndroid Build Coastguard Worker {
205*35238bceSAndroid Build Coastguard Worker     // \todo [2012-07-10 pyry] Do proper case ordering (eg. handle missing cases nicely).
206*35238bceSAndroid Build Coastguard Worker     set<string> addedCases;
207*35238bceSAndroid Build Coastguard Worker 
208*35238bceSAndroid Build Coastguard Worker     for (vector<ShortBatchResult>::const_iterator batchIter = batchResults.begin(); batchIter != batchResults.end();
209*35238bceSAndroid Build Coastguard Worker          batchIter++)
210*35238bceSAndroid Build Coastguard Worker     {
211*35238bceSAndroid Build Coastguard Worker         for (vector<xe::TestCaseResultHeader>::const_iterator caseIter = batchIter->resultHeaders.begin();
212*35238bceSAndroid Build Coastguard Worker              caseIter != batchIter->resultHeaders.end(); caseIter++)
213*35238bceSAndroid Build Coastguard Worker         {
214*35238bceSAndroid Build Coastguard Worker             if (addedCases.find(caseIter->casePath) == addedCases.end())
215*35238bceSAndroid Build Coastguard Worker             {
216*35238bceSAndroid Build Coastguard Worker                 cases.push_back(caseIter->casePath);
217*35238bceSAndroid Build Coastguard Worker                 addedCases.insert(caseIter->casePath);
218*35238bceSAndroid Build Coastguard Worker             }
219*35238bceSAndroid Build Coastguard Worker         }
220*35238bceSAndroid Build Coastguard Worker     }
221*35238bceSAndroid Build Coastguard Worker }
222*35238bceSAndroid Build Coastguard Worker 
getTestResultHeaders(vector<xe::TestCaseResultHeader> & headers,const vector<ShortBatchResult> & batchResults,const char * casePath)223*35238bceSAndroid Build Coastguard Worker static void getTestResultHeaders(vector<xe::TestCaseResultHeader> &headers,
224*35238bceSAndroid Build Coastguard Worker                                  const vector<ShortBatchResult> &batchResults, const char *casePath)
225*35238bceSAndroid Build Coastguard Worker {
226*35238bceSAndroid Build Coastguard Worker     headers.resize(batchResults.size());
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)batchResults.size(); ndx++)
229*35238bceSAndroid Build Coastguard Worker     {
230*35238bceSAndroid Build Coastguard Worker         const ShortBatchResult &batchResult        = batchResults[ndx];
231*35238bceSAndroid Build Coastguard Worker         map<string, int>::const_iterator resultPos = batchResult.resultMap.find(casePath);
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker         if (resultPos != batchResult.resultMap.end())
234*35238bceSAndroid Build Coastguard Worker             headers[ndx] = batchResult.resultHeaders[resultPos->second];
235*35238bceSAndroid Build Coastguard Worker         else
236*35238bceSAndroid Build Coastguard Worker         {
237*35238bceSAndroid Build Coastguard Worker             headers[ndx].casePath   = casePath;
238*35238bceSAndroid Build Coastguard Worker             headers[ndx].caseType   = xe::TESTCASETYPE_SELF_VALIDATE;
239*35238bceSAndroid Build Coastguard Worker             headers[ndx].statusCode = xe::TESTSTATUSCODE_LAST;
240*35238bceSAndroid Build Coastguard Worker         }
241*35238bceSAndroid Build Coastguard Worker     }
242*35238bceSAndroid Build Coastguard Worker }
243*35238bceSAndroid Build Coastguard Worker 
getStatusCodeName(xe::TestStatusCode code)244*35238bceSAndroid Build Coastguard Worker static const char *getStatusCodeName(xe::TestStatusCode code)
245*35238bceSAndroid Build Coastguard Worker {
246*35238bceSAndroid Build Coastguard Worker     if (code == xe::TESTSTATUSCODE_LAST)
247*35238bceSAndroid Build Coastguard Worker         return "Missing";
248*35238bceSAndroid Build Coastguard Worker     else
249*35238bceSAndroid Build Coastguard Worker         return xe::getTestStatusCodeName(code);
250*35238bceSAndroid Build Coastguard Worker }
251*35238bceSAndroid Build Coastguard Worker 
runCompare(const CommandLine & cmdLine,std::ostream & dst)252*35238bceSAndroid Build Coastguard Worker static bool runCompare(const CommandLine &cmdLine, std::ostream &dst)
253*35238bceSAndroid Build Coastguard Worker {
254*35238bceSAndroid Build Coastguard Worker     vector<ShortBatchResult> results;
255*35238bceSAndroid Build Coastguard Worker     vector<string> batchNames;
256*35238bceSAndroid Build Coastguard Worker     bool compareOk = true;
257*35238bceSAndroid Build Coastguard Worker 
258*35238bceSAndroid Build Coastguard Worker     XE_CHECK(!cmdLine.filenames.empty());
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker     try
261*35238bceSAndroid Build Coastguard Worker     {
262*35238bceSAndroid Build Coastguard Worker         // Read in batch results
263*35238bceSAndroid Build Coastguard Worker         results.resize(cmdLine.filenames.size());
264*35238bceSAndroid Build Coastguard Worker         {
265*35238bceSAndroid Build Coastguard Worker             std::vector<de::SharedPtr<LogFileReader>> readers;
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker             for (int ndx = 0; ndx < (int)cmdLine.filenames.size(); ndx++)
268*35238bceSAndroid Build Coastguard Worker             {
269*35238bceSAndroid Build Coastguard Worker                 readers.push_back(
270*35238bceSAndroid Build Coastguard Worker                     de::SharedPtr<LogFileReader>(new LogFileReader(results[ndx], cmdLine.filenames[ndx].c_str())));
271*35238bceSAndroid Build Coastguard Worker                 readers.back()->start();
272*35238bceSAndroid Build Coastguard Worker             }
273*35238bceSAndroid Build Coastguard Worker 
274*35238bceSAndroid Build Coastguard Worker             for (int ndx = 0; ndx < (int)cmdLine.filenames.size(); ndx++)
275*35238bceSAndroid Build Coastguard Worker             {
276*35238bceSAndroid Build Coastguard Worker                 readers[ndx]->join();
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker                 // Use file name as batch name.
279*35238bceSAndroid Build Coastguard Worker                 batchNames.push_back(de::FilePath(cmdLine.filenames[ndx].c_str()).getBaseName());
280*35238bceSAndroid Build Coastguard Worker             }
281*35238bceSAndroid Build Coastguard Worker         }
282*35238bceSAndroid Build Coastguard Worker 
283*35238bceSAndroid Build Coastguard Worker         // Compute unified case list.
284*35238bceSAndroid Build Coastguard Worker         vector<string> caseList;
285*35238bceSAndroid Build Coastguard Worker         computeCaseList(caseList, results);
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker         // Stats.
288*35238bceSAndroid Build Coastguard Worker         int numCases = (int)caseList.size();
289*35238bceSAndroid Build Coastguard Worker         int numEqual = 0;
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker         if (cmdLine.outFormat == OUTPUTFORMAT_CSV)
292*35238bceSAndroid Build Coastguard Worker         {
293*35238bceSAndroid Build Coastguard Worker             dst << "TestCasePath";
294*35238bceSAndroid Build Coastguard Worker             for (vector<string>::const_iterator nameIter = batchNames.begin(); nameIter != batchNames.end(); nameIter++)
295*35238bceSAndroid Build Coastguard Worker                 dst << "," << *nameIter;
296*35238bceSAndroid Build Coastguard Worker             dst << "\n";
297*35238bceSAndroid Build Coastguard Worker         }
298*35238bceSAndroid Build Coastguard Worker 
299*35238bceSAndroid Build Coastguard Worker         // Compare cases.
300*35238bceSAndroid Build Coastguard Worker         for (vector<string>::const_iterator caseIter = caseList.begin(); caseIter != caseList.end(); caseIter++)
301*35238bceSAndroid Build Coastguard Worker         {
302*35238bceSAndroid Build Coastguard Worker             const string &caseName = *caseIter;
303*35238bceSAndroid Build Coastguard Worker             vector<xe::TestCaseResultHeader> headers;
304*35238bceSAndroid Build Coastguard Worker             bool allEqual = true;
305*35238bceSAndroid Build Coastguard Worker 
306*35238bceSAndroid Build Coastguard Worker             getTestResultHeaders(headers, results, caseName.c_str());
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker             for (vector<xe::TestCaseResultHeader>::const_iterator iter = headers.begin() + 1; iter != headers.end();
309*35238bceSAndroid Build Coastguard Worker                  iter++)
310*35238bceSAndroid Build Coastguard Worker             {
311*35238bceSAndroid Build Coastguard Worker                 if (iter->statusCode != headers[0].statusCode)
312*35238bceSAndroid Build Coastguard Worker                 {
313*35238bceSAndroid Build Coastguard Worker                     allEqual = false;
314*35238bceSAndroid Build Coastguard Worker                     break;
315*35238bceSAndroid Build Coastguard Worker                 }
316*35238bceSAndroid Build Coastguard Worker             }
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker             if (allEqual)
319*35238bceSAndroid Build Coastguard Worker                 numEqual += 1;
320*35238bceSAndroid Build Coastguard Worker 
321*35238bceSAndroid Build Coastguard Worker             if (cmdLine.outMode == OUTPUTMODE_ALL || !allEqual)
322*35238bceSAndroid Build Coastguard Worker             {
323*35238bceSAndroid Build Coastguard Worker                 if (cmdLine.outFormat == OUTPUTFORMAT_TEXT)
324*35238bceSAndroid Build Coastguard Worker                 {
325*35238bceSAndroid Build Coastguard Worker                     dst << caseName << "\n";
326*35238bceSAndroid Build Coastguard Worker                     for (int ndx = 0; ndx < (int)headers.size(); ndx++)
327*35238bceSAndroid Build Coastguard Worker                         dst << "  " << batchNames[ndx] << ": " << getStatusCodeName(headers[ndx].statusCode) << " ("
328*35238bceSAndroid Build Coastguard Worker                             << headers[ndx].statusDetails << ")\n";
329*35238bceSAndroid Build Coastguard Worker                     dst << "\n";
330*35238bceSAndroid Build Coastguard Worker                 }
331*35238bceSAndroid Build Coastguard Worker                 else if (cmdLine.outFormat == OUTPUTFORMAT_CSV)
332*35238bceSAndroid Build Coastguard Worker                 {
333*35238bceSAndroid Build Coastguard Worker                     dst << caseName;
334*35238bceSAndroid Build Coastguard Worker                     for (vector<xe::TestCaseResultHeader>::const_iterator iter = headers.begin(); iter != headers.end();
335*35238bceSAndroid Build Coastguard Worker                          iter++)
336*35238bceSAndroid Build Coastguard Worker                         dst << ","
337*35238bceSAndroid Build Coastguard Worker                             << (cmdLine.outValue == OUTPUTVALUE_STATUS_CODE ? getStatusCodeName(iter->statusCode) :
338*35238bceSAndroid Build Coastguard Worker                                                                               iter->statusDetails.c_str());
339*35238bceSAndroid Build Coastguard Worker                     dst << "\n";
340*35238bceSAndroid Build Coastguard Worker                 }
341*35238bceSAndroid Build Coastguard Worker             }
342*35238bceSAndroid Build Coastguard Worker         }
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker         compareOk = numEqual == numCases;
345*35238bceSAndroid Build Coastguard Worker 
346*35238bceSAndroid Build Coastguard Worker         if (cmdLine.outFormat == OUTPUTFORMAT_TEXT)
347*35238bceSAndroid Build Coastguard Worker         {
348*35238bceSAndroid Build Coastguard Worker             dst << "  " << numEqual << " / " << numCases << " test case results match.\n";
349*35238bceSAndroid Build Coastguard Worker             dst << "  Comparison " << (compareOk ? "passed" : "FAILED") << "!\n";
350*35238bceSAndroid Build Coastguard Worker         }
351*35238bceSAndroid Build Coastguard Worker     }
352*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
353*35238bceSAndroid Build Coastguard Worker     {
354*35238bceSAndroid Build Coastguard Worker         printf("%s\n", e.what());
355*35238bceSAndroid Build Coastguard Worker         compareOk = false;
356*35238bceSAndroid Build Coastguard Worker     }
357*35238bceSAndroid Build Coastguard Worker 
358*35238bceSAndroid Build Coastguard Worker     return compareOk;
359*35238bceSAndroid Build Coastguard Worker }
360*35238bceSAndroid Build Coastguard Worker 
parseCommandLine(CommandLine & cmdLine,int argc,const char * const * argv)361*35238bceSAndroid Build Coastguard Worker static bool parseCommandLine(CommandLine &cmdLine, int argc, const char *const *argv)
362*35238bceSAndroid Build Coastguard Worker {
363*35238bceSAndroid Build Coastguard Worker     de::cmdline::Parser parser;
364*35238bceSAndroid Build Coastguard Worker     de::cmdline::CommandLine opts;
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker     XE_CHECK(argc >= 1);
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker     opt::registerOptions(parser);
369*35238bceSAndroid Build Coastguard Worker 
370*35238bceSAndroid Build Coastguard Worker     if (!parser.parse(argc - 1, &argv[1], &opts, std::cerr) || opts.getArgs().empty())
371*35238bceSAndroid Build Coastguard Worker     {
372*35238bceSAndroid Build Coastguard Worker         std::cout << argv[0] << ": [options] [filenames]\n";
373*35238bceSAndroid Build Coastguard Worker         parser.help(std::cout);
374*35238bceSAndroid Build Coastguard Worker         return false;
375*35238bceSAndroid Build Coastguard Worker     }
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker     cmdLine.outFormat = opts.getOption<opt::OutFormat>();
378*35238bceSAndroid Build Coastguard Worker     cmdLine.outMode   = opts.getOption<opt::OutMode>();
379*35238bceSAndroid Build Coastguard Worker     cmdLine.outValue  = opts.getOption<opt::OutValue>();
380*35238bceSAndroid Build Coastguard Worker     cmdLine.filenames = opts.getArgs();
381*35238bceSAndroid Build Coastguard Worker 
382*35238bceSAndroid Build Coastguard Worker     return true;
383*35238bceSAndroid Build Coastguard Worker }
384*35238bceSAndroid Build Coastguard Worker 
main(int argc,const char * const * argv)385*35238bceSAndroid Build Coastguard Worker int main(int argc, const char *const *argv)
386*35238bceSAndroid Build Coastguard Worker {
387*35238bceSAndroid Build Coastguard Worker     CommandLine cmdLine;
388*35238bceSAndroid Build Coastguard Worker 
389*35238bceSAndroid Build Coastguard Worker     if (!parseCommandLine(cmdLine, argc, argv))
390*35238bceSAndroid Build Coastguard Worker         return -1;
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker     try
393*35238bceSAndroid Build Coastguard Worker     {
394*35238bceSAndroid Build Coastguard Worker         bool compareOk = runCompare(cmdLine, std::cout);
395*35238bceSAndroid Build Coastguard Worker         return compareOk ? 0 : -1;
396*35238bceSAndroid Build Coastguard Worker     }
397*35238bceSAndroid Build Coastguard Worker     catch (const std::exception &e)
398*35238bceSAndroid Build Coastguard Worker     {
399*35238bceSAndroid Build Coastguard Worker         printf("FATAL ERROR: %s\n", e.what());
400*35238bceSAndroid Build Coastguard Worker         return -1;
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker }
403