From d768fd5640cc54ba120c8e578b8ac08554ea9f50 Mon Sep 17 00:00:00 2001
From: Jana Cupova <jcupova@redhat.com>
Date: Sep 20 2021 09:29:24 +0000
Subject: Increase API unit tests


---

diff --git a/tests/test_hub/test_get_build_target.py b/tests/test_hub/test_get_build_target.py
index 882b4da..4f755d6 100644
--- a/tests/test_hub/test_get_build_target.py
+++ b/tests/test_hub/test_get_build_target.py
@@ -26,3 +26,35 @@ class TestGetBuildTarget(unittest.TestCase):
         with self.assertRaises(koji.GenericError) as cm:
             self.exports.getBuildTarget(build_target, strict=True)
         self.assertEqual(expected, str(cm.exception))
+
+    def test_more_targets_without_strict(self):
+        build_target = 'build-target'
+        target_info = [{'build_tag': 123,
+                        'build_tag_name': 'test-tag',
+                        'dest_tag': 124,
+                        'dest_tag_name': 'destination-test-tag',
+                        'id': 1,
+                        'name': 'test-build-target-1234'},
+                       {'build_tag': 2,
+                        'build_tag_name': 'test-tag-2',
+                        'dest_tag': 3,
+                        'dest_tag_name': 'destination-test-tag-2',
+                        'id': 2,
+                        'name': 'test-build-target-5678'}
+                       ]
+        self.get_build_targets.return_value = target_info
+        rv = self.exports.getBuildTarget(build_target, strict=False)
+        self.assertEqual(None, rv)
+
+    def test_once_target(self):
+        build_target = 'build-target-5678'
+        target_info = [{'build_tag': 2,
+                        'build_tag_name': 'test-tag-2',
+                        'dest_tag': 3,
+                        'dest_tag_name': 'destination-test-tag-2',
+                        'id': 2,
+                        'name': 'test-build-target-5678'}
+                       ]
+        self.get_build_targets.return_value = target_info
+        rv = self.exports.getBuildTarget(build_target, strict=False)
+        self.assertEqual(target_info[0], rv)
diff --git a/tests/test_hub/test_get_buildroot.py b/tests/test_hub/test_get_buildroot.py
new file mode 100644
index 0000000..705a3df
--- /dev/null
+++ b/tests/test_hub/test_get_buildroot.py
@@ -0,0 +1,41 @@
+import mock
+import unittest
+
+import koji
+import kojihub
+
+
+class TestGetBuildroot(unittest.TestCase):
+    def setUp(self):
+        self.query_buildroots = mock.patch('kojihub.query_buildroots').start()
+        self.buildroot_id = 1
+
+    def test_empty_buildroots_without_strict(self):
+        self.query_buildroots.return_value = []
+        rv = kojihub.get_buildroot(self.buildroot_id, strict=False)
+        self.assertEqual(None, rv)
+
+    def test_empty_buildroots_with_strict(self):
+        self.query_buildroots.return_value = []
+        with self.assertRaises(koji.GenericError) as cm:
+            kojihub.get_buildroot(self.buildroot_id, strict=True)
+        self.assertEqual("No such buildroot: %r" % self.buildroot_id, str(cm.exception))
+
+    def test_more_buildroots(self):
+        self.query_buildroots.return_value = [
+            {'arch': 'x86_64', 'id': 1, 'repo_id': 1, 'repo_state': 1, 'tag_id': 2,
+             'tag_name': 'f34-build-7war', 'task_id': 4},
+            {'arch': 'x86_64', 'id': 1, 'repo_id': 1, 'repo_state': 1, 'tag_id': 2,
+             'tag_name': 'f34-build-7war', 'task_id': 4}
+        ]
+        with self.assertRaises(koji.GenericError) as cm:
+            kojihub.get_buildroot(self.buildroot_id)
+        self.assertEqual("More that one buildroot with id: %i" % self.buildroot_id,
+                         str(cm.exception))
+
+    def test_valid(self):
+        buildroot_info = {'arch': 'x86_64', 'id': 1, 'repo_id': 1, 'repo_state': 1, 'tag_id': 2,
+                          'tag_name': 'f34-build-7war', 'task_id': 4}
+        self.query_buildroots.return_value = [buildroot_info]
+        rv = kojihub.get_buildroot(self.buildroot_id, strict=False)
+        self.assertEqual(buildroot_info, rv)
diff --git a/tests/test_hub/test_get_user.py b/tests/test_hub/test_get_user.py
index f8da250..b54a86c 100644
--- a/tests/test_hub/test_get_user.py
+++ b/tests/test_hub/test_get_user.py
@@ -1,5 +1,7 @@
 import unittest
 
+import mock
+
 import koji
 import kojihub
 
@@ -37,6 +39,9 @@ class TestGetUser(unittest.TestCase):
 
 
 class TestGetUserByKrbPrincipal(unittest.TestCase):
+    def setUp(self):
+        self.get_user = mock.patch('kojihub.get_user').start()
+
     def test_wrong_type_krb_principal(self):
         krb_principal = ['test-user']
         with self.assertRaises(koji.GenericError) as cm:
@@ -49,3 +54,11 @@ class TestGetUserByKrbPrincipal(unittest.TestCase):
         with self.assertRaises(koji.GenericError) as cm:
             kojihub.get_user_by_krb_principal(krb_principal)
         self.assertEqual("No kerberos principal provided", str(cm.exception))
+
+    def test_valid(self):
+        krb_principal = 'test-user@test.org'
+        user_info = {'id': 1, 'krb_principals': ['test-user@test.org'],
+                     'name': 'test-user', 'status': 0, 'usertype': 0}
+        self.get_user.return_value = user_info
+        rv = kojihub.get_user_by_krb_principal(krb_principal)
+        self.assertEqual(user_info, rv)
diff --git a/tests/test_hub/test_list_channels.py b/tests/test_hub/test_list_channels.py
index dd9a106..8c1e2de 100644
--- a/tests/test_hub/test_list_channels.py
+++ b/tests/test_hub/test_list_channels.py
@@ -24,6 +24,7 @@ class TestListChannels(unittest.TestCase):
         # It seems MagicMock will not automatically handle attributes that
         # start with "assert"
         self.exports = kojihub.RootExports()
+        self.get_host = mock.patch('kojihub.get_host').start()
 
     def tearDown(self):
         mock.patch.stopall()
@@ -84,3 +85,40 @@ class TestListChannels(unittest.TestCase):
         with self.assertRaises(koji.GenericError):
             kojihub.list_channels(event=1234)
         self.assertEqual(len(self.queries), 0)
+
+    def test_enabled_is_true_host_string(self):
+        self.get_host.return_value = {'arches': 'x86_64', 'capacity': 2.0, 'comment': None,
+                                      'description': None, 'enabled': True, 'id': 1234,
+                                      'name': 'test-host', 'ready': False, 'task_load': 0.0,
+                                      'user_id': 2}
+        kojihub.list_channels(hostID='test-host', enabled=True)
+
+        self.assertEqual(len(self.queries), 1)
+        query = self.queries[0]
+        joins = ['channels ON channels.id = host_channels.channel_id']
+        clauses = [
+            '(host_channels.active = TRUE)',
+            'enabled IS TRUE',
+            'host_channels.host_id = %(host_id)s'
+        ]
+        self.assertEqual(query.tables, ['host_channels'])
+        self.assertEqual(query.aliases, ['comment', 'description', 'enabled', 'id', 'name'])
+        self.assertEqual(query.joins, joins)
+        self.assertEqual(query.values, {'host_id': 1234})
+        self.assertEqual(query.columns, ['channels.comment', 'channels.description',
+                                         'channels.enabled', 'channels.id', 'channels.name'])
+        self.assertEqual(query.clauses, clauses)
+
+    def test_enabled_is_false(self):
+        kojihub.list_channels(enabled=False)
+
+        self.assertEqual(len(self.queries), 1)
+        query = self.queries[0]
+        clauses = [
+            'enabled IS FALSE',
+        ]
+        self.assertEqual(query.tables, ['channels'])
+        self.assertEqual(query.aliases, ['comment', 'description', 'enabled', 'id', 'name'])
+        self.assertEqual(query.columns, ['channels.comment', 'channels.description',
+                                         'channels.enabled', 'channels.id', 'channels.name'])
+        self.assertEqual(query.clauses, clauses)
diff --git a/tests/test_hub/test_list_tags.py b/tests/test_hub/test_list_tags.py
index 73a4dd8..a0f4f8d 100644
--- a/tests/test_hub/test_list_tags.py
+++ b/tests/test_hub/test_list_tags.py
@@ -43,3 +43,12 @@ class TestListTags(unittest.TestCase):
         with self.assertRaises(koji.GenericError) as cm:
             self.exports.listTags(package=package_name)
         self.assertEqual("No such package: %s" % package_name, str(cm.exception))
+
+    def test_build_package_not_none(self):
+        build_id = 999
+        package_id = 998
+
+        with self.assertRaises(koji.GenericError) as cm:
+            self.exports.listTags(build=build_id, package=package_id)
+        self.assertEqual("only one of build and package may be specified", str(cm.exception))
+        self.get_build.assert_not_called()
diff --git a/tests/test_hub/test_pkglist.py b/tests/test_hub/test_pkglist.py
index a9f660d..f203671 100644
--- a/tests/test_hub/test_pkglist.py
+++ b/tests/test_hub/test_pkglist.py
@@ -4,6 +4,7 @@ import unittest
 import koji
 import kojihub
 
+
 def get_user_factory(data):
     def get_user(userInfo, strict=False):
         if isinstance(userInfo, int):
@@ -14,9 +15,11 @@ def get_user_factory(data):
             if ui[key] == userInfo:
                 return ui
         if strict:
+            user_id = 112233
             raise koji.GenericError(user_id)
     return get_user
 
+
 class TestPkglistBlock(unittest.TestCase):
     def setUp(self):
         self.context = mock.patch('kojihub.context').start()
@@ -46,14 +49,37 @@ class TestPkglistBlock(unittest.TestCase):
         lookup_package.assert_called_once_with('pkg', strict=True)
         pkglist_add.assert_called_once_with('tag', 'pkg', block=True, force=force)
 
+    @mock.patch('kojihub.readPackageList')
+    @mock.patch('kojihub.lookup_package')
+    @mock.patch('kojihub.get_tag')
+    @mock.patch('kojihub.pkglist_add')
+    def test_pkglist_block_package_error(
+            self, pkglist_add, get_tag, lookup_package, readPackageList):
+        pkg_name = 'pkg'
+        tag_name = 'tag'
+        force = mock.MagicMock()
+        get_tag.return_value = {'name': tag_name, 'id': 123}
+        lookup_package.return_value = {'name': pkg_name, 'id': 321}
+        readPackageList.return_value = []
+
+        with self.assertRaises(koji.GenericError) as ex:
+            kojihub.pkglist_block('tag', 'pkg', force=force)
+        self.assertEqual("Package %s is not in tag listing for %s" % (pkg_name, tag_name),
+                         str(ex.exception))
+
+        get_tag.assert_called_once_with('tag', strict=True)
+        lookup_package.assert_called_once_with('pkg', strict=True)
+        pkglist_add.assert_not_called()
+
     @mock.patch('kojihub._pkglist_remove')
     @mock.patch('kojihub._pkglist_add')
     @mock.patch('kojihub.readPackageList')
     @mock.patch('kojihub.assert_policy')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_pkglist_unblock(self, lookup_package, get_tag, assert_policy,
-            readPackageList, _pkglist_add, _pkglist_remove):
+    def test_pkglist_unblock(
+            self, lookup_package, get_tag, assert_policy, readPackageList, _pkglist_add,
+            _pkglist_remove):
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'package', 'owner_id': 3}
         get_tag.return_value = tag
@@ -68,8 +94,10 @@ class TestPkglistBlock(unittest.TestCase):
 
         get_tag.assert_called_once_with('tag', strict=True)
         lookup_package.assert_called_once_with('pkg', strict=True)
-        assert_policy.assert_called_once_with('package_list', {'tag': tag['id'],
-            'action': 'unblock', 'package': pkg['id'], 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag['id'], 'action': 'unblock', 'package': pkg['id'],
+                             'force': False},
+            force=False)
         self.assertEqual(readPackageList.call_count, 2)
         readPackageList.assert_has_calls([
             mock.call(tag['id'], pkgID=pkg['id'], inherit=True),
@@ -89,8 +117,9 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.assert_policy')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_pkglist_unblock_inherited(self, lookup_package, get_tag, assert_policy,
-            readPackageList, _pkglist_add, _pkglist_remove):
+    def test_pkglist_unblock_inherited(
+            self, lookup_package, get_tag, assert_policy, readPackageList, _pkglist_add,
+            _pkglist_remove):
         tag_id, pkg_id, owner_id = 1, 2, 3
         get_tag.return_value = {'id': tag_id, 'name': 'tag'}
         lookup_package.return_value = {'id': pkg_id, 'name': 'pkg'}
@@ -104,8 +133,10 @@ class TestPkglistBlock(unittest.TestCase):
 
         get_tag.assert_called_once_with('tag', strict=True)
         lookup_package.assert_called_once_with('pkg', strict=True)
-        assert_policy.assert_called_once_with('package_list', {'tag': tag_id,
-            'action': 'unblock', 'package': pkg_id, 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag_id, 'action': 'unblock', 'package': pkg_id,
+                             'force': False},
+            force=False)
         readPackageList.assert_called_once_with(tag_id, pkgID=pkg_id, inherit=True)
         _pkglist_add.assert_called_once_with(tag_id, pkg_id, owner_id, False, '')
         _pkglist_remove.assert_not_called()
@@ -116,8 +147,9 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.assert_policy')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_pkglist_unblock_not_present(self, lookup_package, get_tag, assert_policy,
-            readPackageList, _pkglist_add, _pkglist_remove):
+    def test_pkglist_unblock_not_present(
+            self, lookup_package, get_tag, assert_policy, readPackageList, _pkglist_add,
+            _pkglist_remove):
         tag_id, pkg_id = 1, 2
         get_tag.return_value = {'id': tag_id, 'name': 'tag'}
         lookup_package.return_value = {'id': pkg_id, 'name': 'pkg'}
@@ -128,8 +160,10 @@ class TestPkglistBlock(unittest.TestCase):
 
         get_tag.assert_called_once_with('tag', strict=True)
         lookup_package.assert_called_once_with('pkg', strict=True)
-        assert_policy.assert_called_once_with('package_list', {'tag': tag_id,
-            'action': 'unblock', 'package': pkg_id, 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag_id, 'action': 'unblock', 'package': pkg_id,
+                             'force': False},
+            force=False)
         readPackageList.assert_called_once_with(tag_id, pkgID=pkg_id, inherit=True)
         _pkglist_add.assert_not_called()
         _pkglist_remove.assert_not_called()
@@ -140,8 +174,9 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.assert_policy')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_pkglist_unblock_not_blocked(self, lookup_package, get_tag, assert_policy,
-            readPackageList, _pkglist_add, _pkglist_remove):
+    def test_pkglist_unblock_not_blocked(
+            self, lookup_package, get_tag, assert_policy, readPackageList, _pkglist_add,
+            _pkglist_remove):
         tag_id, pkg_id, owner_id = 1, 2, 3
         get_tag.return_value = {'id': tag_id, 'name': 'tag'}
         lookup_package.return_value = {'id': pkg_id, 'name': 'pkg'}
@@ -151,14 +186,15 @@ class TestPkglistBlock(unittest.TestCase):
             'owner_id': owner_id,
             'extra_arches': ''}}
 
-
         with self.assertRaises(koji.GenericError):
             kojihub.pkglist_unblock('tag', 'pkg', force=False)
 
         get_tag.assert_called_once_with('tag', strict=True)
         lookup_package.assert_called_once_with('pkg', strict=True)
-        assert_policy.assert_called_once_with('package_list', {'tag': tag_id,
-            'action': 'unblock', 'package': pkg_id, 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag_id, 'action': 'unblock', 'package': pkg_id,
+                             'force': False},
+            force=False)
         readPackageList.assert_called_once_with(tag_id, pkgID=pkg_id, inherit=True)
         _pkglist_add.assert_not_called()
         _pkglist_remove.assert_not_called()
@@ -173,15 +209,16 @@ class TestPkglistBlock(unittest.TestCase):
     def test_pkglist_setarches(self, pkglist_add):
         force = mock.MagicMock()
         kojihub.pkglist_setarches('tag', 'pkg', 'arches', force=force)
-        pkglist_add.assert_called_once_with('tag', 'pkg', extra_arches='arches', force=force, update=True)
+        pkglist_add.assert_called_once_with('tag', 'pkg', extra_arches='arches', force=force,
+                                            update=True)
 
     @mock.patch('kojihub._direct_pkglist_add')
     def test_pkglist_add(self, _direct_pkglist_add):
         # just transition of params + policy=True
         kojihub.pkglist_add('tag', 'pkg', owner='owner', block='block',
-            extra_arches='extra_arches', force='force', update='update')
-        _direct_pkglist_add.assert_called_once_with('tag', 'pkg', 'owner',
-            'block', 'extra_arches', 'force', 'update', policy=True)
+                            extra_arches='extra_arches', force='force', update='update')
+        _direct_pkglist_add.assert_called_once_with('tag', 'pkg', 'owner', 'block', 'extra_arches',
+                                                    'force', 'update', policy=True)
 
     @mock.patch('kojihub._pkglist_add')
     @mock.patch('kojihub.readPackageList')
@@ -189,13 +226,13 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add(self, lookup_package, get_tag, get_user,
-            assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=False
-        update=False
-        policy=True
+        force = False
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         users = [
@@ -208,10 +245,9 @@ class TestPkglistBlock(unittest.TestCase):
         get_user.side_effect = get_user_factory(users)
         readPackageList.return_value = {}
 
-
-        kojihub._direct_pkglist_add(tag['name'], pkg['name'],
-            user['name'], block=block, extra_arches=extra_arches,
-            force=force, update=update, policy=policy)
+        kojihub._direct_pkglist_add(tag['name'], pkg['name'], user['name'], block=block,
+                                    extra_arches=extra_arches, force=force, update=update,
+                                    policy=policy)
 
         get_tag.assert_called_once_with(tag['name'], strict=True)
         lookup_package.assert_called_once_with(pkg['name'], strict=False)
@@ -219,21 +255,20 @@ class TestPkglistBlock(unittest.TestCase):
             mock.call(user['name'], strict=True),
             mock.call(112233),
         ])
-        assert_policy.assert_called_once_with('package_list', {'tag': tag['id'],
-            'action': 'add', 'package': pkg['name'], 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag['id'], 'action': 'add', 'package': pkg['name'],
+                             'force': False},
+            force=False)
         self.assertEqual(self.run_callbacks.call_count, 2)
         self.run_callbacks.assert_has_calls([
-            mock.call('prePackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
-            mock.call('postPackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
+            mock.call('prePackageListChange', action='add', tag=tag, package=pkg, owner=user['id'],
+                      block=block, extra_arches=extra_arches, force=force, update=update,
+                      user=users[1]),
+            mock.call('postPackageListChange', action='add', tag=tag, package=pkg,
+                      owner=user['id'], block=block, extra_arches=extra_arches, force=force,
+                      update=update, user=users[1]),
         ])
-        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'],
-            user['id'], block, extra_arches)
+        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'], user['id'], block, extra_arches)
 
     @mock.patch('kojihub._pkglist_add')
     @mock.patch('kojihub.readPackageList')
@@ -241,13 +276,13 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add_no_package(self, lookup_package,
-            get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add_no_package(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=False
-        update=False
-        policy=True
+        force = False
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         user = {'id': 3, 'name': 'user'}
@@ -258,9 +293,9 @@ class TestPkglistBlock(unittest.TestCase):
 
         # package needs to be name, not dict
         with self.assertRaises(koji.GenericError) as ex:
-            kojihub._direct_pkglist_add(tag['name'], pkg,
-                user['name'], block=block, extra_arches=extra_arches,
-                force=force, update=update, policy=policy)
+            kojihub._direct_pkglist_add(tag['name'], pkg, user['name'], block=block,
+                                        extra_arches=extra_arches, force=force, update=update,
+                                        policy=policy)
         self.assertEqual("No such package: %s" % pkg, str(ex.exception))
 
     @mock.patch('kojihub.get_tag')
@@ -275,7 +310,7 @@ class TestPkglistBlock(unittest.TestCase):
         lookup_package.side_effect = koji.GenericError(expected)
         with self.assertRaises(koji.GenericError) as ex:
             kojihub._direct_pkglist_add(tag['name'], pkg, user, block=False, extra_arches='arch',
-                force=False, update=True)
+                                        force=False, update=True)
         self.assertEqual(expected, str(ex.exception))
 
     @mock.patch('kojihub._pkglist_add')
@@ -284,13 +319,13 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add_no_user(self, lookup_package,
-            get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add_no_user(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=False
-        update=False
-        policy=True
+        force = False
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         user = {'id': 3, 'name': 'user'}
@@ -300,9 +335,9 @@ class TestPkglistBlock(unittest.TestCase):
         readPackageList.return_value = {}
 
         with self.assertRaises(koji.GenericError):
-            kojihub._direct_pkglist_add(tag['name'], pkg,
-                user['name'], block=block, extra_arches=extra_arches,
-                force=force, update=update, policy=policy)
+            kojihub._direct_pkglist_add(tag['name'], pkg, user['name'], block=block,
+                                        extra_arches=extra_arches, force=force, update=update,
+                                        policy=policy)
 
         lookup_package.assert_called_once_with(pkg, strict=False)
         self.assertEqual(self.run_callbacks.call_count, 0)
@@ -314,13 +349,13 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add_new_package(self, lookup_package, get_tag, get_user,
-            assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add_new_package(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=False
-        update=False
-        policy=True
+        force = False
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         users = [
@@ -333,10 +368,9 @@ class TestPkglistBlock(unittest.TestCase):
         get_user.side_effect = get_user_factory(users)
         readPackageList.return_value = {}
 
-
-        kojihub._direct_pkglist_add(tag['name'], pkg['name'],
-            user['name'], block=block, extra_arches=extra_arches,
-            force=force, update=update, policy=policy)
+        kojihub._direct_pkglist_add(tag['name'], pkg['name'], user['name'], block=block,
+                                    extra_arches=extra_arches, force=force, update=update,
+                                    policy=policy)
 
         get_tag.assert_called_once_with(tag['name'], strict=True)
         self.assertEqual(lookup_package.call_count, 2)
@@ -348,21 +382,20 @@ class TestPkglistBlock(unittest.TestCase):
             mock.call(user['name'], strict=True),
             mock.call(112233),
         ])
-        assert_policy.assert_called_once_with('package_list', {'tag': tag['id'],
-            'action': 'add', 'package': pkg['name'], 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag['id'], 'action': 'add', 'package': pkg['name'],
+                             'force': False},
+            force=False)
         self.assertEqual(self.run_callbacks.call_count, 2)
         self.run_callbacks.assert_has_calls([
-            mock.call('prePackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
-            mock.call('postPackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
+            mock.call('prePackageListChange', action='add', tag=tag, package=pkg, owner=user['id'],
+                      block=block, extra_arches=extra_arches, force=force, update=update,
+                      user=users[1]),
+            mock.call('postPackageListChange', action='add', tag=tag, package=pkg,
+                      owner=user['id'], block=block, extra_arches=extra_arches, force=force,
+                      update=update, user=users[1]),
         ])
-        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'],
-            user['id'], block, extra_arches)
+        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'], user['id'], block, extra_arches)
 
     @mock.patch('kojihub._pkglist_add')
     @mock.patch('kojihub.readPackageList')
@@ -370,18 +403,17 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add_blocked_previously(self,
-            lookup_package, get_tag, get_user,
-            assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add_blocked_previously(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=False
-        update=False
-        policy=True
+        force = False
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         users = [
-            {'id': 3, 'name': 'user',},
+            {'id': 3, 'name': 'user', },
             {'id': 112233, 'name': 'user1'},
         ]
         user = users[0]
@@ -395,9 +427,9 @@ class TestPkglistBlock(unittest.TestCase):
         }
 
         with self.assertRaises(koji.GenericError):
-            kojihub._direct_pkglist_add(tag['name'], pkg['name'],
-                user['name'], block=block, extra_arches=extra_arches,
-                force=force, update=update, policy=policy)
+            kojihub._direct_pkglist_add(tag['name'], pkg['name'], user['name'], block=block,
+                                        extra_arches=extra_arches, force=force, update=update,
+                                        policy=policy)
 
         get_tag.assert_called_once_with(tag['name'], strict=True)
         lookup_package.assert_called_once_with(pkg['name'], strict=False)
@@ -405,13 +437,13 @@ class TestPkglistBlock(unittest.TestCase):
             mock.call(user['name'], strict=True),
             mock.call(112233),
         ])
-        assert_policy.assert_called_once_with('package_list', {'tag': tag['id'],
-            'action': 'add', 'package': pkg['name'], 'force': False}, force=False)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': tag['id'], 'action': 'add', 'package': pkg['name'],
+                             'force': False},
+            force=False)
         self.run_callbacks.assert_called_once_with(
-                'prePackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1])
+            'prePackageListChange', action='add', tag=tag, package=pkg, owner=user['id'],
+            block=block, extra_arches=extra_arches, force=force, update=update, user=users[1])
         _pkglist_add.assert_not_called()
 
     @mock.patch('kojihub._pkglist_add')
@@ -420,18 +452,17 @@ class TestPkglistBlock(unittest.TestCase):
     @mock.patch('kojihub.get_user')
     @mock.patch('kojihub.get_tag')
     @mock.patch('kojihub.lookup_package')
-    def test_direct_pkglist_add_blocked_previously_force(self,
-            lookup_package, get_tag, get_user,
-            assert_policy, readPackageList, _pkglist_add):
+    def test_direct_pkglist_add_blocked_previously_force(
+            self, lookup_package, get_tag, get_user, assert_policy, readPackageList, _pkglist_add):
         block = False
         extra_arches = 'arch123'
-        force=True
-        update=False
-        policy=True
+        force = True
+        update = False
+        policy = True
         tag = {'id': 1, 'name': 'tag'}
         pkg = {'id': 2, 'name': 'pkg', 'owner_id': 3}
         users = [
-            {'id': 3, 'name': 'user',},
+            {'id': 3, 'name': 'user', },
             {'id': 112233, 'name': 'user1'},
         ]
         user = users[0]
@@ -444,9 +475,9 @@ class TestPkglistBlock(unittest.TestCase):
             'extra_arches': ''}
         }
 
-        kojihub._direct_pkglist_add(tag['name'], pkg['name'],
-            user['name'], block=block, extra_arches=extra_arches,
-            force=force, update=update, policy=policy)
+        kojihub._direct_pkglist_add(tag['name'], pkg['name'], user['name'], block=block,
+                                    extra_arches=extra_arches, force=force, update=update,
+                                    policy=policy)
 
         get_tag.assert_called_once_with(tag['name'], strict=True)
         lookup_package.assert_called_once_with(pkg['name'], strict=False)
@@ -455,19 +486,17 @@ class TestPkglistBlock(unittest.TestCase):
             mock.call(112233),
         ])
         # force + admin
-        assert_policy.assert_called_once_with('package_list',
-            {'tag': 1, 'action': 'add', 'package': 'pkg', 'force': True}, force=True)
+        assert_policy.assert_called_once_with(
+            'package_list', {'tag': 1, 'action': 'add', 'package': 'pkg', 'force': True},
+            force=True)
 
         self.assertEqual(self.run_callbacks.call_count, 2)
         self.run_callbacks.assert_has_calls([
-            mock.call('prePackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
-            mock.call('postPackageListChange', action='add', tag=tag,
-                package=pkg, owner=user['id'], block=block,
-                extra_arches=extra_arches, force=force, update=update,
-                user=users[1]),
+            mock.call('prePackageListChange', action='add', tag=tag, package=pkg, owner=user['id'],
+                      block=block, extra_arches=extra_arches, force=force, update=update,
+                      user=users[1]),
+            mock.call('postPackageListChange', action='add', tag=tag, package=pkg,
+                      owner=user['id'], block=block, extra_arches=extra_arches, force=force,
+                      update=update, user=users[1]),
         ])
-        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'],
-            user['id'], block, extra_arches)
+        _pkglist_add.assert_called_once_with(tag['id'], pkg['id'], user['id'], block, extra_arches)
diff --git a/tests/test_hub/test_restart_hosts.py b/tests/test_hub/test_restart_hosts.py
new file mode 100644
index 0000000..5da1c32
--- /dev/null
+++ b/tests/test_hub/test_restart_hosts.py
@@ -0,0 +1,24 @@
+import unittest
+
+import mock
+
+import kojihub
+
+
+class TestRestartHosts(unittest.TestCase):
+
+    def setUp(self):
+        self.exports = kojihub.RootExports()
+        self.context = mock.patch('kojihub.context').start()
+        self.context.session.assertPerm = mock.MagicMock()
+        self.make_task = mock.patch('kojihub.make_task').start()
+
+    def options_is_none(self):
+        self.make_task.return_value = 13
+        rv = self.exports.restartHosts()
+        self.assertEqual(rv, 13)
+
+    def options_is_not_none(self):
+        self.make_task.return_value = 13
+        rv = self.exports.restartHosts(options={'opt': 'open'})
+        self.assertEqual(rv, 13)
diff --git a/tests/test_hub/test_tag_operations.py b/tests/test_hub/test_tag_operations.py
index 33338be..7019e71 100644
--- a/tests/test_hub/test_tag_operations.py
+++ b/tests/test_hub/test_tag_operations.py
@@ -33,14 +33,14 @@ class TestTagBuild(unittest.TestCase):
 
     def setUp(self):
         self.InsertProcessor = mock.patch('kojihub.InsertProcessor',
-                side_effect=self.getInsert).start()
+                                          side_effect=self.getInsert).start()
         self.inserts = []
         self.UpdateProcessor = mock.patch('kojihub.UpdateProcessor',
-                side_effect=self.getUpdate).start()
+                                          side_effect=self.getUpdate).start()
         self.updates = []
         self.query_executeOne = mock.MagicMock()
         self.QueryProcessor = mock.patch('kojihub.QueryProcessor',
-                side_effect=self.getQuery).start()
+                                         side_effect=self.getQuery).start()
         self.queries = []
         self._dml = mock.patch('kojihub._dml').start()
         self.get_tag = mock.patch('kojihub.get_tag').start()
@@ -100,6 +100,48 @@ class TestTagBuild(unittest.TestCase):
         self.assertEqual(insert.rawdata, {})
         insert = self.inserts[0]
 
+    def test_simple_tag_with_user(self):
+        self.check_tag_access.return_value = (True, False, "")
+        self.get_build.return_value = {
+            'id': 1,
+            'name': 'name',
+            'version': 'version',
+            'release': 'release',
+            'state': koji.BUILD_STATES['COMPLETE'],
+        }
+        self.get_tag.return_value = {
+            'id': 777,
+            'name': 'tag',
+        }
+        self.get_user.return_value = {
+            'id': 999,
+            'name': 'user',
+        }
+        self.context.event_id = 42
+        # set return for the already tagged check
+        self.query_executeOne.return_value = None
+
+        # call it
+        kojihub._tag_build('sometag', 'name-version-release', user_id=999)
+
+        self.get_tag.called_once_with('sometag', strict=True)
+        self.get_user.called_one_with(999, strict=True)
+        self.get_build.called_once_with('name-version-release', strict=True)
+        self.context.session.assertPerm.assert_not_called()
+
+        # check the insert
+        self.assertEqual(len(self.inserts), 1)
+        insert = self.inserts[0]
+        self.assertEqual(insert.table, 'tag_listing')
+        values = {
+            'build_id': 1,
+            'create_event': 42,
+            'creator_id': 999,
+            'tag_id': 777
+        }
+        self.assertEqual(insert.data, values)
+        self.assertEqual(insert.rawdata, {})
+        insert = self.inserts[0]
 
     def test_simple_untag(self):
         self.check_tag_access.return_value = (True, False, "")
@@ -147,6 +189,53 @@ class TestTagBuild(unittest.TestCase):
         self.assertEqual(update.values, values)
         update = self.updates[0]
 
+    def test_simple_untag_with_user(self):
+        self.check_tag_access.return_value = (True, False, "")
+        self.get_build.return_value = {
+            'id': 1,
+            'name': 'name',
+            'version': 'version',
+            'release': 'release',
+            'state': koji.BUILD_STATES['COMPLETE'],
+        }
+        self.get_tag.return_value = {
+            'id': 777,
+            'name': 'tag',
+        }
+        self.get_user.return_value = {
+            'id': 999,
+            'name': 'user',
+        }
+        self.context.event_id = 42
+        # set return for the already tagged check
+        self.query_executeOne.return_value = None
+
+        # call it
+        kojihub._untag_build('sometag', 'name-version-release', user_id=999)
+
+        self.get_tag.called_once_with('sometag', strict=True)
+        self.get_user.called_one_with(999, strict=True)
+        self.get_build.called_once_with('name-version-release', strict=True)
+        self.context.session.assertPerm.assert_not_called()
+        self.assertEqual(len(self.inserts), 0)
+
+        # check the update
+        self.assertEqual(len(self.updates), 1)
+        update = self.updates[0]
+        self.assertEqual(update.table, 'tag_listing')
+        values = {
+            'build_id': 1,
+            'tag_id': 777
+        }
+        data = {
+            'revoke_event': 42,
+            'revoker_id': 999,
+        }
+        self.assertEqual(update.rawdata, {'active': 'NULL'})
+        self.assertEqual(update.data, data)
+        self.assertEqual(update.values, values)
+        update = self.updates[0]
+
 
 class TestGetTag(unittest.TestCase):
 

