blob: 3553bec323434372e3859c39c28748604db8effc [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/browser/extension_function_crash_keys.h"
#include "components/crash/core/common/crash_buildflags.h"
#include "components/crash/core/common/crash_key.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
using crash_reporter::GetCrashKeyValue;
// The crash key stub implementation does not store keys so we cannot test the
// value of a key.
#if !BUILDFLAG(USE_CRASH_KEY_STUBS)
class ExtensionFunctionCrashKeysTest : public testing::Test {
public:
void SetUp() override { crash_reporter::InitializeCrashKeysForTesting(); }
void TearDown() override { crash_reporter::ResetCrashKeysForTesting(); }
};
TEST_F(ExtensionFunctionCrashKeysTest, SingleCall) {
extension_function_crash_keys::StartExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id1");
extension_function_crash_keys::EndExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "");
}
TEST_F(ExtensionFunctionCrashKeysTest, MultipleCalls) {
// Simulate an extension with two simultaneous in-flight calls.
extension_function_crash_keys::StartExtensionFunctionCall("id1");
extension_function_crash_keys::StartExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id1");
// Clear the first call. There's still one in-flight.
extension_function_crash_keys::EndExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id1");
// Clear the second call. No requests are in-flight.
extension_function_crash_keys::EndExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "");
}
TEST_F(ExtensionFunctionCrashKeysTest, MultipleExtensions) {
// Create more in-flight calls than we have crash keys available. This is
// common during startup when all extensions are loading.
extension_function_crash_keys::StartExtensionFunctionCall("id1");
extension_function_crash_keys::StartExtensionFunctionCall("id2");
extension_function_crash_keys::StartExtensionFunctionCall("id3");
extension_function_crash_keys::StartExtensionFunctionCall("id4");
// Crash keys are set for the last 3 extensions. They are stored with the
// most recent call first.
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id4");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-2"), "id3");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-3"), "id2");
// Call `id1` again. Now it has 2 in-flight calls and is the most recent.
extension_function_crash_keys::StartExtensionFunctionCall("id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id1");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-2"), "id4");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-3"), "id3");
extension_function_crash_keys::EndExtensionFunctionCall("id1");
// End all calls except `id4`.
extension_function_crash_keys::EndExtensionFunctionCall("id1");
extension_function_crash_keys::EndExtensionFunctionCall("id2");
extension_function_crash_keys::EndExtensionFunctionCall("id3");
// Only one crash key is set and the others are cleared.
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-1"), "id4");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-2"), "");
EXPECT_EQ(GetCrashKeyValue("extension-function-caller-3"), "");
}
#endif // !BUILDFLAG(USE_CRASH_KEY_STUBS)
} // namespace extensions