blob: 784d6452fda8f33bec898bfc014faaec3f4f8753 [file] [log] [blame]
// Copyright 2015 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 "android/crashreport/CrashService.h"
#include "android/crashreport/testing/TestCrashSystem.h"
#include "android/base/testing/TestSystem.h"
#include "android/base/testing/TestTempDir.h"
#include <gtest/gtest.h>
#include <memory>
#include <string>
#include <vector>
#include <inttypes.h>
using namespace android::base;
using namespace android::crashreport;
TEST(CrashService, get_set_dumpfile) {
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
std::string path("/test/foo/bar");
crash->setDumpFile(path);
EXPECT_STREQ(crash->getDumpFile().c_str(), path.c_str());
}
TEST(CrashService, validDumpFile) {
TestSystem testsys("/launchdir", System::kProgramBitness);
TestTempDir* testDir = testsys.getTempRoot();
testDir->makeSubDir("foo");
testDir->makeSubFile("foo/bar.dmp");
testDir->makeSubFile("foo/bar.dmp2");
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
std::string path;
path = "foo/bar.dmp";
crash->setDumpFile(path);
EXPECT_TRUE(crash->validDumpFile());
path = "foo/bar2.dmp";
crash->setDumpFile(path);
EXPECT_FALSE(crash->validDumpFile());
path = "foo/bar.dmp2";
crash->setDumpFile(path);
EXPECT_FALSE(crash->validDumpFile());
}
// Unittest limited to linux as wine seems incompatible, and mac shows
// inconsistent results.
#ifdef __linux__
static std::string getTestCrasher() {
std::string path = System::get()->getLauncherDirectory().c_str();
path += System::kDirSeparator;
path += "emulator";
if (System::get()->getProgramBitness() == 64) {
path += "64";
}
path += "_test_crasher";
#ifdef _WIN32
path += ".exe";
#endif
EXPECT_TRUE(System::get()->pathIsFile(path));
return path;
}
static std::vector<std::string> getTestCrasherCmdLine(std::string pipe) {
const std::vector<std::string> cmdline = {getTestCrasher(), "-pipe", pipe};
return cmdline;
}
// invalidURLUpload hangs on wine, but passes on windows host
TEST(CrashService, invalidURLUpload) {
TestTempDir crashdir("crashdir");
TestCrashSystem crashsystem(crashdir.path(), "non-existent-domain-name-for-crash-reports.com");
crashdir.makeSubFile("bar.dmp");
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
crash->setDumpFile(crashdir.makeSubPath("bar.dmp").c_str());
EXPECT_FALSE(crash->uploadCrash());
}
// Crashing binary doesn't work well in Wine
// Fails intermittently on mac build systems
TEST(CrashService, startAttachWaitCrash) {
TestTempDir crashdir("crashdir");
TestCrashSystem crashsystem(crashdir.path(), "localhost");
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
CrashSystem::CrashPipe crashpipe = CrashSystem::get()->getCrashPipe();
EXPECT_TRUE(crashpipe.isValid());
crash->startCrashServer(crashpipe.mServer);
std::vector<std::string> cmdline = getTestCrasherCmdLine(crashpipe.mClient);
int pid = CrashSystem::spawnService(cmdline);
EXPECT_GT(pid, 0);
int64_t waitduration = crash->waitForDumpFile(pid, 10000);
EXPECT_NE(waitduration, -1);
EXPECT_TRUE(CrashSystem::isDump(crash->getDumpFile()));
crash->processCrash();
std::string details = crash->getReport();
EXPECT_NE(details.find("Crash reason:"), std::string::npos);
EXPECT_NE(details.find("Thread 0"), std::string::npos);
EXPECT_NE(details.find("Loaded modules:"), std::string::npos);
}
TEST(CrashService, startAttachWaitNoCrash) {
TestTempDir crashdir("crashdir");
TestCrashSystem crashsystem(crashdir.path(), "localhost");
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
CrashSystem::CrashPipe crashpipe = CrashSystem::get()->getCrashPipe();
EXPECT_TRUE(crashpipe.isValid());
crash->startCrashServer(crashpipe.mServer);
std::vector<std::string> cmdline = getTestCrasherCmdLine(crashpipe.mClient);
cmdline.push_back(StringView("-nocrash"));
int pid = CrashSystem::spawnService(cmdline);
EXPECT_GT(pid, 0);
int64_t waitduration = crash->waitForDumpFile(pid, 10000);
EXPECT_EQ(waitduration, -1);
}
TEST(CrashService, startWaitNoAttach) {
TestTempDir crashdir("crashdir");
TestCrashSystem crashsystem(crashdir.path(), "localhost");
std::unique_ptr<CrashService> crash(
CrashService::makeCrashService("foo", "bar", nullptr));
CrashSystem::CrashPipe crashpipe = CrashSystem::get()->getCrashPipe();
EXPECT_TRUE(crashpipe.isValid());
crash->startCrashServer(crashpipe.mServer);
std::vector<std::string> cmdline = getTestCrasherCmdLine(crashpipe.mClient);
cmdline.push_back(StringView("-noattach"));
int pid = CrashSystem::spawnService(cmdline);
EXPECT_GT(pid, 0);
int64_t waitduration = crash->waitForDumpFile(pid, 1);
EXPECT_EQ(waitduration, -1);
}
// Test fails regularly on one of the linux build machines
// failure happens when waitForDumpFile times out instead of
// finding a crash
//TEST(CrashService, startAttachWaitTimeout) {
// TestTempDir crashdir("crashdir");
// TestCrashSystem crashsystem(crashdir.path(), "localhost");
// std::unique_ptr<CrashService> crash(
// CrashService::makeCrashService("foo", "bar", nullptr));
// CrashSystem::CrashPipe crashpipe = CrashSystem::get()->getCrashPipe();
// EXPECT_TRUE(crashpipe.isValid());
// crash->startCrashServer(crashpipe.mServer);
// std::vector<std::string> cmdline = getTestCrasherCmdLine(crashpipe.mClient);
// cmdline.push_back(StringView("-delay_ms"));
// cmdline.push_back(StringView("100"));
// int pid = CrashSystem::spawnService(cmdline);
// EXPECT_GT(pid, 0);
// int64_t waitduration = crash->waitForDumpFile(pid, 1);
// EXPECT_EQ(waitduration, -1);
// waitduration = crash->waitForDumpFile(pid, 200);
// EXPECT_NE(waitduration, -1);
//}
#endif // __linux__