rhubarb-lip-sync/rhubarb/tests/LazyTests.cpp

75 lines
1.8 KiB
C++

#include <gmock/gmock.h>
#include "tools/Lazy.h"
using namespace testing;
// Not copyable, no default constructor, movable
struct Foo {
const int value;
Foo(int value) : value(value) {}
Foo() = delete;
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
};
TEST(Lazy, basicUsage) {
bool lambdaCalled = false;
Lazy<Foo> lazy([&lambdaCalled] { lambdaCalled = true; return Foo(42); });
EXPECT_FALSE(lambdaCalled);
EXPECT_FALSE(static_cast<bool>(lazy));
EXPECT_EQ(42, (*lazy).value);
EXPECT_EQ(42, lazy.value().value);
EXPECT_EQ(42, lazy->value);
EXPECT_TRUE(lambdaCalled);
EXPECT_TRUE(static_cast<bool>(lazy));
}
TEST(Lazy, constUsage) {
bool lambdaCalled = false;
const Lazy<Foo> lazy([&lambdaCalled] { lambdaCalled = true; return Foo(42); });
EXPECT_FALSE(lambdaCalled);
EXPECT_FALSE(static_cast<bool>(lazy));
EXPECT_EQ(42, (*lazy).value);
EXPECT_EQ(42, lazy.value().value);
EXPECT_EQ(42, lazy->value);
EXPECT_TRUE(lambdaCalled);
EXPECT_TRUE(static_cast<bool>(lazy));
}
TEST(Lazy, copying) {
Lazy<Foo> a;
int counter = 0;
const auto createValue = [&] { return counter++; };
Lazy<Foo> b(createValue);
a = b;
EXPECT_EQ(0, counter);
EXPECT_FALSE(static_cast<bool>(a));
EXPECT_FALSE(static_cast<bool>(b));
EXPECT_EQ(0, a->value);
EXPECT_EQ(1, counter);
EXPECT_TRUE(static_cast<bool>(a));
EXPECT_TRUE(static_cast<bool>(b));
EXPECT_EQ(0, b->value);
Lazy<Foo> c(createValue);
EXPECT_EQ(1, c->value);
}
using Expensive = Foo;
#define member value;
TEST(Lazy, demo) {
// Constructor takes function
Lazy<Expensive> lazy([] { return Expensive(42); });
// Multiple ways to access value
Expensive& a = *lazy;
Expensive& b = lazy.value();
auto c = lazy->member;
// Check if initialized
if (lazy) { /* ... */ }
}