Martin and Petr Voborník found an automount plugin bug in my patch 50. I checked the automount test coverage and found that it isn't that great – not only automount-key-add-indirect with the parentmap flag, but the import and tofiles commands weren't tested at all.

This patch makes the situation a bit better.


--
Petr³
From c7b466b0481eac481c61100c91213a5df257e6c8 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Fri, 25 May 2012 10:53:23 -0400
Subject: [PATCH] Add more automount tests

This adds tests for the automountlocation_tofiles and
automountlocation_import commands, and to automountmap_add_indirect
with the --parentmap option.

The tofiles test checks not only the XML-RPC output, but also the
output_for_cli method.

The import tests load data from tofiles output to the directory
and check that tofiles output matches.
This only works when all maps are connected to auto.master.

Two minor touches to the automount plugin itself: remove an extra
space, and don't hide the traceback when re-raising an exception.
---
 ipalib/plugins/automount.py                |    4 +-
 tests/test_xmlrpc/test_automount_plugin.py |  227 +++++++++++++++++++++++++++-
 2 files changed, 223 insertions(+), 8 deletions(-)

diff --git a/ipalib/plugins/automount.py b/ipalib/plugins/automount.py
index d3451314cd8740fab5e0dc0d64189a844e082813..5c9f42b4c9812971e4fa03d4700b20ec70a0f81a 100644
--- a/ipalib/plugins/automount.py
+++ b/ipalib/plugins/automount.py
@@ -349,7 +349,7 @@ def output_for_cli(self, textui, result, *keys, **options):
         textui.print_plain(_('maps not connected to /etc/auto.master:'))
         for m in orphanmaps:
             textui.print_plain('---------------------------')
-            textui.print_plain('/etc/%s: ' % m['automountmapname'])
+            textui.print_plain('/etc/%s:' % m['automountmapname'])
             for k in orphankeys:
                 if len(k) == 0: continue
                 dn = DN(k[0]['dn'])
@@ -391,7 +391,7 @@ def __read_mapfile(self, filename):
                     reason=_('File %(file)s not found') % {'file': filename}
                 )
             else:
-                raise e
+                raise
         return map
 
     def forward(self, *args, **options):
diff --git a/tests/test_xmlrpc/test_automount_plugin.py b/tests/test_xmlrpc/test_automount_plugin.py
index 0dd65d8704cb7d2fbaa1e5127db4089ad243308e..d6c2899796edc983e7196e137a2853df377cd934 100644
--- a/tests/test_xmlrpc/test_automount_plugin.py
+++ b/tests/test_xmlrpc/test_automount_plugin.py
@@ -22,14 +22,90 @@
 """
 
 import sys
-from nose.tools import raises, assert_raises  # pylint: disable=E0611
+import textwrap
+import tempfile
+import shutil
 
-from xmlrpc_test import XMLRPC_test, assert_attr_equal
 from ipalib import api
 from ipalib import errors
+from ipalib.dn import DN
 
+from nose.tools import raises, assert_raises  # pylint: disable=E0611
+from xmlrpc_test import XMLRPC_test, assert_attr_equal
+from tests.util import assert_deepequal
 
-class test_automount(XMLRPC_test):
+
+class MockTextui(list):
+    """Collects output lines"""
+    # Extend the mock object if other textui methods are called
+    def print_plain(self, line):
+        self.append(unicode(line))
+
+
+class AutomountTest(XMLRPC_test):
+    """Provides common functionality for automount tests"""
+    def check_tofiles(self):
+        """Check automountlocation_tofiles output against self.tofiles_output
+        """
+        res = api.Command['automountlocation_tofiles'](self.locname)
+
+        mock_ui = MockTextui()
+        command = api.Command['automountlocation_tofiles']
+        command.output_for_cli(mock_ui, res, self.locname)
+        expected_output = self.tofiles_output
+        assert_deepequal(expected_output, u'\n'.join(mock_ui))
+
+    def check_import_roundtrip(self):
+        """Check automountlocation_tofiles/automountlocation_import roundtrip
+
+        Loads self.tofiles_output (which should correspond to
+        automountlocation_tofiles output), then checks the resulting map
+        against tofiles_output again.
+        Do not use this if the test creates maps that aren't connected to
+        auto.master -- these can't be imported successfully.
+        """
+        conf_directory = tempfile.mkdtemp()
+
+        # Parse the tofiles_output into individual files, replace /etc/ by
+        # our temporary directory name
+        current_file = None
+        for line in self.tofiles_output.splitlines():
+            line = line.replace('/etc/',  '%s/' % conf_directory)
+            if line.startswith(conf_directory) and line.endswith(':'):
+                current_file = open(line.rstrip(':'), 'w')
+            elif '--------' in line:
+                current_file.close()
+            elif line.startswith('maps not connected to '):
+                break
+            else:
+                current_file.write(line + '\n')
+        current_file.close()
+
+        self.failsafe_add(api.Object.automountlocation, self.locname)
+
+        try:
+            # Feed the files to automountlocation_import & check
+            master_file = u'%s/auto.master' % conf_directory
+            automountlocation_import = api.Command['automountlocation_import']
+            res = automountlocation_import(self.locname, master_file)
+            assert_deepequal(dict(
+                result=dict(
+                    keys=lambda k: k,
+                    maps=lambda m: m,
+                    skipped=(),
+                    duplicatemaps=(),
+                    duplicatekeys=(),
+                )), res)
+            self.check_tofiles()
+        finally:
+            res = api.Command['automountlocation_del'](self.locname)['result']
+            assert res
+            assert_attr_equal(res, 'failed', '')
+
+        # Success; delete the temporary directory
+        shutil.rmtree(conf_directory)
+
+class test_automount(AutomountTest):
     """
     Test the `automount` plugin.
     """
@@ -45,6 +121,18 @@ class test_automount(XMLRPC_test):
     key_kw = {'automountkey': keyname, 'automountinformation': info, 'raw': True}
     key_kw2 = {'automountkey': keyname2, 'automountinformation': info, 'raw': True}
 
+    tofiles_output = textwrap.dedent(u"""
+        /etc/auto.master:
+        /-\t/etc/auto.direct
+        ---------------------------
+        /etc/auto.direct:
+
+        maps not connected to /etc/auto.master:
+        ---------------------------
+        /etc/testmap:
+        testkey2\tro
+        """).strip()
+
     def test_0_automountlocation_add(self):
         """
         Test adding a location `xmlrpc.automountlocation_add` method.
@@ -141,6 +229,59 @@ def test_a_automountmap_mod(self):
         assert res
         assert_attr_equal(res, 'description', 'new description')
 
+    def test_a2_automountmap_tofiles(self):
+        """
+        Test the `automountlocation_tofiles` command.
+        """
+        res = api.Command['automountlocation_tofiles'](self.locname)
+        assert_deepequal(dict(
+            result=dict(
+                keys={'auto.direct': ()},
+                orphanmaps=(dict(
+                    dn=lambda dn: DN(dn) == DN(
+                            ('automountmapname', self.mapname),
+                            ('cn', self.locname),
+                            ('cn', 'automount'), api.env.basedn),
+                    description=(u'description of map',),
+                    automountmapname=(u'testmap',)),),
+                orphankeys=[(
+                    dict(
+                        dn=lambda dn: DN(dn) == DN(
+                            ('description', self.keyname2),
+                            ('automountmapname', 'testmap'),
+                            ('cn', self.locname),
+                            ('cn', 'automount'), api.env.basedn),
+                        automountkey=(self.keyname2,),
+                        description=(self.keyname2,),
+                        automountinformation=(u'ro',),
+                    ),
+                    dict(
+                        dn=lambda dn: DN(dn) == DN(
+                            ('description', self.keyname_rename),
+                            ('automountmapname', 'testmap'),
+                            ('cn', self.locname),
+                            ('cn', 'automount'), api.env.basedn),
+                        automountkey=(self.keyname_rename,),
+                        description=(self.keyname_rename,),
+                        automountinformation=(u'rw',),
+                    ))],
+                maps=(
+                    dict(
+                        dn=lambda dn: DN(dn) == DN(
+                            ('description', '/- auto.direct'),
+                            ('automountmapname', 'auto.master'),
+                            ('cn', self.locname),
+                            ('cn', 'automount'), api.env.basedn),
+                        automountkey=(u'/-',),
+                        description=(u'/- auto.direct',),
+                        automountinformation=(u'auto.direct',)
+                    ),
+            ))), res)
+
+        # Also check the CLI output
+
+        self.check_tofiles()
+
     def test_b_automountkey_del(self):
         """
         Test the `xmlrpc.automountkey_del` method.
@@ -175,15 +316,28 @@ def test_d_automountmap_del(self):
         with assert_raises(errors.NotFound):
             api.Command['automountkey_show'](self.locname, self.mapname, **key_kw)
 
-class test_automount_direct(XMLRPC_test):
+
+class test_automount_direct(AutomountTest):
     """
     Test the `automount` plugin indirect map functionality.
     """
     locname = u'testlocation'
     mapname = u'auto.direct2'
     keyname = u'/-'
     direct_kw = { 'key' : keyname }
 
+    tofiles_output = textwrap.dedent(u"""
+        /etc/auto.master:
+        /-\t/etc/auto.direct
+        /-\t/etc/auto.direct2
+        ---------------------------
+        /etc/auto.direct:
+        ---------------------------
+        /etc/auto.direct2:
+
+        maps not connected to /etc/auto.master:
+        """).strip()
+
     def test_0_automountlocation_add(self):
         """
         Test adding a location.
@@ -207,6 +361,10 @@ def test_2_automountmap_add_duplicate(self):
         """
         res = api.Command['automountmap_add_indirect'](self.locname, self.mapname, **self.direct_kw)['result']
 
+    def test_2a_automountmap_tofiles(self):
+        """Test the `automountmap_tofiles` command"""
+        self.check_tofiles()
+
     def test_3_automountlocation_del(self):
         """
         Remove the location.
@@ -219,7 +377,13 @@ def test_3_automountlocation_del(self):
         with assert_raises(errors.NotFound):
             api.Command['automountlocation_show'](self.locname)
 
-class test_automount_indirect(XMLRPC_test):
+    def test_z_import_roundtrip(self):
+        """Check automountlocation_tofiles/automountlocation_import roundtrip
+        """
+        self.check_import_roundtrip()
+
+
+class test_automount_indirect(AutomountTest):
     """
     Test the `automount` plugin indirect map functionality.
     """
@@ -230,6 +394,18 @@ class test_automount_indirect(XMLRPC_test):
     map_kw = {'key': keyname, 'parentmap': parentmap, 'raw': True}
     key_kw = {'automountkey': keyname, 'automountinformation': mapname}
 
+    tofiles_output = textwrap.dedent(u"""
+        /etc/auto.master:
+        /-\t/etc/auto.direct
+        /home\t/etc/auto.home
+        ---------------------------
+        /etc/auto.direct:
+        ---------------------------
+        /etc/auto.home:
+
+        maps not connected to /etc/auto.master:
+        """).strip()
+
     def test_0_automountlocation_add(self):
         """
         Test adding a location.
@@ -261,6 +437,10 @@ def test_2_automountmap_show(self):
         assert res
         assert_attr_equal(res, 'automountmapname', self.mapname)
 
+    def test_2a_automountmap_tofiles(self):
+        """Test the `automountmap_tofiles` command"""
+        self.check_tofiles()
+
     def test_3_automountkey_del(self):
         """
         Remove the indirect key /home.
@@ -297,16 +477,38 @@ def test_5_automountlocation_del(self):
         with assert_raises(errors.NotFound):
             api.Command['automountlocation_show'](self.locname)
 
+    def test_z_import_roundtrip(self):
+        """Check automountlocation_tofiles/automountlocation_import roundtrip
+        """
+        self.check_import_roundtrip()
 
-class test_automount_indirect_no_parent(XMLRPC_test):
+class test_automount_indirect_no_parent(AutomountTest):
     """
     Test the `automount` plugin Indirect map function.
     """
     locname = u'testlocation'
     mapname = u'auto.home'
     keyname = u'/home'
+    mapname2 = u'auto.direct2'
+    keyname2 = u'direct2'
     parentmap = u'auto.master'
     map_kw = {'key': keyname, 'raw': True}
+    map_kw2 = {'key': keyname2, 'raw': True}
+
+    tofiles_output = textwrap.dedent(u"""
+        /etc/auto.master:
+        /-\t/etc/auto.direct
+        /home\t/etc/auto.home
+        ---------------------------
+        /etc/auto.direct:
+        ---------------------------
+        /etc/auto.home:
+        direct2\t-fstype=autofs ldap:auto.direct2
+
+        maps not connected to /etc/auto.master:
+        ---------------------------
+        /etc/auto.direct2:
+        """).strip()
 
     def test_0_automountlocation_add(self):
         """
@@ -333,6 +535,19 @@ def test_2_automountkey_show(self):
         assert res
         assert_attr_equal(res, 'automountkey', self.keyname)
 
+    def test_2a_automountmap_add_indirect(self):
+        """
+        Test adding an indirect map with default parent.
+        """
+        res = api.Command['automountmap_add_indirect'](self.locname,
+            u'auto.direct2', parentmap=self.mapname, **self.map_kw2)['result']
+        assert res
+        assert_attr_equal(res, 'automountmapname', self.mapname2)
+
+    def test_2b_automountmap_tofiles(self):
+        """Test the `automountmap_tofiles` command"""
+        self.check_tofiles()
+
     def test_3_automountkey_del(self):
         """
         Remove the indirect key /home.
-- 
1.7.10.2

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to