c++ - 클릭 - 파이썬 selenium 크롤링




스레드 안전성을위한 자동화 된 테스트를 작성하는 방법 (4)

스레드 안전하지 않은 클래스가 있습니다.

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

게다가 foo1과 foo2 객체를 가지고 있다면, foo2-> anotherFunc ()가 반환 될 때까지 foo1-> someFunc ()를 호출 할 수 없다. 이것은 상황이며 변경 될 수 없습니다 (Foo 하위 클래스는 실제로 파이썬 스크립트의 래퍼입니다).

불필요한 호출을 방지하기 위해 다음을 작성했습니다.

class FooWrapper {
public:
    FooWrapper(Foo* foo, FooWrappersMutex* mutex);
    /* Wrapped functions from Foo */
};

내부적으로 FooWrapper는 Foo 함수에 대한 호출을 공유 뮤텍스로 래핑합니다.

스레드 안전을 위해 FooWrapper를 테스트하고 싶습니다. 가장 큰 문제는 스레드가 운영 체제에 의해 관리된다는 사실입니다. 즉 실행에 대한 제어 권한이 적다는 것을 의미합니다. 제가 테스트하고 싶은 것은 다음 시나리오입니다 :

  • 스레드 1은 fooWrapper1-> someFunc ()를 호출하고 함수 내부에서 블록합니다.
  • 스레드 2는 fooWrapper2-> anotherFunc ()를 호출하고 즉시 반환합니다 (someFunc ()이 아직 실행 중이므로)
  • 스레드 1이 실행을 완료합니다.

이런 시나리오를 자동으로 테스트하는 가장 간단한 방법은 무엇입니까?

Win32에서 QT를 사용하고 있지만, 적어도 QT는 크로스 플랫폼 인 솔루션을 선호합니다.


멀티 스레딩을 시작하면 정의에 따라 코드가 비 결정적이되므로 스레드 안전성 테스트는 일반적으로 불가능합니다.

그러나 매우 구체적인 질문에 대해 Foo 내부에 오랜 지연을 삽입하면 각 Foo 메소드가 looonnng 시간이 걸리므로 요청한 것을 수행 할 수 있습니다. 즉, 두 번째 스레드가 호출에 진입하기 전에 리턴하는 첫 번째 스레드의 확률이 본질적으로 0이됩니다.

그러나 당신이 정말로 이루고자하는 것은 무엇입니까? 테스트 할 테스트는 무엇입니까? FooWrappersMutex 클래스가 올바르게 작동하는지 확인하려고하면이 작업이 수행되지 않습니다.


지금까지 다음 코드를 작성했습니다. 때로는 작동하고 때로는 테스트가 실패합니다. 수면으로 모든 스레드를 실행하기에 충분하지 않기 때문입니다.

//! 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() );
}

CHESS : Microsoft Research의 동시 소프트웨어대한 체계적인 테스트 도구 를 확인해보십시오. 다중 스레드 프로그램 (.NET 및 원시 코드 모두)에 대한 테스트 프레임 워크입니다.

내가 올바르게 이해했다면 운영 체제의 스레딩 라이브러리를 자체 스레딩 라이브러리로 바꿔 스레드 전환을 제어 할 수 있습니다. 그런 다음 프로그램을 분석하여 스레드의 실행 스트림이 인터리브 할 수있는 모든 가능한 방식을 파악하고 가능한 모든 인터리브에 대해 테스트를 다시 실행합니다.






testing