blob: affb9de4e7aee3f5f6d2a3d2fa75c72343bc9f3d [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <zircon/compiler.h>
#include <mutex>
#include <zxtest/zxtest.h>
#include "weak.h"
namespace LIBC_NAMESPACE_DECL {
[[gnu::weak]] void NotDefined();
[[gnu::weak]] void NotDefinedWithArgs(int, const char*, double);
namespace {
class LibcTests : public zxtest::Test {
public:
static inline bool gCalled = false;
static inline bool gFakeLock = false;
void SetUp() override { gCalled = gFakeLock = false; }
void TearDown() override { gCalled = gFakeLock = false; }
template <auto Symbol, bool ExpectCall, typename... Args>
static void Call(Args&&... args) {
ASSERT_FALSE(gCalled);
Weak<Symbol>::Call(std::forward<Args>(args)...);
EXPECT_EQ(gCalled, ExpectCall);
gCalled = false;
}
};
void Defined() { LibcTests::gCalled = true; }
void DefinedWithArgs(int i, const char* s, double d) {
LibcTests::gCalled = true;
EXPECT_EQ(i, 1);
EXPECT_STREQ(s, "foo");
EXPECT_EQ(d, 3.14);
}
void FakeLock() {
ASSERT_FALSE(LibcTests::gFakeLock);
LibcTests::gFakeLock = true;
}
void FakeUnlock() {
ASSERT_TRUE(LibcTests::gFakeLock);
LibcTests::gFakeLock = false;
}
constexpr WeakLock<FakeLock, FakeUnlock> kFakeWeakLock;
int gLockedThing __TA_GUARDED(kFakeWeakLock);
TEST_F(LibcTests, WeakUndefined) { Call<NotDefined, false>(); }
TEST_F(LibcTests, WeakUndefinedWithArgs) { Call<NotDefinedWithArgs, false>(1, "foo", 3.14); }
TEST_F(LibcTests, WeakDefined) { Call<Defined, true>(); }
TEST_F(LibcTests, WeakDefinedWithArgs) { Call<DefinedWithArgs, true>(1, "foo", 3.14); }
TEST_F(LibcTests, WeakLock) {
ASSERT_FALSE(LibcTests::gFakeLock);
{
std::lock_guard lock(kFakeWeakLock);
ASSERT_TRUE(LibcTests::gFakeLock);
// Outside the guard's scope, this would be diagnosed by -Wthread-safety.
gLockedThing = 0;
}
ASSERT_FALSE(LibcTests::gFakeLock);
}
// TODO: WeakOr tests
} // namespace
} // namespace LIBC_NAMESPACE_DECL