diff --git a/Makefile b/Makefile index bd3fdc38f1744ebbf6d3f960e811a905e74cb3fa..8f766c5661c008dd1b2be772b52d0b3d7f8e9e33 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,8 @@ VALIDS = \ format-sr-results-schema.yaml__format-sr-results.yaml \ guid-tool-schema.yaml__guid-tool.yaml \ identify-schema.yaml__identify.yaml \ - identify-schema.yaml__tests/data/test-check-sr-results/identify.yaml + identify-schema.yaml__tests/data/test-check-sr-results/identify.yaml \ + boot_sources_result_schema.yaml__boot_sources_result.yaml VALID_TARGETS = $(addsuffix .valid,$(VALIDS)) @@ -48,7 +49,6 @@ test: $(TEST_TARGETS) ./validate.py --schema schemas/$(word 1,$(subst __, ,$@)) \ $(subst .valid,,$(word 2,$(subst __, ,$@))) - valid: $(VALID_TARGETS) # Sequential (small) tests. diff --git a/boot_sources_result.py b/boot_sources_result.py new file mode 100755 index 0000000000000000000000000000000000000000..5bb73a9d18a7792fdcc3bc0247caa88222dd55cf --- /dev/null +++ b/boot_sources_result.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python3 + +import argparse +import logging +import os +import re +import sys +from typing import Any, Dict, List, Optional, cast + +import jsonschema +import yaml + +DbType = Dict[str, Any] +ResType = List[Dict[str, Any]] # Now each device result is a dictionary + + +# Load YAML diagnostics database and validate against schema +def load_diagnostics_db(config_filename: str, schema_filename: str) -> DbType: + logging.debug(f"Loading configuration file `{config_filename}`") + logging.debug(f"Loading schema file `{schema_filename}`") + + # Check if the schema file exists + if not os.path.isfile(schema_filename): + logging.error(f"Schema file `{schema_filename}` does not exist") + sys.exit(1) + + # Load the schema from the schema file + with open(schema_filename, 'r') as schemafile: + try: + schema = cast(Dict[str, Any], yaml.safe_load(schemafile)) + except yaml.YAMLError as err: + logging.error( + f"Error parsing schema file `{schema_filename}`: {err}" + ) + sys.exit(1) + + # Check if the configuration file exists + if not os.path.isfile(config_filename): + logging.error(f"Configuration file `{config_filename}` does not exist") + sys.exit(1) + + # Load the configuration file + with open(config_filename, 'r') as yamlfile: + try: + db = cast(DbType, yaml.safe_load(yamlfile)) + except yaml.YAMLError as err: + logging.error( + f"Error parsing configuration file `{config_filename}`: {err}" + ) + sys.exit(1) + + # Validate the configuration against the schema + try: + jsonschema.validate(instance=db, schema=schema) + except jsonschema.exceptions.ValidationError as err: + logging.error(f"YAML file validation error: {err.message}") + sys.exit(1) + + logging.debug(f"YAML contents: {db}") + return db + + +# Detect block devices based on the log file +def detect_block_devices(log_path: str) -> int: + device_pattern = re.compile(r'INFO: Block device : /dev/\w+') + device_count = 0 + with open(log_path, 'r') as log_file: + for line in log_file: + if device_pattern.search(line): + device_count += 1 + logging.debug(f"Block devices detected: {device_count}") + return device_count + + +# Parse the log file to extract diagnostics results +def parse_diagnostics_log(log_path: str, device_results: ResType) -> None: + partition_pattern = re.compile(r'INFO: Partition table type : GPT|MBR') + read_pattern_success = re.compile( + r'INFO: Block read on /dev/\w+.*successful' + ) + read_pattern_fail = re.compile( + r'INFO: Block read on /dev/\w+.*failed' + ) + write_pattern_pass = re.compile( + r'INFO: write check passed on /dev/\w+' + ) + write_pattern_fail = re.compile( + r'INFO: write check failed on /dev/\w+' + ) + write_prompt_pattern = re.compile( + r'Do you want to perform a write check on /dev/\w+\?' + ) + + current_device_results: Dict[str, str] = {} + awaiting_write_check: bool = False + + with open(log_path, 'r') as log_file: + for line in log_file: + # Detect block device and process results for the previous device + if re.search(r'INFO: Block device : /dev/\w+', line): + logging.debug(f"Detected device: {line.strip()}") + if current_device_results: + # Ensure 'read' is only set to 'FAIL' + if 'read' not in current_device_results: + current_device_results['read'] = 'FAIL' + if awaiting_write_check: + current_device_results['write'] = 'SKIPPED' + # Add the results for the previous device + device_results.append(current_device_results) + current_device_results = {} # Reset for the next device + awaiting_write_check = False + + # Check partition table + if partition_pattern.search(line): + logging.debug(f"Partition table found: {line.strip()}") + current_device_results['partition_table'] = 'PASS' + elif re.search(r'INFO: Invalid partition table', line): + logging.debug(f"Invalid partition table: {line.strip()}") + current_device_results['partition_table'] = 'FAIL' + + # Check block read success/failure + if read_pattern_success.search(line): + logging.debug(f"Block read success: {line.strip()}") + current_device_results['read'] = 'PASS' + elif read_pattern_fail.search(line): + logging.debug(f"Block read failure: {line.strip()}") + current_device_results['read'] = 'FAIL' + + # Detect prompt for write check + if write_prompt_pattern.search(line): + logging.debug(f"Write check prompt detected: {line.strip()}") + awaiting_write_check = True + + # Check write check success/failure + if write_pattern_pass.search(line): + logging.debug(f"Write check success: {line.strip()}") + current_device_results['write'] = 'PASS' + awaiting_write_check = False + elif write_pattern_fail.search(line): + logging.debug(f"Write check failure: {line.strip()}") + current_device_results['write'] = 'FAIL' + awaiting_write_check = False + + # Handle the last device in the log if not already processed + if current_device_results: + if awaiting_write_check: + current_device_results['write'] = 'SKIPPED' + if 'read' not in current_device_results: + current_device_results['read'] = 'FAIL' + device_results.append(current_device_results) + + logging.debug(f"Parsed device results: {device_results}") + + +# Apply criteria from the YAML to the parsed log results +def apply_criteria( + db: DbType, num_devices: int, device_results: ResType +) -> str: + logging.debug('Applying criterias from the database') + num_pass_devices = 0 + num_fail_devices = 0 + + for ir in device_results: + if not ir: + logging.error(f"Skipping incomplete result: {ir}") + continue + + found_match = False + + # Iterate over the YAML criteria and match results + for ii in db['criterias']: + yaml_criteria = ii['results'][0] + + # Check all fields in yaml_criteria against ir + if all( + key in ir and ir[key] == yaml_criteria.get(key) + for key in yaml_criteria + ): + logging.debug(f"Match found: {ir}") + ir['result'] = ii['criteria'] + ir['quality'] = ii['quality'] + ir['recommendation'] = ii['recommendation'] + found_match = True + + if ii['criteria'] == 'PASS': + num_pass_devices += 1 + else: + num_fail_devices += 1 + + break # Stop checking other criteria once a match is found + + if not found_match: + logging.error(f"No validating match found for: {ir}") + + # Final result: If at least num_devices passed, result is PASS + if num_pass_devices >= num_devices: + result = 'PASS' + if num_pass_devices > num_devices: + logging.info( + f"More devices passed ({num_pass_devices}) " + f"than expected ({num_devices})." + ) + else: + result = 'FAIL' + + logging.info( + f"Block-device-diagnostics passed for {num_pass_devices} " + f"and requested {num_devices}" + ) + return result + + +# Function to find the schema file +def find_schema_file(filename: str) -> Optional[str]: + me = os.path.realpath(__file__) + directories = [ + os.path.join(os.path.dirname(me), 'schemas'), + os.path.join(os.path.dirname(os.path.dirname(me)), 'schemas'), + os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(me))), 'schemas' + ), + ] + for schema_dir in directories: + schema_file = os.path.join(schema_dir, filename) + if os.path.isfile(schema_file): + return schema_file + return None + + +if __name__ == "__main__": + me = os.path.realpath(__file__) + here = os.path.dirname(me) + + parser = argparse.ArgumentParser( + description='Parse Block Device Diagnostics logs.', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument( + '--config', + help='Configuration filename', + default=f"{here}/boot_sources_result.yaml" + ) + parser.add_argument( + '--schema', + help=( + 'Schema filename. If not provided, the script will search ' + 'for it automatically.' + ), + default=None + ) + parser.add_argument( + '--debug', action='store_true', help='Turn on debug messages' + ) + parser.add_argument( + 'log', help="Input log filename" + ) + parser.add_argument( + 'num_devices', type=int, + help='Number of block devices expected to pass' + ) + args = parser.parse_args() + + logging.basicConfig( + format='%(levelname)s %(funcName)s: %(message)s', + level=logging.DEBUG if args.debug else logging.INFO + ) + + if args.schema is None: + args.schema = find_schema_file('boot_sources_result_schema.yaml') + if args.schema is None: + logging.error( + 'Schema file boot_sources_result_schema.yaml ' + 'not found in schema directories' + ) + sys.exit(1) + + db = load_diagnostics_db(args.config, args.schema) + num_actual_devices = detect_block_devices(args.log) + num_expected_devices = args.num_devices + + device_results: ResType = [] + parse_diagnostics_log(args.log, device_results) + + result = apply_criteria(db, num_expected_devices, device_results) + + logging.info(f'Block device diagnostics result is: {result}') + if result == "PASS": + sys.exit(0) + else: + sys.exit(1) diff --git a/boot_sources_result.yaml b/boot_sources_result.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cbc3723009003988276723d3f1c434fb030817c2 --- /dev/null +++ b/boot_sources_result.yaml @@ -0,0 +1,39 @@ +############################################################################### +# boot_sources_result.py configuration file # +############################################################################### +--- + +criterias: + - results: + - partition_table: 'PASS' + read: 'PASS' + write: 'PASS' + criteria: 'PASS' + quality: 'BEST' + recommendation: 'All tests passed. Block device is in excellent condition.' + - results: + - partition_table: 'PASS' + read: 'PASS' + write: 'FAIL' + criteria: 'FAIL' + quality: 'BAD' + recommendation: 'Write check failed. Check block device.' + - results: + - partition_table: 'PASS' + read: 'PASS' + write: 'SKIPPED' + criteria: 'PASS' + quality: 'OK' + recommendation: 'Write check was skipped. Device appears fine but + needs further review.' + - results: + - partition_table: 'PASS' + read: 'FAIL' + criteria: 'FAIL' + quality: 'POOR' + recommendation: 'Read check failed. Check block device.' + - results: + - partition_table: 'FAIL' + criteria: 'FAIL' + quality: 'BAD' + recommendation: 'Partition table is invalid or not found.' diff --git a/schemas/boot_sources_result_schema.yaml b/schemas/boot_sources_result_schema.yaml new file mode 100644 index 0000000000000000000000000000000000000000..87ed3eed9b959c4fcd9787ef192d7e089c417585 --- /dev/null +++ b/schemas/boot_sources_result_schema.yaml @@ -0,0 +1,48 @@ +--- +$id: "https://gitlab.arm.com/systemready/systemready-scripts/-/raw/master/\ + schemas/boot_sources_result_schema.yaml" +$schema: https://json-schema.org/draft/2020-12/schema +title: Boot sources results post processing schema +description: | + This schema is used by script which processes read_write_block_devices logs + in systemready and give pass and fail on basis of boot_sources_result.py + + This schema describes requirements on the configuration file. It can be + used by the valid.py script. + + See the README for details. + +type: object +properties: + criterias: + type: array + items: + type: object + properties: + results: + type: array + items: + type: object + properties: + partition_table: + type: string + read: + type: string + write: + type: string + additionalProperties: false + criteria: + type: string + quality: + type: string + recommendation: + type: string + required: + - results + - criteria + - quality + - recommendation + additionalProperties: false +required: + - criterias +additionalProperties: false diff --git a/tests/data/test-boot-sources/read_write_check_blk_devices.log b/tests/data/test-boot-sources/read_write_check_blk_devices.log new file mode 100644 index 0000000000000000000000000000000000000000..a83c569ae5646c146f2515cef1ef73867654d67e --- /dev/null +++ b/tests/data/test-boot-sources/read_write_check_blk_devices.log @@ -0,0 +1,136 @@ +******************************************************************************************************************************** + + Read block devices tool + +******************************************************************************************************************************** +INFO: Detected following block devices with lsblk command : +0: ram0 +1: ram1 +2: ram2 +3: ram3 +4: ram4 +5: ram5 +6: ram6 +7: ram7 +8: ram8 +9: ram9 +10: ram10 +11: ram11 +12: ram12 +13: ram13 +14: ram14 +15: ram15 +16: mtdblock0 +17: vda +18: vdb + +******************************************************************************************************************************** + +INFO: Block device : /dev/ram0 +INFO: Invalid partition table or not found for ram0 +INFO: Block device : /dev/ram1 +INFO: Invalid partition table or not found for ram1 +INFO: Block device : /dev/ram2 +INFO: Invalid partition table or not found for ram2 +INFO: Block device : /dev/ram3 +INFO: Invalid partition table or not found for ram3 +INFO: Block device : /dev/ram4 +INFO: Invalid partition table or not found for ram4 +INFO: Block device : /dev/ram5 +INFO: Invalid partition table or not found for ram5 +INFO: Block device : /dev/ram6 +INFO: Invalid partition table or not found for ram6 +INFO: Block device : /dev/ram7 +INFO: Invalid partition table or not found for ram7 +INFO: Block device : /dev/ram8 +INFO: Invalid partition table or not found for ram8 +INFO: Block device : /dev/ram9 +INFO: Invalid partition table or not found for ram9 +INFO: Block device : /dev/ram10 +INFO: Invalid partition table or not found for ram10 +INFO: Block device : /dev/ram11 +INFO: Invalid partition table or not found for ram11 +INFO: Block device : /dev/ram12 +INFO: Invalid partition table or not found for ram12 +INFO: Block device : /dev/ram13 +INFO: Invalid partition table or not found for ram13 +INFO: Block device : /dev/ram14 +INFO: Invalid partition table or not found for ram14 +INFO: Block device : /dev/ram15 +INFO: Invalid partition table or not found for ram15 +INFO: Block device : /dev/mtdblock0 +INFO: Invalid partition table or not found for mtdblock0 +INFO: Block device : /dev/vda +INFO: Partition table type : GPT + + +INFO: Partition : /dev/vda1 Partition type GUID : C12A7328-F81F-11D2-BA4B-00A0C93EC93B "Platform required bit" : 0 +INFO: vda1 partition is PRECIOUS. +INFO: Number of 512B blocks used on /dev/vda1: (132552, 174304) + EFI System partition : C12A7328-F81F-11D2-BA4B-00A0C93EC93B + Skipping block read/write... + +INFO: Partition : /dev/vda2 Partition type GUID : 0FC63DAF-8483-4772-8E79-3D69D8477DE4 "Platform required bit" : 0 +INFO: Performing block read on /dev/vda2 part_guid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 +INFO: Block read on /dev/vda2 part_guid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 successful +Do you want to perform a write check on /dev/vda2? (yes/no): yes +INFO: Creating backup of the current block before write check... +1+0 records in +1+0 records out +512 bytes copied, 0.000566366 s, 904 kB/s +INFO: Writing test data to the device for write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00111092 s, 461 kB/s +INFO: Reading back the test data for verification... +1+0 records in +1+0 records out +512 bytes copied, 0.000566845 s, 903 kB/s +Original SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +Read-back SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +INFO: write check passed on /dev/vda2. +INFO: Restoring the backup to the device after write check... +1+0 records in +1+0 records out +512 bytes copied, 0.000530221 s, 966 kB/s +INFO: Backup restored for /dev/vda2. + +******************************************************************************************************************************** + +INFO: Block device : /dev/vdb +[ 336.395849] vdb: vdb1 vdb2 +INFO: Partition table type : GPT + + +INFO: Partition : /dev/vdb1 Partition type GUID : C12A7328-F81F-11D2-BA4B-00A0C93EC93B "Platform required bit" : 0 +INFO: vdb1 partition is PRECIOUS. +INFO: Number of 512B blocks used on /dev/vdb1: (0, 869816) + EFI System partition : C12A7328-F81F-11D2-BA4B-00A0C93EC93B + Skipping block read/write... + +INFO: Partition : /dev/vdb2 Partition type GUID : B921B045-1DF0-41C3-AF44-4C6F280D3FAE "Platform required bit" : 0 +INFO: Performing block read on /dev/vdb2 part_guid = B921B045-1DF0-41C3-AF44-4C6F280D3FAE +INFO: Block read on /dev/vdb2 part_guid = B921B045-1DF0-41C3-AF44-4C6F280D3FAE successful +Do you want to perform a write check on /dev/vdb2? (yes/no): yes +INFO: Creating backup of the current block before write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00120164 s, 426 kB/s +INFO: Writing test data to the device for write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00179417 s, 285 kB/s +INFO: Reading back the test data for verification... +1+0 records in +1+0 records out +512 bytes copied, 0.00102902 s, 498 kB/s +Original SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +Read-back SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +INFO: write check passed on /dev/vdb2. +INFO: Restoring the backup to the device after write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00139487 s, 367 kB/s +INFO: Backup restored for /dev/vdb2. + +******************************************************************************************************************************** \ No newline at end of file diff --git a/tests/data/test-boot-sources/read_write_check_blk_devices_FAIL.log b/tests/data/test-boot-sources/read_write_check_blk_devices_FAIL.log new file mode 100644 index 0000000000000000000000000000000000000000..ac01c7ca885dfa7e6322010c596a54b7ada5d075 --- /dev/null +++ b/tests/data/test-boot-sources/read_write_check_blk_devices_FAIL.log @@ -0,0 +1,136 @@ +******************************************************************************************************************************** + + Read block devices tool + +******************************************************************************************************************************** +INFO: Detected following block devices with lsblk command : +0: ram0 +1: ram1 +2: ram2 +3: ram3 +4: ram4 +5: ram5 +6: ram6 +7: ram7 +8: ram8 +9: ram9 +10: ram10 +11: ram11 +12: ram12 +13: ram13 +14: ram14 +15: ram15 +16: mtdblock0 +17: vda +18: vdb + +******************************************************************************************************************************** + +INFO: Block device : /dev/ram0 +INFO: Invalid partition table or not found for ram0 +INFO: Block device : /dev/ram1 +INFO: Invalid partition table or not found for ram1 +INFO: Block device : /dev/ram2 +INFO: Invalid partition table or not found for ram2 +INFO: Block device : /dev/ram3 +INFO: Invalid partition table or not found for ram3 +INFO: Block device : /dev/ram4 +INFO: Invalid partition table or not found for ram4 +INFO: Block device : /dev/ram5 +INFO: Invalid partition table or not found for ram5 +INFO: Block device : /dev/ram6 +INFO: Invalid partition table or not found for ram6 +INFO: Block device : /dev/ram7 +INFO: Invalid partition table or not found for ram7 +INFO: Block device : /dev/ram8 +INFO: Invalid partition table or not found for ram8 +INFO: Block device : /dev/ram9 +INFO: Invalid partition table or not found for ram9 +INFO: Block device : /dev/ram10 +INFO: Invalid partition table or not found for ram10 +INFO: Block device : /dev/ram11 +INFO: Invalid partition table or not found for ram11 +INFO: Block device : /dev/ram12 +INFO: Invalid partition table or not found for ram12 +INFO: Block device : /dev/ram13 +INFO: Invalid partition table or not found for ram13 +INFO: Block device : /dev/ram14 +INFO: Invalid partition table or not found for ram14 +INFO: Block device : /dev/ram15 +INFO: Invalid partition table or not found for ram15 +INFO: Block device : /dev/mtdblock0 +INFO: Invalid partition table or not found for mtdblock0 +INFO: Block device : /dev/vda +INFO: Partition table type : GPT + + +INFO: Partition : /dev/vda1 Partition type GUID : C12A7328-F81F-11D2-BA4B-00A0C93EC93B "Platform required bit" : 0 +INFO: vda1 partition is PRECIOUS. +INFO: Number of 512B blocks used on /dev/vda1: (132552, 174304) + EFI System partition : C12A7328-F81F-11D2-BA4B-00A0C93EC93B + Skipping block read/write... + +INFO: Partition : /dev/vda2 Partition type GUID : 0FC63DAF-8483-4772-8E79-3D69D8477DE4 "Platform required bit" : 0 +INFO: Performing block read on /dev/vda2 part_guid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 +INFO: Block read on /dev/vda2 part_guid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 successful +Do you want to perform a write check on /dev/vda2? (yes/no): yes +INFO: Creating backup of the current block before write check... +1+0 records in +1+0 records out +512 bytes copied, 0.000566366 s, 904 kB/s +INFO: Writing test data to the device for write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00111092 s, 461 kB/s +INFO: Reading back the test data for verification... +1+0 records in +1+0 records out +512 bytes copied, 0.000566845 s, 903 kB/s +Original SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +Read-back SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +INFO: write check passed on /dev/vda2. +INFO: Restoring the backup to the device after write check... +1+0 records in +1+0 records out +512 bytes copied, 0.000530221 s, 966 kB/s +INFO: Backup restored for /dev/vda2. + +******************************************************************************************************************************** + +INFO: Block device : /dev/vdb +[ 336.395849] vdb: vdb1 vdb2 +INFO: Partition table type : GPT + + +INFO: Partition : /dev/vdb1 Partition type GUID : C12A7328-F81F-11D2-BA4B-00A0C93EC93B "Platform required bit" : 0 +INFO: vdb1 partition is PRECIOUS. +INFO: Number of 512B blocks used on /dev/vdb1: (0, 869816) + EFI System partition : C12A7328-F81F-11D2-BA4B-00A0C93EC93B + Skipping block read/write... + +INFO: Partition : /dev/vdb2 Partition type GUID : B921B045-1DF0-41C3-AF44-4C6F280D3FAE "Platform required bit" : 0 +INFO: Performing block read on /dev/vdb2 part_guid = B921B045-1DF0-41C3-AF44-4C6F280D3FAE +INFO: Block read on /dev/vdb2 part_guid = B921B045-1DF0-41C3-AF44-4C6F280D3FAE successful +Do you want to perform a write check on /dev/vdb2? (yes/no): yes +INFO: Creating backup of the current block before write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00120164 s, 426 kB/s +INFO: Writing test data to the device for write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00179417 s, 285 kB/s +INFO: Reading back the test data for verification... +1+0 records in +1+0 records out +512 bytes copied, 0.00102902 s, 498 kB/s +Original SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +Read-back SHA256: 5ba5b889a62d98368222cef5e53305af9da2960ad6ecab48271a293d3337fb92 +INFO: write check failed on /dev/vdb2. +INFO: Restoring the backup to the device after write check... +1+0 records in +1+0 records out +512 bytes copied, 0.00139487 s, 367 kB/s +INFO: Backup restored for /dev/vdb2. + +******************************************************************************************************************************** \ No newline at end of file diff --git a/tests/test-boot-sources b/tests/test-boot-sources new file mode 100755 index 0000000000000000000000000000000000000000..1c1fefdf92bd9e5f9c2d1f33abbc4dac50ea9faf --- /dev/null +++ b/tests/test-boot-sources @@ -0,0 +1,46 @@ +#!/bin/bash +set -eu -o pipefail + +# Unit test for boot_sources_result.py. +# Usage: test-boot-sources [keep] +# Keeps the temporary folder when 'keep' is specified. + +# Redirect all output to a log file in the current folder. +# Keep stdout on fd 3. +bn=$(basename "$0") +log="$bn.log" +exec 3>&1 >"$log" 2>&1 +set -x + +echo -n 'Testing boot_sources_result.py... ' >&3 +trap 'echo "ERROR! (see $log)" >&3' ERR + +# Ensure boot_sources_result.py is in the PATH. +me=$(realpath "$0") +here="${me%/*}" +export PATH="$here/..:$PATH" + +# Create a temporary folder. +if [ "${1:-unset}" == "keep" ]; then + tmp=$(mktemp -d "$(basename "$0").XXX") +else + tmp=$(mktemp -d) + trap 'rm -fr "$tmp"' EXIT +fi + +data="$here/data/$(basename "$0")" +out="$tmp/out" + +# Test 1: Expected number of devices pass. +echo -n 'test 1: Expected number of devices pass' >&3 +boot_sources_result.py "$data/read_write_check_blk_devices.log" 1 --debug |& tee "$out" +grep 'Block device diagnostics result is: PASS' "$out" + +# Test 2: Devices fail to pass the diagnostics. +echo -n ', test 2: Devices fail to pass the diagnostics' >&3 +if boot_sources_result.py "$data/read_write_check_blk_devices_FAIL.log" 2 --debug |& tee "$out"; then + false +fi +grep 'Block device diagnostics result is: FAIL' "$out" + +echo ', ok.' >&3