Merge "Further relax line verification in primitive bbox tests" into nougat-cts-dev...
[platform/upstream/VK-GL-CTS.git] / framework / platform / android / tcuTestLogParserJNI.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
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 Android JNI interface for instrumentations log parsing.
22  *//*--------------------------------------------------------------------*/
23
24 #include "tcuDefs.hpp"
25
26 #include "xeTestResultParser.hpp"
27 #include "xeTestCaseResult.hpp"
28 #include "xeContainerFormatParser.hpp"
29 #include "xeTestLogWriter.hpp"
30 #include "xeXMLWriter.hpp"
31
32 #include <jni.h>
33 #include <stdlib.h>
34 #include <android/log.h>
35
36 #include <sstream>
37
38 namespace
39 {
40 static const char*      TESTCASE_STYLESHEET     = "testlog.xsl";
41 static const char*      LOG_TAG                         = "dEQP-TestLog";
42
43 class TestLogListener
44 {
45 public:
46                                                 TestLogListener         (JNIEnv* env, jobject object);
47                                                 ~TestLogListener        (void);
48
49         void                            beginSession            (void);
50         void                            endSession                      (void);
51         void                            sessionInfo                     (const char* name, const char* value);
52
53         void                            beginTestCase           (const char* testCasePath);
54         void                            endTestCase                     (void);
55
56         void                            terminateTestCase       (const char* reason);
57         void                            testCaseResult          (const char* statusCode, const char* details);
58
59         void                            testLogData                     (const char* data);
60
61 private:
62         JNIEnv*                         m_env;
63         jobject                         m_object;
64         jclass                          m_class;
65
66         jmethodID                       m_sessionInfoID;
67         jmethodID                       m_beginSessionID;
68         jmethodID                       m_endSessionID;
69
70         jmethodID                       m_beginTestCaseID;
71         jmethodID                       m_endTestCaseID;
72         jmethodID                       m_terminateTestCaseID;
73         jmethodID                       m_testCaseResultID;
74         jmethodID                       m_testLogData;
75
76                                                 TestLogListener         (const TestLogListener&);
77         TestLogListener&        operator=                       (const TestLogListener&);
78 };
79
80 TestLogListener::TestLogListener (JNIEnv* env, jobject object)
81         : m_env         (env)
82         , m_object      (object)
83 {
84         m_class                                 = m_env->GetObjectClass(m_object);
85         m_sessionInfoID                 = m_env->GetMethodID(m_class, "sessionInfo",            "(Ljava/lang/String;Ljava/lang/String;)V");
86         m_beginSessionID                = m_env->GetMethodID(m_class, "beginSession",           "()V");
87         m_endSessionID                  = m_env->GetMethodID(m_class, "endSession",                     "()V");
88         m_beginTestCaseID               = m_env->GetMethodID(m_class, "beginTestCase",          "(Ljava/lang/String;)V");
89         m_endTestCaseID                 = m_env->GetMethodID(m_class, "endTestCase",            "()V");
90         m_terminateTestCaseID   = m_env->GetMethodID(m_class, "terminateTestCase",      "(Ljava/lang/String;)V");
91         m_testCaseResultID              = m_env->GetMethodID(m_class, "testCaseResult",         "(Ljava/lang/String;Ljava/lang/String;)V");
92         m_testLogData                   = m_env->GetMethodID(m_class, "testLogData",            "(Ljava/lang/String;)V");
93
94         TCU_CHECK_INTERNAL(m_beginSessionID);
95         TCU_CHECK_INTERNAL(m_endSessionID);
96         TCU_CHECK_INTERNAL(m_sessionInfoID);
97         TCU_CHECK_INTERNAL(m_beginTestCaseID);
98         TCU_CHECK_INTERNAL(m_endTestCaseID);
99         TCU_CHECK_INTERNAL(m_terminateTestCaseID);
100         TCU_CHECK_INTERNAL(m_testCaseResultID);
101         TCU_CHECK_INTERNAL(m_testLogData);
102 }
103
104 TestLogListener::~TestLogListener (void)
105 {
106 }
107
108 void TestLogListener::beginSession (void)
109 {
110         m_env->CallVoidMethod(m_object, m_beginSessionID);
111 }
112
113 void TestLogListener::endSession (void)
114 {
115         m_env->CallVoidMethod(m_object, m_endSessionID);
116 }
117
118 void TestLogListener::sessionInfo (const char* name, const char* value)
119 {
120         jstring jName   = m_env->NewStringUTF(name);
121         jstring jValue  = m_env->NewStringUTF(value);
122
123         m_env->CallVoidMethod(m_object, m_sessionInfoID, jName, jValue);
124         m_env->DeleteLocalRef(jName);
125         m_env->DeleteLocalRef(jValue);
126 }
127
128 void TestLogListener::beginTestCase (const char* testCasePath)
129 {
130         jstring jTestCasePath = m_env->NewStringUTF(testCasePath);
131
132         m_env->CallVoidMethod(m_object, m_beginTestCaseID, jTestCasePath);
133         m_env->DeleteLocalRef(jTestCasePath);
134 }
135
136 void TestLogListener::endTestCase (void)
137 {
138         m_env->CallVoidMethod(m_object, m_endTestCaseID);
139 }
140
141 void TestLogListener::terminateTestCase (const char* reason)
142 {
143         jstring  jReason = m_env->NewStringUTF(reason);
144
145         m_env->CallVoidMethod(m_object, m_terminateTestCaseID, jReason);
146         m_env->DeleteLocalRef(jReason);
147 }
148
149 void TestLogListener::testCaseResult (const char* statusCode, const char* details)
150 {
151         jstring  jStatusCode    = m_env->NewStringUTF(statusCode);
152         jstring  jDetails               = m_env->NewStringUTF(details);
153
154         m_env->CallVoidMethod(m_object, m_testCaseResultID, jStatusCode, jDetails);
155         m_env->DeleteLocalRef(jStatusCode);
156         m_env->DeleteLocalRef(jDetails);
157 }
158
159 void TestLogListener::testLogData (const char* data)
160 {
161         jstring logData = m_env->NewStringUTF(data);
162
163         m_env->CallVoidMethod(m_object, m_testLogData, logData);
164         m_env->DeleteLocalRef(logData);
165 }
166
167 class TestLogParser
168 {
169 public:
170                                                                 TestLogParser   (bool logData);
171                                                                 ~TestLogParser  (void);
172
173         void                                            parse                   (TestLogListener& listener, const char* buffer, size_t size);
174
175 private:
176         const bool                                      m_logData;
177
178         bool                                            m_inTestCase;
179         bool                                            m_loggedResult;
180         xe::ContainerFormatParser       m_containerParser;
181         xe::TestCaseResult                      m_testCaseResult;
182         xe::TestResultParser            m_testResultParser;
183
184                                                                 TestLogParser   (const TestLogParser&);
185         TestLogParser&                          operator=               (const TestLogParser&);
186 };
187
188 TestLogParser::TestLogParser (bool logData)
189         : m_logData                     (logData)
190         , m_inTestCase          (DE_FALSE)
191         , m_loggedResult        (DE_FALSE)
192 {
193 }
194
195 TestLogParser::~TestLogParser (void)
196 {
197 }
198
199 void TestLogParser::parse (TestLogListener& listener, const char* buffer, size_t size)
200 {
201         m_containerParser.feed((const deUint8*)buffer, size);
202
203         while (m_containerParser.getElement() != xe::CONTAINERELEMENT_INCOMPLETE)
204         {
205                 switch (m_containerParser.getElement())
206                 {
207                         case xe::CONTAINERELEMENT_END_OF_STRING:
208                                 // Do nothing
209                                 break;
210
211                         case xe::CONTAINERELEMENT_BEGIN_SESSION:
212                                 listener.beginSession();
213                                 break;
214
215                         case xe::CONTAINERELEMENT_END_SESSION:
216                                 listener.endSession();
217                                 break;
218
219                         case xe::CONTAINERELEMENT_SESSION_INFO:
220                                 listener.sessionInfo(m_containerParser.getSessionInfoAttribute(), m_containerParser.getSessionInfoValue());
221                                 break;
222
223                         case xe::CONTAINERELEMENT_BEGIN_TEST_CASE_RESULT:
224                                 listener.beginTestCase(m_containerParser.getTestCasePath());
225
226                                 m_inTestCase            = DE_TRUE;
227                                 m_loggedResult          = DE_FALSE;
228                                 m_testCaseResult        = xe::TestCaseResult();
229
230                                 m_testResultParser.init(&m_testCaseResult);
231                                 break;
232
233                         case xe::CONTAINERELEMENT_END_TEST_CASE_RESULT:
234                                 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
235                                 {
236                                         listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
237                                         m_loggedResult = DE_TRUE;
238                                 }
239
240                                 if (m_logData)
241                                 {
242                                         std::ostringstream      testLog;
243                                         xe::xml::Writer         xmlWriter(testLog);
244
245                                         testLog << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
246                                                         << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
247
248                                         xe::writeTestResult(m_testCaseResult, xmlWriter);
249
250                                         listener.testLogData(testLog.str().c_str());
251                                 }
252
253                                 listener.endTestCase();
254
255                                 m_inTestCase = DE_FALSE;
256                                 break;
257
258                         case xe::CONTAINERELEMENT_TERMINATE_TEST_CASE_RESULT:
259                                 if (m_logData)
260                                 {
261                                         std::ostringstream      testLog;
262                                         xe::xml::Writer         xmlWriter(testLog);
263
264                                         testLog << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
265                                                         << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
266
267                                         xe::writeTestResult(m_testCaseResult, xmlWriter);
268
269                                         listener.testLogData(testLog.str().c_str());
270                                 }
271
272                                 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
273                                 {
274                                         listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
275                                         m_loggedResult = DE_TRUE;
276                                 }
277
278                                 listener.terminateTestCase(m_containerParser.getTerminateReason());
279                                 m_inTestCase = DE_FALSE;
280                                 break;
281
282                         case xe::CONTAINERELEMENT_TEST_LOG_DATA:
283                         {
284                                 if (m_inTestCase)
285                                 {
286                                         std::vector<deUint8> data(m_containerParser.getDataSize());
287                                         m_containerParser.getData(&(data[0]), (int)data.size(), 0);
288
289                                         //tcu::print("%d %s :%s %s", __LINE__, std::string((const char*)&data[0], data.size()).c_str(), __func__, __FILE__);
290
291                                         if (m_testResultParser.parse(&(data[0]), (int)data.size()) == xe::TestResultParser::PARSERESULT_CHANGED)
292                                         {
293                                                 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
294                                                 {
295                                                         listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
296                                                         m_loggedResult = DE_TRUE;
297                                                 }
298                                         }
299                                 }
300
301                                 break;
302                         }
303
304                         default:
305                                 DE_ASSERT(DE_FALSE);
306
307                 };
308
309                 m_containerParser.advance();
310         }
311 }
312
313 void throwJNIException (JNIEnv* env, const std::exception& e)
314 {
315         jclass exClass;
316
317         exClass = env->FindClass("java/lang/Exception");
318
319         TCU_CHECK_INTERNAL(exClass != DE_NULL);
320
321         TCU_CHECK_INTERNAL(env->ThrowNew(exClass, e.what()) == 0);
322 }
323
324 } // anonymous
325
326 DE_BEGIN_EXTERN_C
327
328 JNIEXPORT jlong JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeCreate (JNIEnv* env, jclass, jboolean logData)
329 {
330         DE_UNREF(env);
331
332         try
333         {
334                 return (jlong)new TestLogParser(logData);
335         }
336         catch (const std::exception& e)
337         {
338                 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
339
340                 throwJNIException(env, e);
341                 return 0;
342         }
343 }
344
345 JNIEXPORT void JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeDestroy (JNIEnv* env, jclass, jlong nativePointer)
346 {
347         DE_UNREF(env);
348
349         try
350         {
351                 delete ((TestLogParser*)nativePointer);
352         }
353         catch (const std::exception& e)
354         {
355                 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
356
357                 throwJNIException(env, e);
358         }
359 }
360
361 JNIEXPORT void JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeParse (JNIEnv* env, jclass, jlong nativePointer, jobject instrumentation, jbyteArray buffer, jint size)
362 {
363         jbyte* logData = DE_NULL;
364
365         try
366         {
367                 TestLogParser*  parser          = (TestLogParser*)nativePointer;
368                 TestLogListener listener        (env, instrumentation);
369
370                 logData = env->GetByteArrayElements(buffer, NULL);
371
372                 parser->parse(listener, (const char*)logData, (size_t)size);
373                 env->ReleaseByteArrayElements(buffer, logData, JNI_ABORT);
374                 logData = DE_NULL;
375         }
376         catch (const std::exception& e)
377         {
378                 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
379
380                 if (logData)
381                         env->ReleaseByteArrayElements(buffer, logData, JNI_ABORT);
382
383                 throwJNIException(env, e);
384         }
385 }
386
387 DE_END_EXTERN_C