# -*- coding: utf-8 -*- """ :codeauthor: Nicole Thomas """ from __future__ import absolute_import, print_function, unicode_literals import os import traceback import salt.config import salt.utils.yaml from salt.ext import six from salt.output import display_output from tests.support.case import ShellCase from tests.support.helpers import slowTest from tests.support.mixins import RUNTIME_VARS class OutputReturnTest(ShellCase): """ Integration tests to ensure outputters return their expected format. Tests against situations where the loader might not be returning the right outputter even though it was explicitly requested. """ @slowTest def test_output_json(self): """ Tests the return of json-formatted data """ ret = self.run_call("test.ping --out=json") self.assertIn("{", ret) self.assertIn('"local": true', "".join(ret)) self.assertIn("}", "".join(ret)) @slowTest def test_output_nested(self): """ Tests the return of nested-formatted data """ expected = ["local:", " True"] ret = self.run_call("test.ping --out=nested") self.assertEqual(ret, expected) @slowTest def test_output_quiet(self): """ Tests the return of an out=quiet query """ expected = [] ret = self.run_call("test.ping --out=quiet") self.assertEqual(ret, expected) @slowTest def test_output_pprint(self): """ Tests the return of pprint-formatted data """ expected = ["{u'local': True}"] if six.PY2 else ["{'local': True}"] ret = self.run_call("test.ping --out=pprint") self.assertEqual(ret, expected) @slowTest def test_output_raw(self): """ Tests the return of raw-formatted data """ expected = ["{u'local': True}"] if six.PY2 else ["{'local': True}"] ret = self.run_call("test.ping --out=raw") self.assertEqual(ret, expected) @slowTest def test_output_txt(self): """ Tests the return of txt-formatted data """ expected = ["local: True"] ret = self.run_call("test.ping --out=txt") self.assertEqual(ret, expected) @slowTest def test_output_yaml(self): """ Tests the return of yaml-formatted data """ expected = ["local: true"] ret = self.run_call("test.ping --out=yaml") self.assertEqual(ret, expected) @slowTest def test_output_yaml_namespaced_dict_wrapper(self): """ Tests the ability to dump a NamespacedDictWrapper instance, as used in magic dunders like __grains__ and __pillar__ See https://github.com/saltstack/salt/issues/49269 """ dumped_yaml = "\n".join(self.run_call("grains.items --out=yaml")) loaded_yaml = salt.utils.yaml.safe_load(dumped_yaml) # We just want to check that the dumped YAML loades as a dict with a # single top-level key, we don't care about the real contents. assert isinstance(loaded_yaml, dict) assert list(loaded_yaml) == ["local"] def test_output_unicodebad(self): """ Tests outputter reliability with utf8 """ opts = salt.config.minion_config( os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "minion") ) opts["output_file"] = os.path.join(RUNTIME_VARS.TMP, "outputtest") data = {"foo": {"result": False, "aaa": "azerzaeréééé", "comment": "ééééàààà"}} try: # this should not raises UnicodeEncodeError display_output(data, opts=opts) except Exception: # pylint: disable=broad-except # display trace in error message for debugging on jenkins trace = traceback.format_exc() sentinel = object() old_max_diff = getattr(self, "maxDiff", sentinel) try: self.maxDiff = None self.assertEqual(trace, "") finally: if old_max_diff is sentinel: delattr(self, "maxDiff") else: self.maxDiff = old_max_diff @slowTest def test_output_highstate(self): """ Regression tests for the highstate outputter. Calls a basic state with various flags. Each comparison should be identical when successful. """ # Test basic highstate output. No frills. expected = [ "minion:", " ID: simple-ping", " Function: module.run", " Name: test.ping", " Result: True", " Comment: Module function test.ping executed", " Changes: ", " ret:", " True", "Summary for minion", "Succeeded: 1 (changed=1)", "Failed: 0", "Total states run: 1", ] state_run = self.run_salt('"minion" state.sls simple-ping') for expected_item in expected: self.assertIn(expected_item, state_run) # Test highstate output while also passing --out=highstate. # This is a regression test for Issue #29796 state_run = self.run_salt('"minion" state.sls simple-ping --out=highstate') for expected_item in expected: self.assertIn(expected_item, state_run) # Test highstate output when passing --static and running a state function. # See Issue #44556. state_run = self.run_salt('"minion" state.sls simple-ping --static') for expected_item in expected: self.assertIn(expected_item, state_run) # Test highstate output when passing --static and --out=highstate. # See Issue #44556. state_run = self.run_salt( '"minion" state.sls simple-ping --static --out=highstate' ) for expected_item in expected: self.assertIn(expected_item, state_run) @slowTest def test_output_highstate_falls_back_nested(self): """ Tests outputter when passing --out=highstate with a non-state call. This should fall back to "nested" output. """ expected = ["minion:", " True"] ret = self.run_salt('"minion" test.ping --out=highstate') self.assertEqual(ret, expected) @slowTest def test_static_simple(self): """ Tests passing the --static option with a basic test.ping command. This should be the "nested" output. """ expected = ["minion:", " True"] ret = self.run_salt('"minion" test.ping --static') self.assertEqual(ret, expected)