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