|
| 1 | +#include "singleton.hpp" |
| 2 | + |
| 3 | +#include <gtest/gtest.h> |
| 4 | + |
| 5 | +#include <atomic> |
| 6 | +#include <chrono> |
| 7 | +#include <future> |
| 8 | +#include <string> |
| 9 | +#include <thread> |
| 10 | +#include <vector> |
| 11 | + |
| 12 | +// 测试用的单例类 |
| 13 | +class TestSingleton : public Singleton<TestSingleton> |
| 14 | +{ |
| 15 | + friend class Singleton<TestSingleton>; |
| 16 | + |
| 17 | +private: |
| 18 | + TestSingleton() |
| 19 | + : value(0) |
| 20 | + {} |
| 21 | + |
| 22 | +public: |
| 23 | + void setValue(int val) { value = val; } |
| 24 | + int getValue() const { return value; } |
| 25 | + void increment() { ++value; } |
| 26 | + |
| 27 | +private: |
| 28 | + std::atomic<int> value; |
| 29 | +}; |
| 30 | + |
| 31 | +// 另一个测试用的单例类 |
| 32 | +class AnotherSingleton |
| 33 | +{ |
| 34 | + SINGLETON(AnotherSingleton) |
| 35 | + |
| 36 | +public: |
| 37 | + std::string getName() const { return "AnotherSingleton"; } |
| 38 | + void setData(const std::string &data) { m_data = data; } // 重命名避免冲突 |
| 39 | + std::string getData() const { return m_data; } |
| 40 | + |
| 41 | +private: |
| 42 | + std::string m_data; // 重命名避免警告 |
| 43 | +}; |
| 44 | + |
| 45 | +// 基础功能测试 |
| 46 | +class SingletonTest : public ::testing::Test |
| 47 | +{ |
| 48 | +protected: |
| 49 | + void SetUp() override |
| 50 | + { |
| 51 | + // 每个测试前重置单例状态(如果需要的话) |
| 52 | + } |
| 53 | + |
| 54 | + void TearDown() override |
| 55 | + { |
| 56 | + // 清理工作 |
| 57 | + } |
| 58 | +}; |
| 59 | + |
| 60 | +// 测试单例实例的唯一性 |
| 61 | +TEST_F(SingletonTest, InstanceUniqueness) |
| 62 | +{ |
| 63 | + TestSingleton &instance1 = TestSingleton::instance(); |
| 64 | + TestSingleton &instance2 = TestSingleton::instance(); |
| 65 | + TestSingleton *instance3 = TestSingleton::getInstance(); |
| 66 | + |
| 67 | + // 验证所有获取方式返回的是同一个实例 |
| 68 | + EXPECT_EQ(&instance1, &instance2); |
| 69 | + EXPECT_EQ(&instance1, instance3); |
| 70 | + EXPECT_EQ(&instance2, instance3); |
| 71 | +} |
| 72 | + |
| 73 | +// 测试单例的功能方法 |
| 74 | +TEST_F(SingletonTest, Functionality) |
| 75 | +{ |
| 76 | + TestSingleton &instance = TestSingleton::instance(); |
| 77 | + |
| 78 | + // 测试设置和获取值 |
| 79 | + instance.setValue(42); |
| 80 | + EXPECT_EQ(instance.getValue(), 42); |
| 81 | + |
| 82 | + // 测试修改值 |
| 83 | + instance.increment(); |
| 84 | + EXPECT_EQ(instance.getValue(), 43); |
| 85 | +} |
| 86 | + |
| 87 | +// 测试多个单例类的独立性 |
| 88 | +TEST_F(SingletonTest, MultipleSingletonIndependence) |
| 89 | +{ |
| 90 | + TestSingleton &testInstance = TestSingleton::instance(); |
| 91 | + AnotherSingleton &anotherInstance = AnotherSingleton::instance(); |
| 92 | + |
| 93 | + testInstance.setValue(100); |
| 94 | + anotherInstance.setData("test_data"); |
| 95 | + |
| 96 | + // 验证两个单例实例不冲突 |
| 97 | + EXPECT_EQ(testInstance.getValue(), 100); |
| 98 | + EXPECT_EQ(anotherInstance.getData(), "test_data"); |
| 99 | + EXPECT_NE(reinterpret_cast<void *>(&testInstance), reinterpret_cast<void *>(&anotherInstance)); |
| 100 | +} |
| 101 | + |
| 102 | +// 测试单例的不可拷贝和不可移动特性 |
| 103 | +TEST_F(SingletonTest, NonCopyableNonMovable) |
| 104 | +{ |
| 105 | + // 这些代码应该编译失败,我们通过SFINAE或编译时检查来验证 |
| 106 | + // 在实际测试中,我们可以验证这些特性是否存在 |
| 107 | + |
| 108 | + EXPECT_TRUE(std::is_copy_constructible_v<TestSingleton> == false); |
| 109 | + EXPECT_TRUE(std::is_copy_assignable_v<TestSingleton> == false); |
| 110 | + EXPECT_TRUE(std::is_move_constructible_v<TestSingleton> == false); |
| 111 | + EXPECT_TRUE(std::is_move_assignable_v<TestSingleton> == false); |
| 112 | +} |
| 113 | + |
| 114 | +// 辅助函数用于多线程测试 |
| 115 | +void threadTask(int threadId, std::promise<TestSingleton *> &promise) |
| 116 | +{ |
| 117 | + (void) threadId; // 标记未使用参数,消除警告 |
| 118 | + TestSingleton &instance = TestSingleton::instance(); |
| 119 | + instance.increment(); // 每个线程增加一次 |
| 120 | + promise.set_value(&instance); |
| 121 | +} |
| 122 | + |
| 123 | +// 多线程安全性测试 |
| 124 | +TEST_F(SingletonTest, ThreadSafety) |
| 125 | +{ |
| 126 | + constexpr int numThreads = 10; |
| 127 | + |
| 128 | + // 创建一个新的单例类用于线程测试 |
| 129 | + class ThreadTestSingleton : public Singleton<ThreadTestSingleton> |
| 130 | + { |
| 131 | + friend class Singleton<ThreadTestSingleton>; |
| 132 | + |
| 133 | + private: |
| 134 | + ThreadTestSingleton() |
| 135 | + : counter(0) |
| 136 | + {} |
| 137 | + |
| 138 | + public: |
| 139 | + void increment() { ++counter; } |
| 140 | + int getCounter() const { return counter; } |
| 141 | + |
| 142 | + private: |
| 143 | + std::atomic<int> counter; |
| 144 | + }; |
| 145 | + |
| 146 | + // 启动多个线程同时访问单例 |
| 147 | + std::vector<std::thread> testThreads; |
| 148 | + std::vector<std::future<ThreadTestSingleton *>> testFutures; |
| 149 | + std::vector<std::promise<ThreadTestSingleton *>> testPromises(numThreads); |
| 150 | + |
| 151 | + for (auto &promise : testPromises) { |
| 152 | + testFutures.push_back(promise.get_future()); |
| 153 | + } |
| 154 | + |
| 155 | + for (int i = 0; i < numThreads; ++i) { |
| 156 | + testThreads.emplace_back([i, &testPromises]() { |
| 157 | + ThreadTestSingleton &instance = ThreadTestSingleton::instance(); |
| 158 | + instance.increment(); |
| 159 | + testPromises[i].set_value(&instance); |
| 160 | + }); |
| 161 | + } |
| 162 | + |
| 163 | + // 等待所有线程完成 |
| 164 | + for (auto &thread : testThreads) { |
| 165 | + thread.join(); |
| 166 | + } |
| 167 | + |
| 168 | + // 验证所有线程获取的是同一个实例 |
| 169 | + ThreadTestSingleton *firstInstance = testFutures[0].get(); |
| 170 | + for (size_t i = 1; i < testFutures.size(); ++i) { |
| 171 | + EXPECT_EQ(firstInstance, testFutures[i].get()); |
| 172 | + } |
| 173 | + |
| 174 | + // 验证计数器值正确(每个线程增加了一次) |
| 175 | + EXPECT_EQ(firstInstance->getCounter(), numThreads); |
| 176 | +} |
| 177 | + |
| 178 | +// 测试单例的继承特性 |
| 179 | +class DerivedSingleton : public Singleton<DerivedSingleton> |
| 180 | +{ |
| 181 | + friend class Singleton<DerivedSingleton>; |
| 182 | + |
| 183 | +private: |
| 184 | + DerivedSingleton() |
| 185 | + : specialValue(999) |
| 186 | + {} |
| 187 | + |
| 188 | +public: |
| 189 | + int getSpecialValue() const { return specialValue; } |
| 190 | + virtual std::string getType() { return "DerivedSingleton"; } |
| 191 | + |
| 192 | +private: |
| 193 | + int specialValue; |
| 194 | +}; |
| 195 | + |
| 196 | +TEST_F(SingletonTest, Inheritance) |
| 197 | +{ |
| 198 | + DerivedSingleton &instance = DerivedSingleton::instance(); |
| 199 | + EXPECT_EQ(instance.getSpecialValue(), 999); |
| 200 | + EXPECT_EQ(instance.getType(), "DerivedSingleton"); |
| 201 | +} |
| 202 | + |
| 203 | +// 性能测试(可选) |
| 204 | +TEST_F(SingletonTest, Performance) |
| 205 | +{ |
| 206 | + auto start = std::chrono::high_resolution_clock::now(); // 修正后的代码 |
| 207 | + |
| 208 | + constexpr int iterations = 100000; |
| 209 | + for (int i = 0; i < iterations; ++i) { |
| 210 | + TestSingleton &instance = TestSingleton::instance(); |
| 211 | + (void) instance; // 避免未使用变量警告 |
| 212 | + } |
| 213 | + |
| 214 | + auto end = std::chrono::high_resolution_clock::now(); // 修正后的代码 |
| 215 | + auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start); |
| 216 | + |
| 217 | + // 验证获取实例的时间在合理范围内 |
| 218 | + // 这个阈值可能需要根据具体环境调整 |
| 219 | + EXPECT_LT(duration.count(), 1000000); // 小于1秒 |
| 220 | +} |
| 221 | + |
| 222 | +// 测试单例宏的正确性 |
| 223 | +TEST_F(SingletonTest, MacroUsage) |
| 224 | +{ |
| 225 | + // 验证使用宏的单例类具有正确的特性 |
| 226 | + EXPECT_FALSE(std::is_default_constructible_v<AnotherSingleton>); |
| 227 | + EXPECT_FALSE(std::is_copy_constructible_v<AnotherSingleton>); |
| 228 | + EXPECT_FALSE(std::is_copy_assignable_v<AnotherSingleton>); |
| 229 | + EXPECT_FALSE(std::is_move_constructible_v<AnotherSingleton>); |
| 230 | + EXPECT_FALSE(std::is_move_assignable_v<AnotherSingleton>); |
| 231 | + |
| 232 | + // 验证实例方法存在且工作正常 |
| 233 | + AnotherSingleton &instance = AnotherSingleton::instance(); |
| 234 | + EXPECT_EQ(instance.getName(), "AnotherSingleton"); |
| 235 | +} |
| 236 | + |
| 237 | +// 主函数 |
| 238 | +int main(int argc, char **argv) |
| 239 | +{ |
| 240 | + ::testing::InitGoogleTest(&argc, argv); |
| 241 | + return RUN_ALL_TESTS(); |
| 242 | +} |
0 commit comments