
    Vh!                        d Z ddlmZ ddlZddlZddlmZmZ ddlm	Z	m
Z
mZ ddlmZ ddlmZmZmZ dd	lmZ  ed
      Z G d de      Z G d de      Z G d d      Z G d de
e         Z G d d      Z G d de      Z G d de      Zy)z.
Tests for L{twisted._threads._threadworker}.
    )annotationsN)ThreadErrorlocal)CallableGenericTypeVar)SynchronousTestCase   )AlreadyQuit
LockWorkerThreadWorker)
SimpleLockTc                      e Zd ZdZy)FakeQueueEmptyz8
    L{FakeQueue}'s C{get} has exhausted the queue.
    N__name__
__module____qualname____doc__     W/home/dcms/DCMS/lib/python3.12/site-packages/twisted/_threads/test/test_threadworker.pyr   r      s    r   r   c                      e Zd ZdZy)WouldDeadlockzf
    If this were a real lock, you'd be deadlocked because the lock would be
    double-acquired.
    Nr   r   r   r   r   r      s    r   r   c                       e Zd ZdZddZddZy)
FakeThreadz
    A fake L{threading.Thread}.

    @ivar target: A target function to run.

    @ivar started: Has this thread been started?
    @type started: L{bool}
    c                     || _         d| _        y)z7
        Create a L{FakeThread} with a target.
        FN)targetstarted)selfr   s     r   __init__zFakeThread.__init__-   s     r   c                    d| _         y)z)
        Set the "started" flag.
        TN)r    r!   s    r   startzFakeThread.start4   s     r   N)r   Callable[[], object]returnNoner'   r(   )r   r   r   r   r"   r%   r   r   r   r   r   #   s    r   r   c                  (    e Zd ZdZddZddZddZy)		FakeQueuez
    A fake L{Queue} implementing C{put} and C{get}.

    @ivar items: A lit of items placed by C{put} but not yet retrieved by
        C{get}.
    @type items: L{list}
    c                    g | _         y)z(
        Create a L{FakeQueue}.
        N)itemsr$   s    r   r"   zFakeQueue.__init__D   s     !
r   c                :    | j                   j                  |       y)zv
        Put an item into the queue for later retrieval by L{FakeQueue.get}.

        @param item: any object
        N)r-   append)r!   items     r   putzFakeQueue.putJ   s     	

$r   c                d    | j                   s
t               | j                   j                  d      S )zR
        Get an item.

        @return: an item previously put by C{put}.
        r   )r-   r   popr$   s    r   getzFakeQueue.getR   s'     zz ""zz~~a  r   Nr)   )r0   r   r'   r(   )r'   r   )r   r   r   r   r"   r1   r4   r   r   r   r+   r+   ;   s    ! !r   r+   c                  (    e Zd ZdZddZddZddZy)FakeLockzi
    A stand-in for L{threading.Lock}.

    @ivar acquired: Whether this lock is presently acquired.
    c                    d| _         y)z9
        Create a lock in the un-acquired state.
        FNacquiredr$   s    r   r"   zFakeLock.__init__d   s     r   c                >    | j                   r
t               d| _         y)zX
        Acquire the lock.  Raise an exception if the lock is already acquired.
        T)r9   r   r$   s    r   acquirezFakeLock.acquirej   s     ==/!r   c                >    | j                   s
t               d| _         y)zf
        Release the lock.  Raise an exception if the lock is not presently
        acquired.
        FN)r9   r   r$   s    r   releasezFakeLock.releases   s    
 }}-r   Nr)   )r'   bool)r   r   r   r   r"   r;   r=   r   r   r   r6   r6   ]   s    r   r6   c                  (    e Zd ZdZddZddZddZy)ThreadWorkerTestsz$
    Tests for L{ThreadWorker}.
    c                R     g  _         d fd}t        |t                      _        y)z4
        Create a worker with fake threads.
        c                v    t        |       }|j                          j                  j                  |       |S )N)r   )r   r%   fakeThreadsr/   )r   	newThreadr!   s     r   startThreadz,ThreadWorkerTests.setUp.<locals>.startThread   s1    "&1IOO##I.r   N)r   r&   r'   r   )rC   r   r+   worker)r!   rE   s   ` r   setUpzThreadWorkerTests.setUp   s$     .0	 #;	<r   c                   | j                  t        | j                        d       | j                  | j                  d   j                  d       ddfd}| j                  j                  |       | j                  d       | j                  t        | j                  d   j                         | j                  d       y)z
        L{ThreadWorker} calls its C{createThread} callable to create a thread,
        its C{createQueue} callable to create a queue, and then the thread's
        target pulls work from that queue.
           r   TFc                 
    d y NTr   )dones   r   doItz@ThreadWorkerTests.test_startsThreadAndPerformsWork.<locals>.doIt   s    Dr   Nr)   )	assertEquallenrC   r    rF   doassertRaisesr   r   )r!   rM   rL   s     @r    test_startsThreadAndPerformsWorkz2ThreadWorkerTests.test_startsThreadAndPerformsWork   s     	T--.2))!,44d;	 	tu%.$*:*:1*=*D*DEt$r   c                    | j                   j                          | j                  t        | j                   j                         | j                  t        | j                   j                  t
               y)z
        L{ThreadWorker.quit} causes future calls to L{ThreadWorker.do} and
        L{ThreadWorker.quit} to raise L{AlreadyQuit}.
        N)rF   quitrQ   r   rP   listr$   s    r   test_quitPreventsFutureCallsz.ThreadWorkerTests.test_quitPreventsFutureCalls   sH    
 	+t{{'7'78+t{{~~t<r   Nr)   )r   r   r   r   rG   rR   rV   r   r   r   r@   r@   }   s    =%(=r   r@   c                  H    e Zd ZdZd
dZd
dZd
dZd
dZd
dZd
dZ	d
dZ
y	)LockWorkerTestsz"
    Tests for L{LockWorker}.
    c                x    t               }|j                          | j                  t        |j                         y)ze
        The L{FakeLock} test fixture will alert us if there's a potential
        deadlock.
        N)r6   r;   rQ   r   )r!   locks     r   test_fakeDeadlockz!LockWorkerTests.test_fakeDeadlock   s(    
 z-6r   c                    t               }| j                  t        |j                         |j	                          |j                         }| j                  d|       | j                  t        |j                         y)zk
        The L{FakeLock} test fixture will alert us if there's a potential
        double-release.
        N)r6   rQ   r   r=   r;   assertIs)r!   rZ   noResults      r   test_fakeDoubleReleasez&LockWorkerTests.test_fakeDoubleRelease   sU    
 z+t||4<<>dH%+t||4r   c                   t               }t               t        |      }dddfd}|j                  |       | j	                  d       | j	                  d       | j	                  j
                  d       y)zp
        L{LockWorker.do} immediately performs the work it's given, while the
        lock is acquired.
        Fc                 "    dj                    y rK   r8   )r9   rL   rZ   s   r   workz@LockWorkerTests.test_doExecutesImmediatelyWithLock.<locals>.work   s    D}}Hr   TNr)   )r   r6   r   rP   rN   r9   )r!   storagerF   rb   r9   rL   rZ   s       @@@r   "test_doExecutesImmediatelyWithLockz2LockWorkerTests.test_doExecutesImmediatelyWithLock   so    
 'zD'*	%
 			$t$4(.r   c                    t               t        t                     g g ddfdj                         | j	                  ddg       | j	                  ddg       y)z
        If L{LockWorker.do} is called recursively, it postpones the inner call
        until the outer one is complete.
        r   c                     dz  j                          j                  j                         t              dk  rj                         dz  y )NrI   r
   )r/   r9   rO   rP   )r9   levellevelsrZ   rb   rF   s   r   rb   z6LockWorkerTests.test_doUnwindsReentrancy.<locals>.work   sG    QJEMM% OODMM*6{Q		$QJEr   rI   TNr)   )r6   r   r   rP   rN   )r!   r9   rg   rh   rZ   rb   rF   s    @@@@@@r   test_doUnwindsReentrancyz(LockWorkerTests.test_doUnwindsReentrancy   sh    
 zD%'*	 	 			$!Q(D$<0r   c                   t               }t        j                  |      }t        |t	                     }~| j                   |       d       |j                          t        j                          | j                   |       d       | j                  t        |j                         | j                  t        |j                  t               y)z
        L{LockWorker.quit} frees the resources associated with its lock and
        causes further calls to C{do} and C{quit} to fail.
        N)r6   weakrefrefr   r   assertIsNotrT   gccollectr]   rQ   r   rP   rU   )r!   rZ   rl   rF   s       r   	test_quitzLockWorkerTests.test_quit   s    
 zkk$D%'*%


ceT"+v{{3+vyy$7r   c                    t               t        j                        }t        t	                     dddd fd}dfdj                  |        j                  d        j                  d        j                  j                  d       t        j                           j                   |       d       y)z
        If L{LockWorker.quit} is invoked during a call to L{LockWorker.do}, all
        recursive work scheduled with L{LockWorker.do} will be completed and
        the lock will be released.
        FNc                     j                         j                          j                  t        j                   t               d y rK   )rP   rT   rQ   r   rU   )phase1completephase2r!   rF   s   r   phase1z5LockWorkerTests.test_quitWhileWorking.<locals>.phase1  s3    IIfKKMk699d;!Nr   c                 "    d j                   y rK   r8   )rZ   phase2acquiredphase2completes   r   rt   z5LockWorkerTests.test_quitWhileWorking.<locals>.phase2  s    !N!]]Nr   Tr)   )r6   rk   rl   r   r   rP   rN   r9   rn   ro   r]   )	r!   rl   ru   rZ   rs   rt   rw   rx   rF   s	   `  @@@@@@r   test_quitWhileWorkingz%LockWorkerTests.test_quitWhileWorking  s     zkk$D%'*	" 	"	+
 			&...


ceT"r   c                     G d dt               } |t               t                     }| j                  t        |j
                  t               y)z
        If L{LockWorker.do} is called concurrently with L{LockWorker.quit}, and
        C{quit} wins the race before C{do} gets the lock attribute, then
        L{AlreadyQuit} will be raised.
        c                  D    e Zd Zedd       Zej
                  dd       Zy)ALockWorkerTests.test_quitWhileGettingLock.<locals>.RacyLockWorkerc                D    | j                          | j                  d   }|S N_lock)rT   __dict__)r!   its     r   r   zGLockWorkerTests.test_quitWhileGettingLock.<locals>.RacyLockWorker._lock/  s    		!%w!7	r   c                "    || j                   d<   y r~   )r   )r!   values     r   r   zGLockWorkerTests.test_quitWhileGettingLock.<locals>.RacyLockWorker._lock5  s    ).g&r   N)r'   SimpleLock | None)r   r   r'   r(   )r   r   r   propertyr   setterr   r   r   RacyLockWorkerr|   .  s,     
 \\/ /r   r   N)r   r6   r   rQ   r   rP   rU   )r!   r   rF   s      r   test_quitWhileGettingLockz)LockWorkerTests.test_quitWhileGettingLock'  s6    		/Z 		/  
EG4+vyy$7r   Nr)   )r   r   r   r   r[   r_   rd   ri   rp   ry   r   r   r   r   rX   rX      s+    7
5/*108  #D8r   rX   )r   
__future__r   rn   rk   	threadingr   r   typingr   r   r   twisted.trial.unittestr	    r   r   r   _threadworkerr   r   	Exceptionr   r   r   r+   r6   r@   rX   r   r   r   <module>r      s    # 	  ( - - 6 4 4 &CLY I  0!
 !D @.=+ .=bL8) L8r   