зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1024669 - Part 2: Test cases for thread name annotation in the crash report. r=gsvelto
MozReview-Commit-ID: 3ahk3hpkfuk
This commit is contained in:
Родитель
ece1ce1a7d
Коммит
2929778c37
|
@ -54,6 +54,9 @@ if CONFIG['MOZ_CRASHREPORTER_INJECTOR']:
|
|||
'LoadLibraryRemote.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['ENABLE_TESTS']:
|
||||
DIRS += ['test/gtest']
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
EXPORTS += [
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ThreadAnnotation.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::Monitor;
|
||||
using mozilla::MonitorAutoLock;
|
||||
|
||||
namespace CrashReporter {
|
||||
namespace {
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestInitShutdown)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestNestedInitShutdown)
|
||||
{
|
||||
// No bad things should happen in case we have extra init/shutdown calls.
|
||||
InitThreadAnnotation();
|
||||
InitThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestUnbalancedInit)
|
||||
{
|
||||
// No bad things should happen in case we have unbalanced init/shutdown calls.
|
||||
InitThreadAnnotation();
|
||||
InitThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestUnbalancedShutdown)
|
||||
{
|
||||
// No bad things should happen in case we have unbalanced init/shutdown calls.
|
||||
InitThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_BeforeInit)
|
||||
{
|
||||
// GetFlatThreadAnnotation() should not return anything before init.
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
ASSERT_STREQ(aAnnotation, "");
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_AfterShutdown)
|
||||
{
|
||||
// GetFlatThreadAnnotation() should not return anything after shutdown.
|
||||
InitThreadAnnotation();
|
||||
ShutdownThreadAnnotation();
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
ASSERT_STREQ(aAnnotation, "");
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIThread>
|
||||
CreateTestThread(const char* aName, Monitor& aMonitor, bool& aDone)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> setNameRunnable = NS_NewRunnableFunction([aName, &aMonitor, &aDone] () -> void {
|
||||
NS_SetCurrentThreadName(aName);
|
||||
|
||||
MonitorAutoLock lock(aMonitor);
|
||||
aDone = true;
|
||||
aMonitor.NotifyAll();
|
||||
});
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(thread), setNameRunnable);
|
||||
mozilla::Unused << rv;
|
||||
|
||||
return thread.forget();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_OneThread)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
|
||||
Monitor monitor("TestCrashThreadAnnotation");
|
||||
bool threadNameSet = false;
|
||||
nsCOMPtr<nsIThread> thread = CreateTestThread("Thread1", monitor, threadNameSet);
|
||||
ASSERT_TRUE(!!thread);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
while (!threadNameSet) {
|
||||
monitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
ASSERT_TRUE(!!strstr(aAnnotation, "Thread1"));
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_SetNameTwice)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
|
||||
Monitor monitor("TestCrashThreadAnnotation");
|
||||
bool threadNameSet = false;
|
||||
|
||||
nsCOMPtr<nsIRunnable> setNameRunnable = NS_NewRunnableFunction([&] () -> void {
|
||||
NS_SetCurrentThreadName("Thread1");
|
||||
// Set the name again. We should get the latest name.
|
||||
NS_SetCurrentThreadName("Thread1Again");
|
||||
|
||||
MonitorAutoLock lock(monitor);
|
||||
threadNameSet = true;
|
||||
monitor.NotifyAll();
|
||||
});
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsresult rv = NS_NewThread(getter_AddRefs(thread), setNameRunnable);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
while (!threadNameSet) {
|
||||
monitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
ASSERT_TRUE(!!strstr(aAnnotation, "Thread1Again"));
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_TwoThreads)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
|
||||
Monitor monitor("TestCrashThreadAnnotation");
|
||||
bool thread1NameSet = false;
|
||||
bool thread2NameSet = false;
|
||||
|
||||
nsCOMPtr<nsIThread> thread1 = CreateTestThread("Thread1", monitor, thread1NameSet);
|
||||
ASSERT_TRUE(!!thread1);
|
||||
|
||||
nsCOMPtr<nsIThread> thread2 = CreateTestThread("Thread2", monitor, thread2NameSet);
|
||||
ASSERT_TRUE(!!thread2);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
while (!(thread1NameSet && thread2NameSet)) {
|
||||
monitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
// Assert that Thread1 and Thread2 are both in the annotation data.
|
||||
ASSERT_TRUE(!!strstr(aAnnotation, "Thread1"));
|
||||
ASSERT_TRUE(!!strstr(aAnnotation, "Thread2"));
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_ShutdownOneThread)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
|
||||
Monitor monitor("TestCrashThreadAnnotation");
|
||||
bool thread1NameSet = false;
|
||||
bool thread2NameSet = false;
|
||||
|
||||
nsCOMPtr<nsIThread> thread1 = CreateTestThread("Thread1", monitor, thread1NameSet);
|
||||
ASSERT_TRUE(!!thread1);
|
||||
|
||||
nsCOMPtr<nsIThread> thread2 = CreateTestThread("Thread2", monitor, thread2NameSet);
|
||||
ASSERT_TRUE(!!thread2);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
while (!(thread1NameSet && thread2NameSet)) {
|
||||
monitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = thread1->Shutdown();
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
// Assert that only Thread2 is present in the annotation data.
|
||||
ASSERT_TRUE(!strstr(aAnnotation, "Thread1"));
|
||||
ASSERT_TRUE(!!strstr(aAnnotation, "Thread2"));
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
TEST(TestCrashThreadAnnotation, TestGetFlatThreadAnnotation_ShutdownBothThreads)
|
||||
{
|
||||
InitThreadAnnotation();
|
||||
|
||||
Monitor monitor("TestCrashThreadAnnotation");
|
||||
bool thread1NameSet = false;
|
||||
bool thread2NameSet = false;
|
||||
|
||||
nsCOMPtr<nsIThread> thread1 = CreateTestThread("Thread1", monitor, thread1NameSet);
|
||||
ASSERT_TRUE(!!thread1);
|
||||
|
||||
nsCOMPtr<nsIThread> thread2 = CreateTestThread("Thread2", monitor, thread2NameSet);
|
||||
ASSERT_TRUE(!!thread2);
|
||||
|
||||
{
|
||||
MonitorAutoLock lock(monitor);
|
||||
while (!(thread1NameSet && thread2NameSet)) {
|
||||
monitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = thread1->Shutdown();
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
rv = thread2->Shutdown();
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
std::function<void(const char*)> getThreadAnnotationCB =
|
||||
[&] (const char * aAnnotation) -> void {
|
||||
// No leftover in annnotation data.
|
||||
ASSERT_STREQ(aAnnotation, "");
|
||||
};
|
||||
GetFlatThreadAnnotation(getThreadAnnotationCB);
|
||||
|
||||
ShutdownThreadAnnotation();
|
||||
}
|
||||
|
||||
} // Anonymous namespace.
|
||||
} // namespace CrashReporter
|
|
@ -0,0 +1,17 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'TestCrashThreadAnnotation.cpp',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../'
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul-gtest'
|
|
@ -0,0 +1,15 @@
|
|||
function run_test() {
|
||||
if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) {
|
||||
dump("INFO | test_crash_thread_annotation.js | Can't test crashreporter in a non-libxul build.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do_crash(
|
||||
function() {
|
||||
crashType = CrashTestUtils.CRASH_INVALID_POINTER_DEREF;
|
||||
},
|
||||
function(mdump, extra) {
|
||||
do_check_true("ThreadIdNameMapping" in extra);
|
||||
},
|
||||
true);
|
||||
}
|
|
@ -23,6 +23,9 @@ skip-if = os != 'win'
|
|||
skip-if = os == 'win'
|
||||
|
||||
[test_crash_uncaught_exception.js]
|
||||
|
||||
[test_crash_thread_annotation.js]
|
||||
|
||||
[test_crash_with_memory_report.js]
|
||||
[test_crashreporter.js]
|
||||
[test_crashreporter_crash.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче