1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Android JNI interface for instrumentations log parsing.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuDefs.hpp"
26 #include "xeTestResultParser.hpp"
27 #include "xeTestCaseResult.hpp"
28 #include "xeContainerFormatParser.hpp"
29 #include "xeTestLogWriter.hpp"
30 #include "xeXMLWriter.hpp"
34 #include <android/log.h>
40 static const char* TESTCASE_STYLESHEET = "testlog.xsl";
41 static const char* LOG_TAG = "dEQP-TestLog";
46 TestLogListener (JNIEnv* env, jobject object);
47 ~TestLogListener (void);
49 void beginSession (void);
50 void endSession (void);
51 void sessionInfo (const char* name, const char* value);
53 void beginTestCase (const char* testCasePath);
54 void endTestCase (void);
56 void terminateTestCase (const char* reason);
57 void testCaseResult (const char* statusCode, const char* details);
59 void testLogData (const char* data);
66 jmethodID m_sessionInfoID;
67 jmethodID m_beginSessionID;
68 jmethodID m_endSessionID;
70 jmethodID m_beginTestCaseID;
71 jmethodID m_endTestCaseID;
72 jmethodID m_terminateTestCaseID;
73 jmethodID m_testCaseResultID;
74 jmethodID m_testLogData;
76 TestLogListener (const TestLogListener&);
77 TestLogListener& operator= (const TestLogListener&);
80 TestLogListener::TestLogListener (JNIEnv* env, jobject object)
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");
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);
104 TestLogListener::~TestLogListener (void)
108 void TestLogListener::beginSession (void)
110 m_env->CallVoidMethod(m_object, m_beginSessionID);
113 void TestLogListener::endSession (void)
115 m_env->CallVoidMethod(m_object, m_endSessionID);
118 void TestLogListener::sessionInfo (const char* name, const char* value)
120 jstring jName = m_env->NewStringUTF(name);
121 jstring jValue = m_env->NewStringUTF(value);
123 m_env->CallVoidMethod(m_object, m_sessionInfoID, jName, jValue);
124 m_env->DeleteLocalRef(jName);
125 m_env->DeleteLocalRef(jValue);
128 void TestLogListener::beginTestCase (const char* testCasePath)
130 jstring jTestCasePath = m_env->NewStringUTF(testCasePath);
132 m_env->CallVoidMethod(m_object, m_beginTestCaseID, jTestCasePath);
133 m_env->DeleteLocalRef(jTestCasePath);
136 void TestLogListener::endTestCase (void)
138 m_env->CallVoidMethod(m_object, m_endTestCaseID);
141 void TestLogListener::terminateTestCase (const char* reason)
143 jstring jReason = m_env->NewStringUTF(reason);
145 m_env->CallVoidMethod(m_object, m_terminateTestCaseID, jReason);
146 m_env->DeleteLocalRef(jReason);
149 void TestLogListener::testCaseResult (const char* statusCode, const char* details)
151 jstring jStatusCode = m_env->NewStringUTF(statusCode);
152 jstring jDetails = m_env->NewStringUTF(details);
154 m_env->CallVoidMethod(m_object, m_testCaseResultID, jStatusCode, jDetails);
155 m_env->DeleteLocalRef(jStatusCode);
156 m_env->DeleteLocalRef(jDetails);
159 void TestLogListener::testLogData (const char* data)
161 jstring logData = m_env->NewStringUTF(data);
163 m_env->CallVoidMethod(m_object, m_testLogData, logData);
164 m_env->DeleteLocalRef(logData);
170 TestLogParser (bool logData);
171 ~TestLogParser (void);
173 void parse (TestLogListener& listener, const char* buffer, size_t size);
176 const bool m_logData;
180 xe::ContainerFormatParser m_containerParser;
181 xe::TestCaseResult m_testCaseResult;
182 xe::TestResultParser m_testResultParser;
184 TestLogParser (const TestLogParser&);
185 TestLogParser& operator= (const TestLogParser&);
188 TestLogParser::TestLogParser (bool logData)
189 : m_logData (logData)
190 , m_inTestCase (DE_FALSE)
191 , m_loggedResult (DE_FALSE)
195 TestLogParser::~TestLogParser (void)
199 void TestLogParser::parse (TestLogListener& listener, const char* buffer, size_t size)
201 m_containerParser.feed((const deUint8*)buffer, size);
203 while (m_containerParser.getElement() != xe::CONTAINERELEMENT_INCOMPLETE)
205 switch (m_containerParser.getElement())
207 case xe::CONTAINERELEMENT_END_OF_STRING:
211 case xe::CONTAINERELEMENT_BEGIN_SESSION:
212 listener.beginSession();
215 case xe::CONTAINERELEMENT_END_SESSION:
216 listener.endSession();
219 case xe::CONTAINERELEMENT_SESSION_INFO:
220 listener.sessionInfo(m_containerParser.getSessionInfoAttribute(), m_containerParser.getSessionInfoValue());
223 case xe::CONTAINERELEMENT_BEGIN_TEST_CASE_RESULT:
224 listener.beginTestCase(m_containerParser.getTestCasePath());
226 m_inTestCase = DE_TRUE;
227 m_loggedResult = DE_FALSE;
228 m_testCaseResult = xe::TestCaseResult();
230 m_testResultParser.init(&m_testCaseResult);
233 case xe::CONTAINERELEMENT_END_TEST_CASE_RESULT:
234 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
236 listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
237 m_loggedResult = DE_TRUE;
242 std::ostringstream testLog;
243 xe::xml::Writer xmlWriter(testLog);
245 testLog << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
246 << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
248 xe::writeTestResult(m_testCaseResult, xmlWriter);
250 listener.testLogData(testLog.str().c_str());
253 listener.endTestCase();
255 m_inTestCase = DE_FALSE;
258 case xe::CONTAINERELEMENT_TERMINATE_TEST_CASE_RESULT:
261 std::ostringstream testLog;
262 xe::xml::Writer xmlWriter(testLog);
264 testLog << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
265 << "<?xml-stylesheet href=\"" << TESTCASE_STYLESHEET << "\" type=\"text/xsl\"?>\n";
267 xe::writeTestResult(m_testCaseResult, xmlWriter);
269 listener.testLogData(testLog.str().c_str());
272 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
274 listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
275 m_loggedResult = DE_TRUE;
278 listener.terminateTestCase(m_containerParser.getTerminateReason());
279 m_inTestCase = DE_FALSE;
282 case xe::CONTAINERELEMENT_TEST_LOG_DATA:
286 std::vector<deUint8> data(m_containerParser.getDataSize());
287 m_containerParser.getData(&(data[0]), (int)data.size(), 0);
289 //tcu::print("%d %s :%s %s", __LINE__, std::string((const char*)&data[0], data.size()).c_str(), __func__, __FILE__);
291 if (m_testResultParser.parse(&(data[0]), (int)data.size()) == xe::TestResultParser::PARSERESULT_CHANGED)
293 if (m_testCaseResult.statusCode != xe::TESTSTATUSCODE_LAST && !m_loggedResult)
295 listener.testCaseResult(xe::getTestStatusCodeName(m_testCaseResult.statusCode), m_testCaseResult.statusDetails.c_str());
296 m_loggedResult = DE_TRUE;
309 m_containerParser.advance();
313 void throwJNIException (JNIEnv* env, const std::exception& e)
317 exClass = env->FindClass("java/lang/Exception");
319 TCU_CHECK_INTERNAL(exClass != DE_NULL);
321 TCU_CHECK_INTERNAL(env->ThrowNew(exClass, e.what()) == 0);
328 JNIEXPORT jlong JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeCreate (JNIEnv* env, jclass, jboolean logData)
334 return (jlong)new TestLogParser(logData);
336 catch (const std::exception& e)
338 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
340 throwJNIException(env, e);
345 JNIEXPORT void JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeDestroy (JNIEnv* env, jclass, jlong nativePointer)
351 delete ((TestLogParser*)nativePointer);
353 catch (const std::exception& e)
355 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
357 throwJNIException(env, e);
361 JNIEXPORT void JNICALL Java_com_drawelements_deqp_testercore_TestLogParser_nativeParse (JNIEnv* env, jclass, jlong nativePointer, jobject instrumentation, jbyteArray buffer, jint size)
363 jbyte* logData = DE_NULL;
367 TestLogParser* parser = (TestLogParser*)nativePointer;
368 TestLogListener listener (env, instrumentation);
370 logData = env->GetByteArrayElements(buffer, NULL);
372 parser->parse(listener, (const char*)logData, (size_t)size);
373 env->ReleaseByteArrayElements(buffer, logData, JNI_ABORT);
376 catch (const std::exception& e)
378 __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s", e.what());
381 env->ReleaseByteArrayElements(buffer, logData, JNI_ABORT);
383 throwJNIException(env, e);