
    Vh1>                        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	 ddl
mZ ddlmZ ddlmZ dd	lmZ d
ZdZ ej(                         r ed       ed      dZdZ G d de      Z G d de      Zy)z'
Tests for L{twisted.python.lockfile}.
    )annotationsN)skipIf
skipUnless)NoReturn)lockfile)requireModule)platform)TestCaseF zwin32api.OpenProcess
pywintypesTzZOn windows, lockfile.kill is not implemented in the absence of win32api and/or pywintypes.c                      e Zd ZdZddZ e ej                         d      dd       ZddZ	 e ej                         d      dd       Z
 eee      dd       Z eee      dd	       Zdd
Zy)	UtilTestszM
    Tests for the helper functions used to implement L{FilesystemLock}.
    c                    | j                         }t        j                  d|       | j                  t        t        j                  d|      }| j                  |j                  t        j                         y)z
        L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EEXIST}
        when an attempt is made to create a symlink which already exists.
        fooN)mktempr   symlinkassertRaisesOSErrorassertEqualerrnoEEXISTselfnameexcs      J/home/dcms/DCMS/lib/python3.12/site-packages/twisted/test/test_lockfile.pytest_symlinkEEXISTzUtilTests.test_symlinkEEXIST(   sS    
 {{}%)9)95$GELL1    Bspecial rename EIO handling only necessary and correct on Windows.c                    | j                         }dd}| j                  t        d|       | j                  t        t        j
                  |d      }| j                  |j                  t        j                         y)a<  
        L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EIO} when
        the underlying L{rename} call fails with L{EIO}.

        Renaming a file on Windows may fail if the target of the rename is in
        the process of being deleted (directory deletion appears not to be
        atomic).
        c                6    t        t        j                  d       Nr   r   EIOsrcdsts     r   
fakeRenamez4UtilTests.test_symlinkEIOWindows.<locals>.fakeRenameA   s    %))T**r   renamer   Nr&   strr'   r+   returnr   )	r   patchr   r   IOErrorr   r   r   r$   )r   r   r(   r   s       r   test_symlinkEIOWindowsz UtilTests.test_symlinkEIOWindows2   sZ     {{}	+ 	

8Xz2)9)94GEII.r   c                    | j                         }| j                  t        t        j                  |      }| j                  |j                  t        j                         y)z
        L{lockfile.readlink} raises L{OSError} with C{errno} set to L{ENOENT}
        when an attempt is made to read a symlink which does not exist.
        N)r   r   r   r   readlinkr   r   ENOENTr   s      r   test_readlinkENOENTzUtilTests.test_readlinkENOENTH   sA    
 {{}):):DAELL1r   Gspecial readlink EACCES handling only necessary and correct on Windows.c                    | j                         }dd}| j                  t        d|       | j                  t        t        j
                  |      }| j                  |j                  t        j                         y)a\  
        L{lockfile.readlink} raises L{OSError} with C{errno} set to L{EACCES}
        on Windows when the underlying file open attempt fails with C{EACCES}.

        Opening a file on Windows may fail if the path is inside a directory
        which is in the process of being deleted (directory deletion appears
        not to be atomic).
        c                6    t        t        j                  d       r"   r   r   EACCES)pathmodes     r   fakeOpenz6UtilTests.test_readlinkEACCESWindows.<locals>.fakeOpen`       %,,--r   _openN)r9   r+   r:   r+   r,   r   )	r   r-   r   r   r.   r1   r   r   r8   )r   r   r;   r   s       r   test_readlinkEACCESWindowsz$UtilTests.test_readlinkEACCESWindowsQ   sX     {{}	. 	

8Wh/):):DAELL1r   c                T    t        j                  t        j                         d       y)z}
        L{lockfile.kill} returns without error if passed the PID of a
        process which exists and signal C{0}.
        r   N)r   killosgetpidr   s    r   	test_killzUtilTests.test_killg   s     	biik1%r   c                    | j                  t        t        j                  dd      }| j	                  |j
                  t
        j                         y)z
        L{lockfile.kill} raises L{OSError} with errno of L{ESRCH} if
        passed a PID which does not correspond to any process.
        ir   N)r   r   r   r@   r   r   ESRCH)r   r   s     r   test_killESRCHzUtilTests.test_killESRCHo   s6     	1EEKK0r   c                    | j                  t        dd       t        j                  | j                               }|j	                          | j                  |j	                                y)z
        Verify that when L{lockfile.kill} does end up as None (e.g. on Windows
        without pywin32), it doesn't end up being called and raising a
        L{TypeError}.
        r@   N)r-   r   FilesystemLockr   lockassertFalse)r   fls     r   test_noKillCallzUtilTests.test_noKillCally   sG     	

8VT*$$T[[]3
	#r   Nr,   None)__name__
__module____qualname____doc__r   r   r	   	isWindowsr/   r3   r>   r   skipKillskipKillReasonrD   rG   rM    r   r   r   r   #   s    2 O/	/$2 T2	2$ Hn%& && Hn%1 &1	$r   r   c                     e Zd ZddZddZ e ej                         d      dd       ZddZ	ddZ
ddZddZdd	Z e ej                         d
      dd       Z e ej                         d      dd       Z	 	 	 	 	 	 ddZddZ e ej                         d      dd       ZddZddZddZddZddZy)LockingTestsc                   dfd}| j                  t        d|       | j                         }t        j                  |      }| j	                  t
        |j                        }| j                  |j                         y )Nc                    t        d       r"   )r   )sourcedestr   s     r   fakeSymlinkz3LockingTests._symlinkErrorTest.<locals>.fakeSymlink   s    %&&r   r   )r\   r+   r]   r+   r,   r   )	r-   r   r   rI   r   r   rJ   r   r   )r   r   r^   lockfrJ   r   s    `    r   _symlinkErrorTestzLockingTests._symlinkErrorTest   s_    	' 	

8Y4&&u-3E*r   c                B    | j                  t        j                         y)z
        An exception raised by C{symlink} other than C{EEXIST} is passed up to
        the caller of L{FilesystemLock.lock}.
        N)r`   r   ENOSYSrC   s    r   test_symlinkErrorzLockingTests.test_symlinkError   s    
 	u||,r   z9POSIX-specific error propagation not expected on Windows.c                    | j                  t        j                         | j                  t        j                         y)a   
        An L{OSError} raised by C{symlink} on a POSIX platform with an errno of
        C{EACCES} or C{EIO} is passed to the caller of L{FilesystemLock.lock}.

        On POSIX, unlike on Windows, these are unexpected errors which cannot
        be handled by L{FilesystemLock}.
        N)r`   r   r8   r$   rC   s    r   test_symlinkErrorPOSIXz#LockingTests.test_symlinkErrorPOSIX   s(     	u||,uyy)r   c                    | j                         }t        j                  |      }| j                  |j	                                | j                  |j
                         | j                  |j                         y)z
        If the lock has never been held, it can be acquired and the C{clean}
        and C{locked} attributes are set to C{True}.
        N)r   r   rI   
assertTruerJ   cleanlockedr   r_   rJ   s      r   test_cleanlyAcquirez LockingTests.test_cleanlyAcquire   sQ    
 &&u-		$

#$r   c                   | j                         }t        j                  |      }| j                  |j	                                |j                          | j                  |j                         t        j                  |      }| j                  |j	                                | j                  |j                         | j                  |j                         y)z
        If a lock is released cleanly, it can be re-acquired and the C{clean}
        and C{locked} attributes are set to C{True}.
        N)	r   r   rI   rg   rJ   unlockrK   ri   rh   rj   s      r   test_cleanlyReleasez LockingTests.test_cleanlyRelease   s    
 &&u-		$%&&u-		$

#$r   c                *   | j                         }t        j                  |      }| j                  |j	                                t        j                  |      }| j                  |j	                                | j                  |j                         y)zK
        If a lock is currently locked, it cannot be locked again.
        N)r   r   rI   rg   rJ   rK   ri   )r   r_   	firstLock
secondLocks       r   test_cannotLockLockedz"LockingTests.test_cannotLockLocked   sk     ++E2		(),,U3
*+**+r   c                   ddfd}| j                         }| j                  t        d|       t        j                  t	              |       t        j
                  |      }| j                  |j                                | j                  |j                         | j                  |j                         | j                  t        j                  |      t	        t        j                                      y)z
        If a lock was held by a process which no longer exists, it can be
        acquired, the C{clean} attribute is set to C{False}, and the
        C{locked} attribute is set to C{True}.
        i90  c                    |dk7  rt        t        j                  d       | k(  rt        t        j                  d       y )Nr   r   r   EPERMrF   )pidsignalowners     r   fakeKillz4LockingTests.test_uncleanlyAcquire.<locals>.fakeKill   s8    {ekk400e|ekk400 r   r@   Nrw   intrx   r|   r,   rO   )r   r-   r   r   r+   rI   rg   rJ   rK   rh   ri   r   r1   rA   rB   )r   rz   r_   rJ   ry   s       @r   test_uncleanlyAcquirez"LockingTests.test_uncleanlyAcquire   s     	1 

8VX.UU+&&u-		$$$**513ryy{3CDr   c                   dfd}| j                  t        d|      dd}| j                  t        d|       | j                         t        j                        }t        j                  t        d             | j                  |j                                | j                  |j                         | j                  |j                         y)	z
        If the lock is initially held but then released before it can be
        examined to determine if the process which held it still exists, it is
        acquired and the C{clean} and C{locked} attributes are set to C{True}.
        c                x    t        j                         j                          t        j                  |       S r"   )r   rmlinkrestorer1   )r   r_   readlinkPatchs    r   fakeReadlinkz?LockingTests.test_lockReleasedBeforeCheck.<locals>.fakeReadlink   s,    OOE"!!#$$T**r   r1   c                    |dk7  rt        t        j                  d       | dk(  rt        t        j                  d       y Nr   u  ru   rw   rx   s     r   rz   z;LockingTests.test_lockReleasedBeforeCheck.<locals>.fakeKill   7    {ekk400e|ekk400 r   r@   r   N)r   r+   r,   r+   r{   
r-   r   r   rI   r   r+   rg   rJ   rh   ri   )r   r   rz   rJ   r_   r   s       @@r   test_lockReleasedBeforeCheckz)LockingTests.test_lockReleasedBeforeCheck   s    	+ 

8ZF	1 	

8VX.&&u-UU+		$

#$r   r   c                    dd}| j                  t        d|       | j                         }t        j                  |      }| j	                  |j                                | j	                  |j                         y)a  
        If the lock is released while an attempt is made to acquire
        it, the lock attempt fails and C{FilesystemLock.lock} returns
        C{False}.  This can happen on Windows when L{lockfile.symlink}
        fails with L{IOError} of C{EIO} because another process is in
        the middle of a call to L{os.rmdir} (implemented in terms of
        RemoveDirectory) which is not atomic.
        c                6    t        t        j                  d       r"   r#   r%   s     r   r^   zGLockingTests.test_lockReleasedDuringAcquireSymlink.<locals>.fakeSymlink  s     %))T**r   r   Nr*   )r-   r   r   rI   rK   rJ   ri   )r   r^   r_   rJ   s       r   %test_lockReleasedDuringAcquireSymlinkz2LockingTests.test_lockReleasedDuringAcquireSymlink  sZ    	+
 	

8Y4&&u-%%r   r4   c                6   dd}| j                  t        d|       | j                         }t        j                  |      }t        j                  t        d      |       | j                  |j                                | j                  |j                         y)z
        If the lock is initially held but is released while an attempt
        is made to acquire it, the lock attempt fails and
        L{FilesystemLock.lock} returns C{False}.
        c                6    t        t        j                  d       r"   r7   r   s    r   r   zILockingTests.test_lockReleasedDuringAcquireReadlink.<locals>.fakeReadlink+  s     %,,--r   r1   r   Nr   r+   r,   r   )	r-   r   r   rI   r   r+   rK   rJ   ri   )r   r   r_   rJ   s       r   &test_lockReleasedDuringAcquireReadlinkz3LockingTests.test_lockReleasedDuringAcquireReadlink   sn    	. 	

8Z6&&u-UU+%%r   c                r   dfd}| j                  t        d|       | j                         }t        j                  t	        d      |       t        j
                  |      }| j                  |j                        }| j                  |j                         | j                  |j                         y )Nc                     d       r"   rW   )r   r   exceptionTypes    r   r   z5LockingTests._readlinkErrorTest.<locals>.fakeReadlink<  s    t,,r   r1   r   r   )r-   r   r   r   r+   rI   r   rJ   r   r   rK   ri   )r   r   r   r   r_   rJ   r   s    ``    r   _readlinkErrorTestzLockingTests._readlinkErrorTest9  s    	- 	

8Z6 	UU+&&u-tyy9E*%r   c                    | j                  t        t        j                         | j                  t        t        j                         y)z
        An exception raised by C{readlink} other than C{ENOENT} is passed up to
        the caller of L{FilesystemLock.lock}.
        N)r   r   r   rb   r.   rC   s    r   test_readlinkErrorzLockingTests.test_readlinkErrorK  s,    
 	66r   c                    | j                  t        t        j                         | j                  t        t        j                         y)z
        Any L{IOError} raised by C{readlink} on a POSIX platform passed to the
        caller of L{FilesystemLock.lock}.

        On POSIX, unlike on Windows, these are unexpected errors which cannot
        be handled by L{FilesystemLock}.
        N)r   r.   r   rb   r8   rC   s    r   test_readlinkErrorPOSIXz$LockingTests.test_readlinkErrorPOSIXS  s,     	66r   c                   dfd}| j                  t        d|      dd}| j                  t        d|       | j                         t        j                        }t        j                  t        d             | j                  |j                                | j                  |j                         | j                  |j                         y)	z
        If a second process cleans up the lock after a first one checks the
        lock and finds that no process is holding it, the first process does
        not fail when it tries to clean up the lock.
        c                x    j                          t        j                         t        j                  |       S r"   )r   r   r   )r   r_   rmlinkPatchs    r   
fakeRmlinkz?LockingTests.test_lockCleanedUpConcurrently.<locals>.fakeRmlinki  s*    !OOE"??4((r   r   c                    |dk7  rt        t        j                  d       | dk(  rt        t        j                  d       y r   ru   r   s     r   rz   z=LockingTests.test_lockCleanedUpConcurrently.<locals>.fakeKillr  r   r   r@   r   N)r   r+   r,   rO   r{   r   )r   r   rz   rJ   r_   r   s       @@r   test_lockCleanedUpConcurrentlyz+LockingTests.test_lockCleanedUpConcurrentlyb  s    	) jj8Z@	1 	

8VX.&&u-UU+		$

#$r   c                   dd}| j                  t        d|       dd}| j                  t        d|       | j                         }t        j                  t	        d      |       t        j
                  |      }| j                  t        |j                        }| j                  |j                  t        j                         | j                  |j                         y)	z
        An exception raised by L{rmlink} other than C{ENOENT} is passed up
        to the caller of L{FilesystemLock.lock}.
        c                6    t        t        j                  d       r"   )r   r   rb   r   s    r   r   z1LockingTests.test_rmlinkError.<locals>.fakeRmlink  r<   r   r   c                    |dk7  rt        t        j                  d       | dk(  rt        t        j                  d       y r   ru   r   s     r   rz   z/LockingTests.test_rmlinkError.<locals>.fakeKill  r   r   r@   r   Nr   r{   )r-   r   r   r   r+   rI   r   r   rJ   r   r   rb   rK   ri   )r   r   rz   r_   rJ   r   s         r   test_rmlinkErrorzLockingTests.test_rmlinkError  s    	. 	

8Xz2	1 	

8VX. 	UU+&&u-3ELL1%r   c                   dd}| j                  t        d|       | j                         }t        j                  t	        d      |       t        j
                  |      }| j                  t        |j                        }| j                  |j                  t        j                         | j                  |j                         y)z
        If L{kill} raises an exception other than L{OSError} with errno set to
        C{ESRCH}, the exception is passed up to the caller of
        L{FilesystemLock.lock}.
        c                6    t        t        j                  d       r"   )r   r   rv   r   s     r   rz   z-LockingTests.test_killError.<locals>.fakeKill  s    %++t,,r   r@   r   N)rw   r|   rx   r|   r,   r   )r-   r   r   r   r+   rI   r   r   rJ   r   r   rv   rK   ri   )r   rz   r_   rJ   r   s        r   test_killErrorzLockingTests.test_killError  s    	- 	

8VX. 	UU+&&u-3EKK0%r   c                    | j                         }t        j                  t        t	        j
                         dz         |       t        j                  |      }| j                  t        |j                         y)z
        L{FilesystemLock.unlock} raises L{ValueError} if called for a lock
        which is held by a different process.
           N)
r   r   r   r+   rA   rB   rI   r   
ValueErrorrm   rj   s      r   test_unlockOtherzLockingTests.test_unlockOther  sR    
 RYY[1_-u5&&u-*dkk2r   c                   | j                         }| j                  t        j                  |             t        j                  |      }| j                  |j                                | j                  t        j                  |             |j                          | j                  t        j                  |             y)zp
        L{isLocked} returns C{True} if the named lock is currently locked,
        C{False} otherwise.
        N)r   rK   r   isLockedrI   rg   rJ   rm   rj   s      r   test_isLockedzLockingTests.test_isLocked  s    
 **512&&u-		$))%01**512r   N)r   r|   r,   rO   rN   )r   ztype[OSError] | type[IOError]r   r|   r,   rO   )rP   rQ   rR   r`   rc   r   r	   rT   re   rk   rn   rr   r}   r   r   r   r   r   r   r   r   r   r   r   r   rW   r   r   rY   rY      s	   	+- C	*		*	%% 
,E2%> O&	&, T&	&*&:&CF&	&$7 C	7		7%>&:&,33r   rY   )rS   
__future__r   r   rA   unittestr   r   typing_extensionsr   twisted.pythonr   twisted.python.reflectr   twisted.python.runtimer	   twisted.trial.unittestr
   rU   rV   rT   r   rY   rW   r   r   <module>r      s   
 #  	 ' & # 0 + +8,-5,'/< 	_$ _$DD38 D3r   