blob: 74965dd2161114f70b8a6158c62961bbc9769d25 [file]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <algorithm>
#include <set>
#include <sstream>
#include <string>
#include "gtest/gtest.h"
#include "jni/jni_helper.h"
using ::testing::EmptyTestEventListener;
using ::testing::InitGoogleTest;
using ::testing::Test;
using ::testing::TestCase;
using ::testing::TestEventListeners;
using ::testing::TestInfo;
using ::testing::TestPartResult;
using ::testing::UnitTest;
namespace {
static JNIEnv* s_env = 0;
static jobject s_context = 0;
// Record the output of googletest tests
class GTestRecorder : public EmptyTestEventListener {
std::vector<std::string> tests_started;
std::set<std::string> tests_completed;
std::vector<std::string> success_invocations; // Only from SUCCESS macros
std::vector<std::string>
failed_invocations; // From any failed EXPECT or ASSERT
bool overall_success;
private:
// Called before any test activity starts.
void OnTestProgramStart(const UnitTest& /* unit_test */) override {
overall_success = false;
}
// Called after all test activities have ended.
void OnTestProgramEnd(const UnitTest& unit_test) override {
overall_success = unit_test.Passed();
}
// Called before a test starts.
void OnTestStart(const TestInfo& test_info) override {
tests_started.push_back(std::string(test_info.test_case_name()) + "." +
test_info.name());
}
// Called after a failed assertion or a SUCCEED() invocation.
void OnTestPartResult(const TestPartResult& test_part_result) override {
std::stringstream record;
// This assumes we are not running tests in parallel, so the last one
// added to tests_started is the test for which we are getting the
// partial result.
record << tests_started.back() << '\n';
record << test_part_result.file_name() << ":"
<< test_part_result.line_number() << '\n'
<< test_part_result.summary() << '\n';
if (test_part_result.failed()) {
failed_invocations.push_back(record.str());
} else {
success_invocations.push_back(record.str());
}
}
// Called after a test ends.
void OnTestEnd(const TestInfo& test_info) override {
tests_completed.insert(std::string(test_info.test_case_name()) + "." +
test_info.name());
}
public:
std::string GetResult() const {
std::stringstream result;
result << "TESTS " << (overall_success ? "SUCCEEDED" : "FAILED")
<< '\n';
result << "\nTests that ran to completion:\n";
for (auto s : tests_completed) {
result << s << '\n';
}
std::set<std::string> not_completed;
std::set<std::string> tests_started_set(tests_started.begin(),
tests_started.end());
std::set_difference(tests_started_set.begin(), tests_started_set.end(),
tests_completed.begin(), tests_completed.end(),
std::inserter(not_completed, not_completed.end()));
if (not_completed.size() > 0) {
result << "\nTests that started but failed to complete:\n";
for (auto s : not_completed) {
result << s << '\n';
}
}
if (!failed_invocations.empty()) {
result << "\nFailures:\n";
for (auto s : failed_invocations) result << s << '\n';
}
if (!success_invocations.empty()) {
result << "\nExplicitly recorded successes:\n";
for (auto s : success_invocations) result << s << '\n';
}
return result.str();
}
}; // class GTestRecorder
} // namespace
extern "C" bool init_jni_for_tests() {
gamesdk::jni::Init(s_env, s_context);
return true;
}
extern "C" void clear_jni_for_tests() { gamesdk::jni::Destroy(); }
extern "C" int shared_main(int argc, char* argv[], JNIEnv* env, jobject context,
std::string& messages) {
::testing::InitGoogleTest(&argc, argv);
// Set up Java env
s_env = env;
s_context = context;
// Set up result recorder
UnitTest& unit_test = *UnitTest::GetInstance();
TestEventListeners& listeners = unit_test.listeners();
delete listeners.Release(listeners.default_result_printer());
auto recorder = std::make_shared<GTestRecorder>();
listeners.Append(recorder.get());
// Run tests
int result = RUN_ALL_TESTS();
messages = recorder->GetResult();
return result;
}