From f5f32d902b39889880e0a8ca35170069aa111d63 Mon Sep 17 00:00:00 2001 From: maxkoryukov Date: Wed, 3 Feb 2016 18:19:35 +0500 Subject: [PATCH] SoftChroot module done --- headphones/config_test.py | 17 ++++++-- headphones/softchroot.py | 55 +++++++++++++++++++++++- headphones/softchroot_test.py | 78 ++++++++++++++++++++++++++++++++++- 3 files changed, 145 insertions(+), 5 deletions(-) diff --git a/headphones/config_test.py b/headphones/config_test.py index 4af7f725..9fcf8560 100644 --- a/headphones/config_test.py +++ b/headphones/config_test.py @@ -1,6 +1,6 @@ #import unittest import mock -from headphones.unittestcompat import TestCase +from headphones.unittestcompat import TestCase, TestArgs from mock import MagicMock import headphones.config @@ -34,6 +34,17 @@ class ConfigPathTest(TestCase): p1 = path(s) self.assertIn('headphones.config.path', p1.__repr__()) + @TestArgs( + (None), + (''), + (' '), + ) + def test_empty_path(self, s): + """ headphones.path does nom modify empty strings """ + p1 = path(s) + a = str(p1) + e = str(s) + self.assertEqual(a, e) # patch required, since Config works ower a @mock.patch('headphones.config.ConfigObj', name='ConfigObjMock') @@ -47,14 +58,14 @@ class ConfigTest(TestCase): return config_obj_mock def test_create(self, config_obj_fabric_mock): - """Test creating headphones.Config""" + """ creating headphones.Config """ cf = headphones.config.Config('/tmp/notexist') self.assertIsInstance(cf, headphones.config.Config) self.assertTrue(True) def test_write(self, config_obj_fabric_mock): - """ Test writing config """ + """ writing config """ path = '/tmp/notexist' conf_mock = self.putConfigToFabric(config_obj_fabric_mock) diff --git a/headphones/softchroot.py b/headphones/softchroot.py index 5219a8fd..a56c669d 100644 --- a/headphones/softchroot.py +++ b/headphones/softchroot.py @@ -2,13 +2,66 @@ import os from headphones.exceptions import SoftChrootError class SoftChroot(object): + + enabled = False + chroot = None + def __init__(self, path): + if not path: + #disabled + return + path = path.strip() + if not path: + return if (not os.path.exists(path) or not os.path.isdir(path)): raise SoftChrootError('No such directory: %s' % path) - path = path.strip(os.path.sep) + os.path.sep + path = path.rstrip(os.path.sep) + os.path.sep + self.enabled = True self.chroot = path + + def isEnabled(self): + return self.enabled + + def getRoot(self): + return self.chroot + + def apply(self, path): + if not self.enabled: + return path + + if not path: + return path + + p = path.strip() + if not p: + return path + + if path.startswith(self.chroot): + p = os.path.sep + path[len(self.chroot):] + else: + p = os.path.sep + + return p + + def revoke(self, path): + if not self.enabled: + return path + + if not path: + return path + + p = path.strip() + if not p: + return path + + if os.path.sep == p[0]: + p = p[1:] + + + p = self.chroot + p + return p diff --git a/headphones/softchroot_test.py b/headphones/softchroot_test.py index 424e2eac..e0db5edd 100644 --- a/headphones/softchroot_test.py +++ b/headphones/softchroot_test.py @@ -1,6 +1,6 @@ import os import mock -from headphones.unittestcompat import TestCase +from headphones.unittestcompat import TestCase, TestArgs #from mock import MagicMock from headphones.softchroot import SoftChroot @@ -12,6 +12,21 @@ class SoftChrootTest(TestCase): cf = SoftChroot('/tmp/') self.assertIsInstance(cf, SoftChroot) + self.assertTrue(cf.isEnabled()) + self.assertEqual(cf.getRoot(), '/tmp/') + + @TestArgs( + (None), + (''), + (' '), + ) + def test_create_disabled(self, empty_path): + """ create DISABLED SoftChroot """ + + cf = SoftChroot(empty_path) + self.assertIsInstance(cf, SoftChroot) + self.assertFalse(cf.isEnabled()) + self.assertIsNone(cf.getRoot()) def test_create_on_not_exists_dir(self): """ create SoftChroot on non existent dir """ @@ -44,3 +59,64 @@ class SoftChrootTest(TestCase): self.assertRegexpMatches(str(exc.exception), r'No such directory') self.assertRegexpMatches(str(exc.exception), path) + + + @TestArgs( + (None, None), + ('', ''), + (' ', ' '), + ('/tmp/', '/'), + ('/tmp/asdf', '/asdf'), + ) + def test_apply(self, p, e): + """ apply SoftChroot """ + sc = SoftChroot('/tmp/') + a = sc.apply(p) + self.assertEqual(a, e) + + @TestArgs( + ('/'), + ('/nonch/path/asdf'), + ('tmp/asdf'), + ) + def test_apply_out_of_root(self, p): + """ apply SoftChroot to paths outside of the chroot """ + sc = SoftChroot('/tmp/') + a = sc.apply(p) + self.assertEqual(a, '/') + + @TestArgs( + (None, None), + ('', ''), + (' ', ' '), + ('/', '/tmp/'), + ('/asdf', '/tmp/asdf'), + ('/asdf/', '/tmp/asdf/'), + ('localdir/adf', '/tmp/localdir/adf'), + ('localdir/adf/', '/tmp/localdir/adf/'), + ) + def test_revoke(self, p, e): + """ revoke SoftChroot """ + sc = SoftChroot('/tmp/') + a = sc.revoke(p) + self.assertEqual(a, e) + + @TestArgs( + (None), + (''), + (' '), + ('/tmp'), + ('/tmp/'), + ('/tmp/asdf'), + ('/tmp/localdir/adf'), + ('localdir/adf'), + ('localdir/adf/'), + ) + def test_actions_on_disabled(self, p): + """ disabled SoftChroot should not change args on apply and revoke """ + sc = SoftChroot(None) + a = sc.apply(p) + self.assertEqual(a, p) + + r = sc.revoke(p) + self.assertEqual(r, p)