summaryrefslogtreecommitdiffstats
path: root/test/TestNestedJinjaRule.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/TestNestedJinjaRule.py')
-rw-r--r--test/TestNestedJinjaRule.py208
1 files changed, 208 insertions, 0 deletions
diff --git a/test/TestNestedJinjaRule.py b/test/TestNestedJinjaRule.py
new file mode 100644
index 0000000..f8367b0
--- /dev/null
+++ b/test/TestNestedJinjaRule.py
@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+# Author: Adrián Tóth <adtoth@redhat.com>
+#
+# Copyright (c) 2020, Red Hat, Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from collections import namedtuple
+
+import pytest
+
+from ansiblelint.runner import Runner
+
+PlayFile = namedtuple('PlayFile', ['name', 'content'])
+
+
+FAIL_TASK_1LN = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: one-level nesting
+ set_fact:
+ var_one: "2*(1+2) is {{ 2 * {{ 1 + 2 }} }}"
+''')
+
+FAIL_TASK_1LN_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: one-level multiline nesting
+ set_fact:
+ var_one_ml: >
+ 2*(1+2) is {{ 2 *
+ {{ 1 + 2 }}
+ }}
+''')
+
+FAIL_TASK_2LN = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: two-level nesting
+ set_fact:
+ var_two: "2*(1+(3-1)) is {{ 2 * {{ 1 + {{ 3 - 1 }} }} }}"
+''')
+
+FAIL_TASK_2LN_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: two-level multiline nesting
+ set_fact:
+ var_two_ml: >
+ 2*(1+(3-1)) is {{ 2 *
+ {{ 1 +
+ {{ 3 - 1 }}
+ }} }}
+''')
+
+FAIL_TASK_W_5LN = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: five-level wild nesting
+ set_fact:
+ var_three_wld: "{{ {{ {{ {{ {{ 234 }} }} }} }} }}"
+''')
+
+FAIL_TASK_W_5LN_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: five-level wild multiline nesting
+ set_fact:
+ var_three_wld_ml: >
+ {{
+ {{
+ {{
+ {{
+ {{ 234 }}
+ }}
+ }}
+ }}
+ }}
+''')
+
+SUCCESS_TASK_P = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: non-nested example
+ set_fact:
+ var_one: "number for 'one' is {{ 2 * 1 }}"
+''')
+
+SUCCESS_TASK_P_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: multiline non-nested example
+ set_fact:
+ var_one_ml: >
+ number for 'one' is {{
+ 2 * 1 }}
+''')
+
+SUCCESS_TASK_2P = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: nesting far from each other
+ set_fact:
+ var_two: "number for 'two' is {{ 2 * 1 }} and number for 'three' is {{ 4 - 1 }}"
+''')
+
+SUCCESS_TASK_2P_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: multiline nesting far from each other
+ set_fact:
+ var_two_ml: >
+ number for 'two' is {{ 2 * 1
+ }} and number for 'three' is {{
+ 4 - 1 }}
+''')
+
+SUCCESS_TASK_C_2P = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: nesting close to each other
+ set_fact:
+ var_three: "number for 'ten' is {{ 2 - 1 }}{{ 3 - 3 }}"
+''')
+
+SUCCESS_TASK_C_2P_M = PlayFile('playbook.yml', '''
+- hosts: all
+ tasks:
+ - name: multiline nesting close to each other
+ set_fact:
+ var_three_ml: >
+ number for 'ten' is {{
+ 2 - 1
+ }}{{ 3 - 3 }}
+''')
+
+
+@pytest.fixture
+def runner(tmp_path, default_rules_collection):
+ return Runner(
+ default_rules_collection,
+ str(tmp_path / 'playbook.yml'),
+ [], [], [],
+ )
+
+
+@pytest.fixture
+def _playbook_file(tmp_path, request):
+ if request.param is None:
+ return
+ for play_file in request.param:
+ p = tmp_path / play_file.name
+ p.write_text(play_file.content)
+
+
+@pytest.mark.parametrize(
+ '_playbook_file',
+ (
+ pytest.param([FAIL_TASK_1LN], id='file includes one-level nesting'),
+ pytest.param([FAIL_TASK_1LN_M], id='file includes one-level multiline nesting'),
+ pytest.param([FAIL_TASK_2LN], id='file includes two-level nesting'),
+ pytest.param([FAIL_TASK_2LN_M], id='file includes two-level multiline nesting'),
+ pytest.param([FAIL_TASK_W_5LN], id='file includes five-level wild nesting'),
+ pytest.param([FAIL_TASK_W_5LN_M], id='file includes five-level wild multiline nesting'),
+ ),
+ indirect=['_playbook_file'],
+)
+@pytest.mark.usefixtures('_playbook_file')
+def test_including_wrong_nested_jinja(runner):
+ rule_violations = runner.run()
+ assert rule_violations[0].rule.id == '207'
+
+
+@pytest.mark.parametrize(
+ '_playbook_file',
+ (
+ pytest.param([SUCCESS_TASK_P], id='file includes non-nested example'),
+ pytest.param([SUCCESS_TASK_P_M], id='file includes multiline non-nested example'),
+ pytest.param([SUCCESS_TASK_2P], id='file includes nesting far from each other'),
+ pytest.param([SUCCESS_TASK_2P_M], id='file includes multiline nesting far from each other'),
+ pytest.param([SUCCESS_TASK_C_2P], id='file includes nesting close to each other'),
+ pytest.param(
+ [SUCCESS_TASK_C_2P_M],
+ id='file includes multiline nesting close to each other',
+ ),
+ ),
+ indirect=['_playbook_file'],
+)
+@pytest.mark.usefixtures('_playbook_file')
+def test_including_proper_nested_jinja(runner):
+ rule_violations = runner.run()
+ assert not rule_violations