From eca3536b86c4ed942b9337caad89c291fa09fff8 Mon Sep 17 00:00:00 2001 From: Luis Araujo <luis.araujo@collabora.co.uk> Date: Tue, 27 Nov 2018 22:02:13 +0800 Subject: [PATCH] Split the renderer into its own module Signed-off-by: Luis Araujo <luis.araujo@collabora.co.uk> --- renderer/render-test-case | 168 +--------------------------------- renderer/renderer.py | 185 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 164 deletions(-) create mode 100644 renderer/renderer.py diff --git a/renderer/render-test-case b/renderer/render-test-case index 427eb25..ef0a47c 100755 --- a/renderer/render-test-case +++ b/renderer/render-test-case @@ -1,6 +1,6 @@ #!/usr/bin/env python3 ################################################################################### -# Test case renderer. +# render-test-case: Main program to render test case files. # Create a HTML page from a YAML test case file. # # Copyright (C) 2018 @@ -22,174 +22,14 @@ ################################################################################### import os -import sys -import yaml import shutil -from jinja2 import Environment, FileSystemLoader from argparse import ArgumentParser -from parser import parse_format -from exceptions import ParserTypeError, ParserMissingFieldError - -TEMPLATE_DIR="." - -# This command parses each line of a list and returns a structure of the form -# (comment, command, output) to apply the following formatting for the respective -# sections: -# -# pre-conditions: -# notes: -# expected: -# - Start line with '$' for commands. -# - Start line with '>' for command output. -# - Start line with '@' to attach image. -# - Start line with '~' to add web link. -# - Everything else is a comment. -# -# run: steps: (only for automated tests) -# - Start line with '#' for comments , everything else is a command. -# -def parse_list(lines, automated_run=False): - processed_lines = [] - for line in lines: - p, c = '', '' - sline = line.strip() - if not sline: - continue - - if automated_run: - if sline[0] == '#': - # Remove the '#' with the slice [1:] - processed_lines.append((sline[1:], '', '', '', '')) - else: - # Add the '$ ' in the line for the command - processed_lines.append(('', '$ '+sline, '', '', '')) - else: - if sline[0] == '$': - processed_lines.append(('', sline, '', '', '')) - elif sline[0] == '>': - processed_lines.append(('', '', sline[1:].split('\n'), '', '')) - elif sline[0] == '@': - processed_lines.append(('', '', '', sline[1:], '')) - elif sline[0] == '~': - processed_lines.append(('', '', '', '', sline[1:])) - else: - processed_lines.append((sline, '', '', '', '')) - - return processed_lines - -def priority_color(priority): - return \ - (priority == 'low' and 'secondary') or \ - (priority == 'medium' and 'info') or \ - (priority == 'high' and 'warning') or \ - (priority == 'critical' and 'danger') or 'light' - -def get_template_values(testcase_data): - template_values = {} - is_automated = False - - # Mandatory fields - metadata = testcase_data.get('metadata') - if not metadata: - print("Error: missing mandatory field metadata") - sys.exit(1) - - for mv in ['name', 'image-type', 'image-arch', 'type', - 'exec-type', 'priority', 'description', 'expected']: - value = metadata.get(mv) - if value: - if mv == 'exec-type' and value == 'automated': - is_automated = True - if mv == 'expected': - template_values.update({ mv : parse_list(value) }) - else: - # Set the priority_color. - if mv == 'priority': - template_values.update({ 'priority_color' : - priority_color(value) }) - template_values.update({ mv.replace('-', '_') : value }) - else: - print("Error: missing mandatory field", mv) - sys.exit(1) - - run = testcase_data.get('run') - if not run: - print("Error: missing mandatory field run") - sys.exit(1) - else: - steps = run.get('steps') - if not steps: - print("Error: missing mandatory field steps for run") - sys.exit(1) - # 'is_automated' so automated tests steps are parsed differently. - template_values.update({ 'run_steps' : - parse_list(steps, automated_run=is_automated) }) - - # No mandatory fields - for nm in ['notes', 'format', 'maintainer', 'resources', - 'pre-conditions', 'post-conditions']: - value = metadata.get(nm) - if value: - template_values.update({ nm.replace('-', '_') : parse_list(value) - if nm in ['notes', 'pre-conditions', - 'post-conditions'] - else value }) - - install = testcase_data.get('install') - if install: - deps = install.get('deps') - if not deps: - print("Error: missing mandatory field deps for install") - sys.exit(1) - template_values.update({ 'install_steps' : deps }) - # A install.deps directive will always add a preconditions section - # to install the required packages using the macro to install packages. - template_values.update({ 'packages_list' : ' '.join(deps) }) - - # Macros variables - ostree_preconditions = metadata.get('macro_ostree_preconditions') - if ostree_preconditions: - template_values.update({ 'pkgname' : ostree_preconditions }) - - packages_list = metadata.get('macro_install_packages_preconditions') - if packages_list: - template_values.update({ 'packages_list' : packages_list }) - - modules_preconditions = metadata.get('macro_modules_preconditions') - if modules_preconditions: - template_values.update({ 'libname' : modules_preconditions }) - - return template_values - -def generate_test_case(tc_file, directory): - try: - with open(tc_file) as testcase: - tc_data = yaml.safe_load(testcase) - except yaml.scanner.ScannerError as e: - print("yaml format error:", e) - sys.exit(1) - - # Parse file to detect any syntax error. - print("Parsing file", tc_file) - try: - parse_format(tc_data) - except (ParserTypeError, ParserMissingFieldError) as error: - print("Error: " + str(error)) - exit(1) - - env = Environment(loader=FileSystemLoader([TEMPLATE_DIR])) - # Get template from environment and render it. - data = env.get_template('templates/index.html').render(get_template_values(tc_data)) - - filename = os.path.splitext(os.path.basename(tc_file))[0] + ".html" - print("Generating test case page", filename) - with open(os.path.join(directory, filename), 'w') as html_file: - html_file.write(data) +from renderer import generate_test_case if '__main__' == __name__: - cli_parser = ArgumentParser(description="make_page") + cli_parser = ArgumentParser(description="render-test-case") cli_parser.add_argument('-d', '--test-case-dir', help="Directory path for generated test cases") cli_parser.add_argument('yaml_files', @@ -205,7 +45,7 @@ if '__main__' == __name__: print("Directory '{}' already exists".format(directory)) except e: print("Error:", e) - sys.exit(1) + exit(1) if os.path.isfile(args.yaml_files): generate_test_case(args.yaml_files, directory) diff --git a/renderer/renderer.py b/renderer/renderer.py new file mode 100644 index 0000000..8291de5 --- /dev/null +++ b/renderer/renderer.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +################################################################################### +# Test case renderer. +# Create a HTML page from a YAML test case file. +# +# Copyright (C) 2018 +# Luis Araujo <luis.araujo@collabora.co.uk> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 US +################################################################################### + +import os +import yaml +from jinja2 import Environment, FileSystemLoader + +from parser import parse_format +from exceptions import ParserTypeError, ParserMissingFieldError + +TEMPLATE_DIR="." + +# This command parses each line of a list and returns a structure of the form +# (comment, command, output) to apply the following formatting for the respective +# sections: +# +# pre-conditions: +# notes: +# expected: +# - Start line with '$' for commands. +# - Start line with '>' for command output. +# - Start line with '@' to attach image. +# - Start line with '~' to add web link. +# - Everything else is a comment. +# +# run: steps: (only for automated tests) +# - Start line with '#' for comments , everything else is a command. +# +def parse_list(lines, automated_run=False): + processed_lines = [] + for line in lines: + p, c = '', '' + sline = line.strip() + if not sline: + continue + + if automated_run: + if sline[0] == '#': + # Remove the '#' with the slice [1:] + processed_lines.append((sline[1:], '', '', '', '')) + else: + # Add the '$ ' in the line for the command + processed_lines.append(('', '$ '+sline, '', '', '')) + else: + if sline[0] == '$': + processed_lines.append(('', sline, '', '', '')) + elif sline[0] == '>': + processed_lines.append(('', '', sline[1:].split('\n'), '', '')) + elif sline[0] == '@': + processed_lines.append(('', '', '', sline[1:], '')) + elif sline[0] == '~': + processed_lines.append(('', '', '', '', sline[1:])) + else: + processed_lines.append((sline, '', '', '', '')) + + return processed_lines + +def priority_color(priority): + return \ + (priority == 'low' and 'secondary') or \ + (priority == 'medium' and 'info') or \ + (priority == 'high' and 'warning') or \ + (priority == 'critical' and 'danger') or 'light' + +def get_template_values(testcase_data): + template_values = {} + is_automated = False + + # Mandatory fields + metadata = testcase_data.get('metadata') + if not metadata: + print("Error: missing mandatory field metadata") + exit(1) + + for mv in ['name', 'image-type', 'image-arch', 'type', + 'exec-type', 'priority', 'description', 'expected']: + value = metadata.get(mv) + if value: + if mv == 'exec-type' and value == 'automated': + is_automated = True + if mv == 'expected': + template_values.update({ mv : parse_list(value) }) + else: + # Set the priority_color. + if mv == 'priority': + template_values.update({ 'priority_color' : + priority_color(value) }) + template_values.update({ mv.replace('-', '_') : value }) + else: + print("Error: missing mandatory field", mv) + exit(1) + + run = testcase_data.get('run') + if not run: + print("Error: missing mandatory field run") + exit(1) + else: + steps = run.get('steps') + if not steps: + print("Error: missing mandatory field steps for run") + exit(1) + # 'is_automated' so automated tests steps are parsed differently. + template_values.update({ 'run_steps' : + parse_list(steps, automated_run=is_automated) }) + + # No mandatory fields + for nm in ['notes', 'format', 'maintainer', 'resources', + 'pre-conditions', 'post-conditions']: + value = metadata.get(nm) + if value: + template_values.update({ nm.replace('-', '_') : parse_list(value) + if nm in ['notes', 'pre-conditions', + 'post-conditions'] + else value }) + + install = testcase_data.get('install') + if install: + deps = install.get('deps') + if not deps: + print("Error: missing mandatory field deps for install") + exit(1) + template_values.update({ 'install_steps' : deps }) + # A install.deps directive will always add a preconditions section + # to install the required packages using the macro to install packages. + template_values.update({ 'packages_list' : ' '.join(deps) }) + + # Macros variables + ostree_preconditions = metadata.get('macro_ostree_preconditions') + if ostree_preconditions: + template_values.update({ 'pkgname' : ostree_preconditions }) + + packages_list = metadata.get('macro_install_packages_preconditions') + if packages_list: + template_values.update({ 'packages_list' : packages_list }) + + modules_preconditions = metadata.get('macro_modules_preconditions') + if modules_preconditions: + template_values.update({ 'libname' : modules_preconditions }) + + return template_values + +def generate_test_case(tc_file, directory): + try: + with open(tc_file) as testcase: + tc_data = yaml.safe_load(testcase) + except yaml.scanner.ScannerError as e: + print("yaml format error:", e) + exit(1) + + # Parse file to detect any syntax error. + print("Parsing file", tc_file) + try: + parse_format(tc_data) + except (ParserTypeError, ParserMissingFieldError) as error: + print("Error: " + str(error)) + exit(1) + + env = Environment(loader=FileSystemLoader([TEMPLATE_DIR])) + # Get template from environment and render it. + data = env.get_template('templates/index.html').render(get_template_values(tc_data)) + + filename = os.path.splitext(os.path.basename(tc_file))[0] + ".html" + print("Generating test case page", filename) + with open(os.path.join(directory, filename), 'w') as html_file: + html_file.write(data) -- GitLab