Package pike :: Package test :: Module lock
[hide private]
[frames] | no frames]

Source Code for Module pike.test.lock

  1  # 
  2  # Copyright (c) 2013, EMC Corporation 
  3  # All rights reserved. 
  4  # 
  5  # Redistribution and use in source and binary forms, with or without 
  6  # modification, are permitted provided that the following conditions are met: 
  7  # 
  8  # 1. Redistributions of source code must retain the above copyright notice, 
  9  # this list of conditions and the following disclaimer. 
 10  # 2. Redistributions in binary form must reproduce the above copyright notice, 
 11  # this list of conditions and the following disclaimer in the documentation 
 12  # and/or other materials provided with the distribution. 
 13  # 
 14  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 15  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 16  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 17  # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
 18  # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 19  # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 20  # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 21  # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 22  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 23  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 24  # POSSIBILITY OF SUCH DAMAGE. 
 25  # 
 26  # Module Name: 
 27  # 
 28  #        lock.py 
 29  # 
 30  # Abstract: 
 31  # 
 32  #        Lock tests 
 33  # 
 34  # Authors: Arlene Berry (arlene.berry@emc.com) 
 35  # 
 36   
 37  import pike.model 
 38  import pike.smb2 
 39  import pike.test 
 40  import pike.ntstatus 
 41   
42 -class LockTest(pike.test.PikeTest):
43 # Take a basic byte-range lock
44 - def test_lock(self):
45 chan, tree = self.tree_connect() 46 buffer = "0123456789012345678901" 47 locks = [(8, 8, pike.smb2.SMB2_LOCKFLAG_EXCLUSIVE_LOCK | pike.smb2.SMB2_LOCKFLAG_FAIL_IMMEDIATELY)] 48 49 share_all = pike.smb2.FILE_SHARE_READ | pike.smb2.FILE_SHARE_WRITE | pike.smb2.FILE_SHARE_DELETE 50 51 file = chan.create(tree, 52 'lock.txt', 53 access=pike.smb2.FILE_READ_DATA | pike.smb2.FILE_WRITE_DATA | pike.smb2.DELETE, 54 share=share_all, 55 disposition=pike.smb2.FILE_SUPERSEDE, 56 options=pike.smb2.FILE_DELETE_ON_CLOSE).result() 57 58 bytes_written = chan.write(file, 59 0, 60 buffer) 61 self.assertEqual(bytes_written, len(buffer)) 62 63 chan.lock(file, locks).result() 64 65 chan.close(file)
66 67 # Test that pending lock request can be cancelled, yielding STATUS_CANCELLED
68 - def test_cancel(self):
69 chan, tree = self.tree_connect() 70 buffer = "0123456789012345678901" 71 locks = [(8, 8, pike.smb2.SMB2_LOCKFLAG_EXCLUSIVE_LOCK)] 72 73 share_all = pike.smb2.FILE_SHARE_READ | pike.smb2.FILE_SHARE_WRITE | pike.smb2.FILE_SHARE_DELETE 74 access = pike.smb2.FILE_READ_DATA | pike.smb2.FILE_WRITE_DATA | pike.smb2.DELETE 75 76 # Create file, lock 77 file1 = chan.create(tree, 78 'lock.txt', 79 access=access, 80 share=share_all, 81 disposition=pike.smb2.FILE_SUPERSEDE).result() 82 83 bytes_written = chan.write(file1, 84 0, 85 buffer) 86 self.assertEqual(bytes_written, len(buffer)) 87 88 chan.lock(file1, locks).result() 89 90 # Open file again (with delete on close) 91 file2 = chan.create(tree, 92 'lock.txt', 93 access=access, 94 share=share_all, 95 disposition=pike.smb2.FILE_OPEN, 96 options=pike.smb2.FILE_DELETE_ON_CLOSE).result() 97 98 # This will block since the lock is already held, so only wait for interim response 99 lock_future = chan.lock(file2, locks) 100 lock_future.wait_interim() 101 102 # Cancel, wait for response, verify error response 103 with self.assert_error(pike.ntstatus.STATUS_CANCELLED): 104 chan.cancel(lock_future).result() 105 106 chan.close(file1) 107 chan.close(file2)
108
109 - def test_deny_write(self):
110 chan, tree = self.tree_connect() 111 buffer = "0123456789012345678901" 112 lock_offset = 8 113 lock_size = 8 114 locks = [(lock_offset, lock_size, pike.smb2.SMB2_LOCKFLAG_EXCLUSIVE_LOCK)] 115 116 share_all = pike.smb2.FILE_SHARE_READ | pike.smb2.FILE_SHARE_WRITE | pike.smb2.FILE_SHARE_DELETE 117 access = pike.smb2.FILE_READ_DATA | pike.smb2.FILE_WRITE_DATA | pike.smb2.DELETE 118 119 # Create file, lock 120 file1 = chan.create(tree, 121 'lock.txt', 122 access=access, 123 share=share_all, 124 disposition=pike.smb2.FILE_SUPERSEDE).result() 125 126 bytes_written = chan.write(file1, 0, buffer) 127 self.assertEqual(bytes_written, len(buffer)) 128 129 chan.lock(file1, locks).result() 130 131 # Open file again (with delete on close) 132 file2 = chan.create(tree, 133 'lock.txt', 134 access=access, 135 share=share_all, 136 disposition=pike.smb2.FILE_OPEN, 137 options=pike.smb2.FILE_DELETE_ON_CLOSE).result() 138 139 cases = ((offset,size) for offset in xrange(0, 16) for size in xrange(0, 16)) 140 141 for (offset,size) in cases: 142 if ranges_intersect(offset, offset+size, lock_offset, lock_offset + lock_size): 143 with self.assert_error(pike.ntstatus.STATUS_FILE_LOCK_CONFLICT): 144 chan.write(file2, offset, 'a' * size) 145 146 chan.close(file1) 147 chan.close(file2)
148
150 chan, tree = self.tree_connect() 151 buffer = "0123456789012345678901" 152 lock_offset = 8 153 lock_size = 8 154 locks = [(lock_offset, lock_size, pike.smb2.SMB2_LOCKFLAG_EXCLUSIVE_LOCK)] 155 156 share_all = pike.smb2.FILE_SHARE_READ | pike.smb2.FILE_SHARE_WRITE | pike.smb2.FILE_SHARE_DELETE 157 access = pike.smb2.FILE_READ_DATA | pike.smb2.FILE_WRITE_DATA | pike.smb2.DELETE 158 159 # Create file, lock 160 file1 = chan.create(tree, 161 'lock.txt', 162 access=access, 163 share=share_all, 164 disposition=pike.smb2.FILE_SUPERSEDE).result() 165 166 bytes_written = chan.write(file1, 0, buffer) 167 self.assertEqual(bytes_written, len(buffer)) 168 169 chan.lock(file1, locks).result() 170 171 # Open file again (with delete on close) 172 file2 = chan.create(tree, 173 'lock.txt', 174 access=access, 175 share=share_all, 176 disposition=pike.smb2.FILE_OPEN, 177 options=pike.smb2.FILE_DELETE_ON_CLOSE).result() 178 179 chan.write(file2, lock_offset + 1, None) 180 181 chan.close(file1) 182 chan.close(file2)
183
184 -def range_contains(a1, a2, b):
185 return b >= a1 and b < a2
186
187 -def ranges_intersect(a1, a2, b1, b2):
188 return a2 > a1 and b2 > b1 and \ 189 (range_contains(a1, a2, b1) or range_contains(a1, a2, b2-1) or \ 190 range_contains(b1, b2, a1) or range_contains(b1, b2, a2-1))
191