1# test-compress.cmake -- Runs a test against an input file to make sure that the specified 2# targets are able to to compress and then decompress it successfully. Optionally verify 3# the results with gzip. Output files are generated with unique names to prevent parallel 4# tests from corrupting one another. Default target arguments are compatible with minigzip. 5 6# Copyright (C) 2021 Nathan Moinvaziri 7# Licensed under the Zlib license, see LICENSE.md for details 8 9# that test a specific input file for compression or decompression. 10 11# Required Variables 12# INPUT - Input file to test 13# TARGET or - Command to run for both compress and decompress 14# COMPRESS_TARGET and - Command to run to compress input file 15# DECOMPRESS_TARGET - Command to run to decompress output file 16 17# Optional Variables 18# TEST_NAME - Name of test to use when constructing output file paths 19# COMPRESS_ARGS - Arguments to pass for compress command (default: -c -k) 20# DECOMPRESS_ARGS - Arguments to pass to decompress command (default: -d -c) 21 22# GZIP_VERIFY - Verify that gzip can decompress the COMPRESS_TARGET output and 23# verify that DECOMPRESS_TARGET can decompress gzip output of INPUT 24# COMPARE - Verify decompressed output is the same as input 25# SUCCESS_EXIT - List of successful exit codes (default: 0, ie: 0;1) 26 27if(TARGET) 28 set(COMPRESS_TARGET ${TARGET}) 29 set(DECOMPRESS_TARGET ${TARGET}) 30endif() 31 32if(NOT DEFINED INPUT OR NOT DEFINED COMPRESS_TARGET OR NOT DEFINED DECOMPRESS_TARGET) 33 message(FATAL_ERROR "Compress test arguments missing") 34endif() 35 36# Set default values 37if(NOT DEFINED COMPARE) 38 set(COMPARE ON) 39endif() 40if(NOT DEFINED COMPRESS_ARGS) 41 set(COMPRESS_ARGS -c -k) 42endif() 43if(NOT DEFINED DECOMPRESS_ARGS) 44 set(DECOMPRESS_ARGS -d -c) 45endif() 46if(NOT DEFINED GZIP_VERIFY) 47 set(GZIP_VERIFY ON) 48endif() 49if(NOT DEFINED SUCCESS_EXIT) 50 set(SUCCESS_EXIT 0) 51endif() 52 53# Use test name from input file name 54if(NOT DEFINED TEST_NAME) 55 get_filename_component(TEST_NAME "${INPUT}" NAME) 56endif() 57 58# Generate unique output path so multiple tests can be executed at the same time 59string(RANDOM LENGTH 6 UNIQUE_ID) 60string(REPLACE "." "-" TEST_NAME "${TEST_NAME}") 61set(OUTPUT_BASE "${CMAKE_CURRENT_BINARY_DIR}/test/${TEST_NAME}-${UNIQUE_ID}") 62 63# Ensure directory exists for output files 64get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) 65file(MAKE_DIRECTORY "${OUTPUT_DIR}") 66 67macro(cleanup) 68 # Cleanup temporary mingizip files 69 file(REMOVE ${OUTPUT_BASE}.gz ${OUTPUT_BASE}.out) 70 # Cleanup temporary gzip files 71 file(REMOVE ${OUTPUT_BASE}.gzip.gz ${OUTPUT_BASE}.gzip.out) 72endmacro() 73 74# Compress input file 75if(NOT EXISTS ${INPUT}) 76 message(FATAL_ERROR "Cannot find compress input: ${INPUT}") 77endif() 78 79set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) 80 81execute_process(COMMAND ${CMAKE_COMMAND} 82 "-DCOMMAND=${COMPRESS_COMMAND}" 83 -DINPUT=${INPUT} 84 -DOUTPUT=${OUTPUT_BASE}.gz 85 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 86 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 87 RESULT_VARIABLE CMD_RESULT) 88 89if(CMD_RESULT) 90 cleanup() 91 message(FATAL_ERROR "Compress failed: ${CMD_RESULT}") 92endif() 93 94# Decompress output 95if(NOT EXISTS ${OUTPUT_BASE}.gz) 96 cleanup() 97 message(FATAL_ERROR "Cannot find decompress input: ${OUTPUT_BASE}.gz") 98endif() 99 100set(DECOMPRESS_COMMAND ${DECOMPRESS_TARGET} ${DECOMPRESS_ARGS}) 101 102execute_process(COMMAND ${CMAKE_COMMAND} 103 "-DCOMMAND=${DECOMPRESS_COMMAND}" 104 -DINPUT=${OUTPUT_BASE}.gz 105 -DOUTPUT=${OUTPUT_BASE}.out 106 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 107 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 108 RESULT_VARIABLE CMD_RESULT) 109 110if(CMD_RESULT) 111 cleanup() 112 message(FATAL_ERROR "Decompress failed: ${CMD_RESULT}") 113endif() 114 115if(COMPARE) 116 # Compare decompressed output with original input file 117 execute_process(COMMAND ${CMAKE_COMMAND} 118 -E compare_files ${INPUT} ${OUTPUT_BASE}.out 119 RESULT_VARIABLE CMD_RESULT) 120 121 if(CMD_RESULT) 122 cleanup() 123 message(FATAL_ERROR "Compare minigzip decompress failed: ${CMD_RESULT}") 124 endif() 125endif() 126 127if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") 128 # Transparent writing does not use gzip format 129 find_program(GZIP gzip) 130 if(GZIP) 131 if(NOT EXISTS ${OUTPUT_BASE}.gz) 132 cleanup() 133 message(FATAL_ERROR "Cannot find gzip decompress input: ${OUTPUT_BASE}.gz") 134 endif() 135 136 # Check gzip can decompress our compressed output 137 set(GZ_DECOMPRESS_COMMAND ${GZIP} --decompress) 138 139 execute_process(COMMAND ${CMAKE_COMMAND} 140 "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" 141 -DINPUT=${OUTPUT_BASE}.gz 142 -DOUTPUT=${OUTPUT_BASE}.gzip.out 143 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 144 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 145 RESULT_VARIABLE CMD_RESULT) 146 147 if(CMD_RESULT) 148 cleanup() 149 message(FATAL_ERROR "Gzip decompress failed: ${CMD_RESULT}") 150 endif() 151 152 # Compare gzip output with original input file 153 execute_process(COMMAND ${CMAKE_COMMAND} 154 -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out 155 RESULT_VARIABLE CMD_RESULT) 156 157 if(CMD_RESULT) 158 cleanup() 159 message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") 160 endif() 161 162 if(NOT EXISTS ${OUTPUT_BASE}.gz) 163 cleanup() 164 message(FATAL_ERROR "Cannot find gzip compress input: ${INPUT}") 165 endif() 166 167 # Compress input file with gzip 168 set(GZ_COMPRESS_COMMAND ${GZIP} --stdout) 169 170 execute_process(COMMAND ${CMAKE_COMMAND} 171 "-DCOMMAND=${GZ_COMPRESS_COMMAND}" 172 -DINPUT=${INPUT} 173 -DOUTPUT=${OUTPUT_BASE}.gzip.gz 174 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 175 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 176 RESULT_VARIABLE CMD_RESULT) 177 178 if(CMD_RESULT) 179 cleanup() 180 message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") 181 endif() 182 183 if(NOT EXISTS ${OUTPUT_BASE}.gz) 184 cleanup() 185 message(FATAL_ERROR "Cannot find minigzip decompress input: ${OUTPUT_BASE}.gzip.gz") 186 endif() 187 188 # Check decompress target can handle gzip compressed output 189 execute_process(COMMAND ${CMAKE_COMMAND} 190 "-DCOMMAND=${DECOMPRESS_COMMAND}" 191 -DINPUT=${OUTPUT_BASE}.gzip.gz 192 -DOUTPUT=${OUTPUT_BASE}.gzip.out 193 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 194 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 195 RESULT_VARIABLE CMD_RESULT) 196 197 if(CMD_RESULT) 198 cleanup() 199 message(FATAL_ERROR "Minigzip decompress gzip failed: ${CMD_RESULT}") 200 endif() 201 202 if(COMPARE) 203 # Compare original input file with gzip decompressed output 204 execute_process(COMMAND ${CMAKE_COMMAND} 205 -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out 206 RESULT_VARIABLE CMD_RESULT) 207 208 if(CMD_RESULT) 209 cleanup() 210 message(FATAL_ERROR "Compare minigzip decompress gzip failed: ${CMD_RESULT}") 211 endif() 212 endif() 213 endif() 214endif() 215 216cleanup()