# -*- coding: utf-8 -*-
# Copyright (C) 2012-2018 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
from __future__ import absolute_import
from __future__ import unicode_literals
import libdnf.transaction
import dnf.cli.output
import dnf.const
import dnf.transaction
import tests.support
from tests.support import mock
INFOOUTPUT_OUTPUT = """\
Name : tour
Epoch : 1
Version : 5
Release : 0
Architecture : noarch
Size : 0.0
Source : tour.src.rpm
Repository : None
Summary : A summary of the package.
URL : http://example.com
License : GPL+
Description :
"""
LIST_TRANSACTION_OUTPUT = u"""\
================================================================================
Package Arch Version Repository Size
================================================================================
Upgrading:
pepper x86_64 20-1 updates 0
replacing hole.x86_64 1-1
Transaction Summary
================================================================================
Upgrade 1 Package
"""
class OutputFunctionsTest(tests.support.TestCase):
def test_make_lists(self):
return
goal = mock.Mock(get_reason=lambda x: libdnf.transaction.TransactionItemReason_USER)
ts = dnf.transaction.Transaction()
# ts = dnf.db.history.
ts.add_install('pepper-3', [])
ts.add_install('pepper-2', [])
lists = dnf.cli.output._make_lists(ts, goal)
self.assertEmpty(lists.erased)
self.assertEqual([tsi._active for tsi in lists.installed],
['pepper-2', 'pepper-3'])
def test_spread(self):
fun = dnf.cli.output._spread_in_columns
self.assertEqual(fun(3, "tour", list(range(3))),
[('tour', 0, 1), ('', 2, '')])
self.assertEqual(fun(3, "tour", ()), [('tour', '', '')])
self.assertEqual(fun(5, "tour", list(range(8))),
[('tour', 0, 1, 2, 3), ('', 4, 5, 6, 7)])
class OutputTest(tests.support.DnfBaseTestCase):
REPOS = ['updates']
@staticmethod
def _keyboard_interrupt(*ignored):
raise KeyboardInterrupt
@staticmethod
def _eof_error(*ignored):
raise EOFError
def setUp(self):
super(OutputTest, self).setUp()
self.output = dnf.cli.output.Output(self.base, self.base.conf)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_col_widths(self, _real_term_width):
rows = (('pep', 'per', 'row',
'', 'lon', 'e'))
self.assertCountEqual(self.output._col_widths(rows), (-38, -37, -1))
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.cli.output.P_', dnf.pycomp.NullTranslations().ungettext)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_list_transaction(self, _real_term_width):
return
sack = self.base.sack
q = sack.query().filter(name='pepper')
i = q.installed()[0]
u = q.available()[0]
obs = sack.query().filter(name='hole').installed()[0]
transaction = dnf.transaction.Transaction()
transaction.add_upgrade(u, i, [obs])
self.assertEqual(self.output.list_transaction(transaction),
LIST_TRANSACTION_OUTPUT)
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.i18n.ucd_input')
def test_userconfirm(self, input_fnc):
# with defaultyes==False
input_fnc.return_value = 'y'
self.assertTrue(self.output.userconfirm())
self.assertEqual(input_fnc.call_args, mock.call(u'Is this ok [y/N]: '))
input_fnc.return_value = 'n'
self.assertFalse(self.output.userconfirm())
input_fnc.return_value = ''
self.assertFalse(self.output.userconfirm())
input_fnc.side_effect = self._keyboard_interrupt
input_fnc.return_value = 'y'
self.assertFalse(self.output.userconfirm())
input_fnc.side_effect = self._eof_error
self.assertFalse(self.output.userconfirm())
# with defaultyes==True
self.output.conf.defaultyes = True
input_fnc.side_effect = None
input_fnc.return_value = ''
self.assertTrue(self.output.userconfirm())
input_fnc.side_effect = self._keyboard_interrupt
input_fnc.return_value = ''
self.assertFalse(self.output.userconfirm())
input_fnc.side_effect = self._eof_error
self.assertTrue(self.output.userconfirm())
def _to_unicode_mock(str):
return {'y': 'a', 'yes': 'ano', 'n': 'e', 'no': 'ee'}.get(str, str)
@mock.patch('dnf.cli.output._', _to_unicode_mock)
@mock.patch('dnf.i18n.ucd_input')
def test_userconfirm_translated(self, input_fnc):
input_fnc.return_value = 'ee'
self.assertFalse(self.output.userconfirm())
input_fnc.return_value = 'ano'
self.assertTrue(self.output.userconfirm())
class _InputGenerator(object):
INPUT = ['haha', 'dada', 'n']
def __init__(self):
self.called = 0
def __call__(self, msg):
ret = self.INPUT[self.called]
self.called += 1
return ret
def test_userconfirm_bad_input(self):
input_fnc = self._InputGenerator()
with mock.patch('dnf.i18n.ucd_input', input_fnc):
self.assertFalse(self.output.userconfirm())
self.assertEqual(input_fnc.called, 3)
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_infoOutput_with_none_description(self, _real_term_width):
pkg = tests.support.MockPackage('tour-5-0.noarch')
pkg._from_system = False
pkg._size = 0
pkg._pkgid = None
pkg.repoid = None
pkg.e = pkg.epoch = 1
pkg.v = pkg.version
pkg.r = pkg.release
pkg.sourcerpm = 'tour.src.rpm'
pkg.summary = 'A summary of the package.'
pkg.url = 'http://example.com'
pkg.license = 'GPL+'
pkg.description = None
with mock.patch('sys.stdout') as stdout:
print(self.output.infoOutput(pkg))
written = ''.join([mc[1][0] for mc in stdout.method_calls
if mc[0] == 'write'])
self.assertEqual(written, INFOOUTPUT_OUTPUT)
PKGS_IN_GROUPS_OUTPUT = u"""\
Group: Pepper's
Mandatory Packages:
hole
lotus
"""
PKGS_IN_GROUPS_VERBOSE_OUTPUT = u"""\
Group: Pepper's
Group-Id: Peppers
Mandatory Packages:
hole-1-1.x86_64 @System
lotus-3-16.i686 main
"""
GROUPS_IN_ENVIRONMENT_OUTPUT = """\
Environment Group: Sugar Desktop Environment
Description: A software playground for learning about learning.
Mandatory Groups:
Pepper's
Solid Ground
Optional Groups:
Base
"""
class GroupOutputTest(tests.support.DnfBaseTestCase):
REPOS = ['main']
COMPS = True
def setUp(self):
super(GroupOutputTest, self).setUp()
self.output = dnf.cli.output.Output(self.base, self.base.conf)
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_group_info(self, _real_term_width):
group = self.base.comps.group_by_pattern('Peppers')
with tests.support.patch_std_streams() as (stdout, stderr):
self.output.display_pkgs_in_groups(group)
self.assertEqual(stdout.getvalue(), PKGS_IN_GROUPS_OUTPUT)
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_group_verbose_info(self, _real_term_width):
group = self.base.comps.group_by_pattern('Peppers')
self.base.set_debuglevel(dnf.const.VERBOSE_LEVEL)
with tests.support.patch_std_streams() as (stdout, stderr):
self.output.display_pkgs_in_groups(group)
self.assertEqual(stdout.getvalue(), PKGS_IN_GROUPS_VERBOSE_OUTPUT)
@mock.patch('dnf.cli.output._', dnf.pycomp.NullTranslations().ugettext)
@mock.patch('dnf.cli.term._real_term_width', return_value=80)
def test_environment_info(self, _real_term_width):
env = self.base.comps.environments[0]
with tests.support.patch_std_streams() as (stdout, stderr):
self.output.display_groups_in_environment(env)
self.assertEqual(stdout.getvalue(), GROUPS_IN_ENVIRONMENT_OUTPUT)