How to write an automated test for thread safety

后端 未结 6 726
醉话见心
醉话见心 2020-12-31 18:29

I have a class which is not thread safe:

class Foo { 
    /* Abstract base class, code which is not thread safe */ 
};

Moreover, if you hav

6条回答
  •  一个人的身影
    2020-12-31 18:46

    So far I've written the following code. Sometimes it works and sometimes the test fails, since the Sleep is not enough for running all threads.

    //! Give some time to the other threads
    static void YieldThread()
    {
    #ifdef _WIN32
        Sleep(10);
    #endif //_WIN32
    }
    
    class FooWithMutex: public Foo {
    public:
        QMutex m_mutex;
        virtual void someFunc()
        {
            QMutexLocker(&m_mutex);
        }
        virtual void anotherFunc()
        {
            QMutexLocker(&m_mutex);
        }
    };
    
    class ThreadThatCallsFooFunc1: public QThread {
    public:
        ThreadThatCallsFooFunc1( FooWrapper& fooWrapper )
            : m_fooWrapper(fooWrapper) {}
    
        virtual void run()
        {
            m_fooWrapper.someFunc();
        }
    private:
        FooWrapper& m_fooWrapper;
    };
    
    class ThreadThatCallsFooFunc2: public QThread {
    public:
        ThreadThatCallsFooFunc2( FooWrapper& fooWrapper )
            : m_fooWrapper(fooWrapper) {}
    
        virtual void run()
        {
            m_fooWrapper.anotherFunc();
        }
    private:
        FooWrapper& m_fooWrapper;
    };
    
    TEST(ScriptPluginWrapperTest, CallsFromMultipleThreads)
    {
        // FooWithMutex inherits the abstract Foo and adds
        // mutex lock/unlock on each function.
        FooWithMutex fooWithMutex;
    
        FooWrapper fooWrapper( &fooWithMutex );
        ThreadThatCallsFooFunc1 thread1(fooWrapper);
        ThreadThatCallsFooFunc2 thread2(fooWrapper);
    
        fooWithMutex.m_mutex.lock();
        thread1.start(); // Should block
    
        YieldThread();
        ASSERT_FALSE( thread1.isFinished() );
    
        thread2.start(); // Should finish immediately
        YieldThread();
        ASSERT_TRUE( thread2.isFinished() );
    
        fooWithMutex.m_mutex.unlock();
    
        YieldThread();
        EXPECT_TRUE( thread1.isFinished() );
    }
    

提交回复
热议问题