Skip to content

Commit

Permalink
Merge pull request #834 from Mchakravartula/issue#828_share_functiona…
Browse files Browse the repository at this point in the history
…l_tests

Issue#828 share functional tests
  • Loading branch information
schakrava committed Aug 27, 2015
2 parents 6d237d8 + 2d503af commit 09945f5
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 45 deletions.
163 changes: 118 additions & 45 deletions src/rockstor/storageadmin/tests/test_shares.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def setUpClass(cls):
cls.patch_add_share = patch('storageadmin.views.share.add_share')
cls.mock_add_share = cls.patch_add_share.start()
cls.mock_add_share.return_value = True

cls.patch_update_quota = patch('storageadmin.views.share.update_quota')
cls.mock_update_quota = cls.patch_update_quota.start()
cls.mock_update_quota.return_value = True
Expand All @@ -55,12 +55,17 @@ def setUpClass(cls):

cls.patch_qgroup_id = patch('storageadmin.views.share.qgroup_id')
cls.mock_qgroup_id = cls.patch_qgroup_id.start()
cls.mock_qgroup_id.return_value = True
cls.mock_qgroup_id.return_value = '0f123f'

# put mocks
cls.patch_share_usage = patch('storageadmin.views.share.share_usage')
cls.mock_share_usage = cls.patch_share_usage.start()
cls.mock_share_usage.return_value = 500
cls.mock_share_usage.return_value = (500, 500)

# delete mocks
cls.patch_remove_share = patch('storageadmin.views.share.remove_share')
cls.mock_remove_share = cls.patch_remove_share.start()
cls.mock_remove_share.return_value = True

@classmethod
def tearDownClass(cls):
Expand All @@ -70,11 +75,22 @@ def test_get(self):
"""
Test GET request
1. Get base URL
2. Get nonexistant share
3. Get w/ sort parameters
2. Get existing share
3. Get nonexistant share
4. Get w/ sort parameters
"""
self.get_base(self.BASE_URL)

# get share poolshare1( alreday existing share in fixture fix1)
response = self.client.get('%s/poolshare1' % self.BASE_URL)
self.assertEqual(response.status_code, status.HTTP_200_OK, msg=response)

# get share that does not exist
e_msg = ''
response = self.client.get('%s/invalid_share' % self.BASE_URL)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND, msg=response)

# Get w/ sort parameters
response1 = self.client.get('%s?sortby=usage&reverse=yes' % self.BASE_URL)
self.assertEqual(response1.status_code, status.HTTP_200_OK, msg=response1.data)

Expand All @@ -89,7 +105,7 @@ def test_name_regex(self):
1. Test a few valid regexes (eg: share1, Myshare, 123, etc..)
2. Test a few invalid regexes (eg: -share1, .share etc..)
3. Empty string for share name
4. max length(255 character) for share name
4. max length(254 characters) for share name
5. max length + 1 for share name
"""
# valid share names
Expand All @@ -107,15 +123,23 @@ def test_name_regex(self):
e_msg = ('Share name must start with a alphanumeric(a-z0-9) character '
'and can be followed by any of the following characters: '
'letter(a-z), digits(0-9), hyphen(-), underscore(_) or a period(.).')
invalid_names = ('Share $', '-share', '.share', '', ' ', 'Sh' +
'a' * 254 + 're',)
invalid_names = ('Share $', '-share', '.share', '', ' ',)
for sname in invalid_names:
data['sname'] = sname
response = self.client.post(self.BASE_URL, data=data)
self.assertEqual(response.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response.data)
self.assertEqual(response.data['detail'], e_msg)

# Share name with more than 255 characters
e_msg = ('Share name length cannot exceed 254 characters')

data['sname']= 'Sh' + 'a' * 251 + 're'
response = self.client.post(self.BASE_URL, data=data)
self.assertEqual(response.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response.data)
self.assertEqual(response.data['detail'], e_msg)

def test_create(self):
"""
Test POST request to create shares
Expand Down Expand Up @@ -219,29 +243,37 @@ def test_resize(self):
"""

# create new share
data = {'sname': 'rootshare', 'pool': 'rockstor_rockstor', 'size': 100}
data = {'sname': 'share1', 'pool': 'rockstor_rockstor', 'size': 1000}
response = self.client.post(self.BASE_URL, data=data)
self.assertEqual(response.status_code, status.HTTP_200_OK, msg=response.data)
self.assertEqual(response.data['name'], 'rootshare')
self.assertEqual(response.data['name'], 'share1')
self.assertEqual(response.data['size'], 1000)

# resize a share
# data2 = {'sname': 'rootshare', 'pool': 'rockstor_rockstor', 'size': 1000}
data2 = {'size': 1000}
response2 = self.client.put('%s/rootshare' % self.BASE_URL, data=data2)
self.assertEqual(response2.status_code, status.HTTP_200_OK, msg=response2.data)
self.assertEqual(response2.data['size'], 1000)
# resize share
data3 = {'size': 2000,}
response3 = self.client.put('%s/share1' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code, status.HTTP_200_OK, msg=response3.data)
self.assertEqual(response3.data['size'], 2000)

# resize a share that doesn't exist
data3 = {'sname': 'invalid', 'size': 1500}
response3 = self.client.put('%s/invalid' % self.BASE_URL, data=data3)
# resize a 'root' share
data3 = {'size': 1500}
response3 = self.client.put('%s/root' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response3.data)
e_msg = ('Operation not permitted on this Share(root) because it is a special system Share')
self.assertEqual(response3.data['detail'], e_msg)

# resize a 'home' share
data3 = {'size': 1500}
response3 = self.client.put('%s/home' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response3.data)
e_msg = ('Share(invalid) does not exist.')
e_msg = ('Operation not permitted on this Share(home) because it is a special system Share')
self.assertEqual(response3.data['detail'], e_msg)

# resize to below current share usage value
# resize to below current share usage value
data3 = {'size': 400}
response3 = self.client.put('%s/rootshare' % self.BASE_URL, data=data3)
response3 = self.client.put('%s/share1' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response3.data)
e_msg = ('Unable to resize because requested new size(400KB) is less '
Expand All @@ -251,12 +283,22 @@ def test_resize(self):
# resize below 100KB
self.mock_share_usage.return_value = 50
data3 = {'size': 99}
response3 = self.client.put('%s/rootshare' % self.BASE_URL, data=data3)
response3 = self.client.put('%s/share1' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response3.data)
e_msg = ('Share size should atleast be 100KB. Given size is 99KB')
self.assertEqual(response3.data['detail'], e_msg)

# resize a share that doesn't exist
data3 = {'sname': 'invalid', 'size': 1500}
response3 = self.client.put('%s/invalid' % self.BASE_URL, data=data3)
self.assertEqual(response3.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response3.data)
e_msg = ('Share(invalid) does not exist')
self.assertEqual(response3.data['detail'], e_msg)



def test_compression(self):
"""
Test PUT request to update share compression_algo
Expand Down Expand Up @@ -331,7 +373,7 @@ def test_compression(self):
@mock.patch('storageadmin.views.share.SambaShare')
@mock.patch('storageadmin.views.share.NFSExport')
@mock.patch('storageadmin.views.share.Snapshot')
def test_delete(self, mock_snapshot, mock_nfs, mock_samba, mock_sftp, mock_remove_share):
def test_delete_set1(self, mock_snapshot, mock_nfs, mock_samba, mock_sftp, mock_remove_share):
"""
Test DELETE request on share
1. Create valid share
Expand All @@ -341,8 +383,7 @@ def test_delete(self, mock_snapshot, mock_nfs, mock_samba, mock_sftp, mock_remov
5. Delete share with snapshots
6. Delete share with SFTP export
7. Delete share with remove_share failure (share still mounted)
8. Delete share
9. Delete nonexistent share
8. Delete nonexistent share
"""
# create share
data = {'sname': 'rootshare', 'pool': 'rockstor_rockstor', 'size': 100}
Expand Down Expand Up @@ -401,27 +442,59 @@ def test_delete(self, mock_snapshot, mock_nfs, mock_samba, mock_sftp, mock_remov
self.assertEqual(response5.data['detail'], e_msg)
mock_snapshot.objects.filter(share=share, snap_type='admin').exists.return_value = False

# Delete share with remove_share failure (share still mounted)
mock_remove_share.return_value = 'foo'
mock_remove_share.side_effect = Exception
e_msg = ('Share(rootshare) is still mounted and cannot be deleted. '
'Trying again usually succeeds. But if it does not, you can '
'manually unmount it with command: /usr/bin/umount /mnt2/rootshare')
response7 = self.client.delete('%s/rootshare' % self.BASE_URL)
self.assertEqual(response7.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response7.data)
self.assertEqual(response7.data['detail'], e_msg)
mock_remove_share.side_effect = None

# delete share
response8 = self.client.delete('%s/rootshare' % self.BASE_URL)
self.assertEqual(response8.status_code, status.HTTP_200_OK, msg=response8.data)
assert mock_remove_share.called
self.assertEqual(response8.data, None)

# delete a share that doesn't exist
e_msg = ('Share(invalid) does not exist.')
e_msg = ('Share(invalid) does not exist')
response9 = self.client.delete('%s/invalid' % self.BASE_URL)
self.assertEqual(response9.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response9.data)
self.assertEqual(response9.data['detail'], e_msg)

@mock.patch('storageadmin.views.share.Service')
def test_delete2(self, mock_service):
# happy path
# create share
data = {'sname': 'rootshare', 'pool': 'pool1', 'size': 100}
response = self.client.post(self.BASE_URL, data=data)
self.assertEqual(response.status_code, status.HTTP_200_OK, msg=response.data)
self.assertEqual(response.data['name'], 'rootshare')

# Delete share

mock_service.objects.get.side_effect= None
response7 = self.client.delete('%s/rootshare' % self.BASE_URL)
self.assertEqual(response7.status_code,
status.HTTP_200_OK, msg=response7.data)

@mock.patch('storageadmin.views.share.Service')
def test_delete3(self, mock_service):
# unhappy path
# create share
data = {'sname': 'rootshare', 'pool': 'pool1', 'size': 100}
response = self.client.post(self.BASE_URL, data=data)
self.assertEqual(response.status_code, status.HTTP_200_OK, msg=response.data)
self.assertEqual(response.data['name'], 'rootshare')

# Delete share
e_msg = ('Failed to delete the Share(rootshare). Error from the OS: ')
mock_service.objects.get.side_effect= None
self.mock_remove_share.side_effect = Exception
response7 = self.client.delete('%s/rootshare' % self.BASE_URL)
self.assertEqual(response7.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response7.data)
self.assertEqual(response7.data['detail'], e_msg)
self.mock_remove_share.side_effect = None

# Delete share that is in use by rock-on service
class MockService(object):
def __init__(self, **kwargs):
self.config = {'root_share': 'rootshare',}
e_msg = ('Share(rootshare) cannot be deleted because it is in use '
'by Rock-on service. If you really need to delete '
'it, (1)turn the service off, (2)change its '
'configuration to use a different Share and then '
'(3)try deleting this Share(%s) again.')
mock_service.objects.get.side_effect = MockService
response7 = self.client.delete('%s/rootshare' % self.BASE_URL)
self.assertEqual(response7.status_code,
status.HTTP_500_INTERNAL_SERVER_ERROR, msg=response7.data)
self.assertEqual(response7.data['detail'], e_msg)
5 changes: 5 additions & 0 deletions src/rockstor/storageadmin/views/share.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ def post(self, request):
'hyphen(-), underscore(_) or a period(.).')
handle_exception(Exception(e_msg), request)

if (len(sname) > 254):
#btrfs subvolume names cannot exceed 254 characters.
e_msg = ('Share name length cannot exceed 254 characters')
handle_exception(Exception(e_msg), request)

if (Share.objects.filter(name=sname).exists()):
e_msg = ('Share(%s) already exists. Choose a different name' % sname)
handle_exception(Exception(e_msg), request)
Expand Down

0 comments on commit 09945f5

Please sign in to comment.