Project Fondue have been busy once again and we've just put live a Permissions Calculator, a tool to make it simple to generate the syntax for the chmod (change mode) command.
Remembering the syntax for the chmod command can be tricky. Whilst it's easy to remember the basics, do you know the difference between setgid, setuid and the sticky bit?
The Unix Permissions Calculator provides a way to understand permissions more fully as well as provide a resource to point colleagues to when you want to explain the use of permissions in documentation.
One feature that we're hoping will come in handy is the permlinking of octal permissions. This makes it possible to link documentation which is describing setting permissions to explanations of exactly what those permissions do. Here's an example: 0777
Another part of the tool which was personally interesting to me was testing the symbolic syntax generator code. In the end I used a dynamically generated test suite which generated the tests based on all the permutations of the target permission.
Testing all permutations of both initial and target permissions resulted in ~2.8 million tests which was a bit excessive, so in the end I tested every permutation of the target with a set of 11 initial permissions. This resulted in over 18k tests but unlike the 2.8 million tests took only minutes to run. This demonstrated to me that there's a happy balance to strike with testing where you can cover pretty all of your bases but without going to extremes.
Out of interest the code to generate dynamic tests is very straight-forward so here's a quick example:
import unittest
class MyTests(unittest.TestCase):
def test_something(self):
"""A daft example"""
self.assertEqual(1,1)
def test_generator(data):
def test(self):
# Assert something using data here e.g:
# result = foo(data)
self.assertEqual(len(data), 3) # another example
return test
if __name__ == '__main__':
data = ("foo", "bar", "baz")
for item in data:
test_name = 'test_%s' % item
test = test_generator(item)
setattr(MyTests, test_name, test)
suite = unittest.TestLoader().loadTestsFromTestCase(MyTests)
unittest.TextTestRunner(verbosity=2).run(suite)
Ok the examples are dumb but you get the idea. Running this gives you:
test_bar (__main__.MyTests) ... ok
test_baz (__main__.MyTests) ... ok
test_foo (__main__.MyTests) ... ok
A daft example ... ok
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK