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}/Testing/Temporary/${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 67# Cleanup temporary files 68macro(cleanup_always) 69 file(GLOB TEMP_FILES ${OUTPUT_BASE}*) 70 file(REMOVE ${TEMP_FILES}) 71endmacro() 72# Clean up temporary files if not on CI 73macro(cleanup) 74 if(NOT DEFINED ENV{CI}) 75 cleanup_always() 76 endif() 77endmacro() 78 79# Show differences between two files 80macro(diff src1 src2) 81 find_program(XXD xxd) 82 if(XXD) 83 find_program(DIFF diff) 84 if(DIFF) 85 set(XXD_COMMAND ${XXD} ${src1} ${src1}.hex) 86 execute_process(COMMAND ${XXD_COMMAND}) 87 set(XXD_COMMAND ${XXD} ${src2} ${src2}.hex) 88 execute_process(COMMAND ${XXD_COMMAND}) 89 90 set(DIFF_COMMAND ${DIFF} -u ${src1}.hex ${src2}.hex) 91 execute_process(COMMAND ${DIFF_COMMAND} 92 OUTPUT_FILE ${src2}.diff) 93 94 file(READ ${src2}.diff DIFF_OUTPUT) 95 message(STATUS "Diff:\n${DIFF_OUTPUT}") 96 97 if(NOT DEFINED ENV{CI}) 98 file(REMOVE ${src1}.hex ${src2}.hex ${src2}.diff) 99 endif() 100 endif() 101 endif() 102endmacro() 103 104# Compress input file 105if(NOT EXISTS ${INPUT}) 106 message(FATAL_ERROR "Cannot find compress input: ${INPUT}") 107endif() 108 109set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) 110 111message(STATUS "Compress ${COMPRESS_COMMAND}") 112message(STATUS " Input: ${INPUT}") 113message(STATUS " Output: ${OUTPUT_BASE}.gz") 114 115execute_process(COMMAND ${CMAKE_COMMAND} 116 "-DCOMMAND=${COMPRESS_COMMAND}" 117 -DINPUT=${INPUT} 118 -DOUTPUT=${OUTPUT_BASE}.gz 119 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 120 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 121 RESULT_VARIABLE CMD_RESULT) 122 123if(CMD_RESULT) 124 cleanup() 125 message(FATAL_ERROR "Compress failed: ${CMD_RESULT}") 126endif() 127 128# Decompress output 129if(NOT EXISTS ${OUTPUT_BASE}.gz) 130 cleanup() 131 message(FATAL_ERROR "Cannot find decompress input: ${OUTPUT_BASE}.gz") 132endif() 133 134set(DECOMPRESS_COMMAND ${DECOMPRESS_TARGET} ${DECOMPRESS_ARGS}) 135 136message(STATUS "Decompress ${DECOMPRESS_COMMAND}") 137message(STATUS " Input: ${OUTPUT_BASE}.gz") 138message(STATUS " Output: ${OUTPUT_BASE}") 139 140execute_process(COMMAND ${CMAKE_COMMAND} 141 "-DCOMMAND=${DECOMPRESS_COMMAND}" 142 -DINPUT=${OUTPUT_BASE}.gz 143 -DOUTPUT=${OUTPUT_BASE} 144 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 145 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 146 RESULT_VARIABLE CMD_RESULT) 147 148if(CMD_RESULT) 149 cleanup() 150 message(FATAL_ERROR "Decompress failed: ${CMD_RESULT}") 151endif() 152 153if(COMPARE) 154 # Compare decompressed output with original input file 155 execute_process(COMMAND ${CMAKE_COMMAND} 156 -E compare_files ${INPUT} ${OUTPUT_BASE} 157 RESULT_VARIABLE CMD_RESULT) 158 159 if(CMD_RESULT) 160 diff(${INPUT} ${OUTPUT_BASE}) 161 cleanup() 162 message(FATAL_ERROR "Compare decompress failed: ${CMD_RESULT}") 163 endif() 164endif() 165 166if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") 167 # Transparent writing does not use gzip format 168 find_program(GZIP gzip) 169 if(GZIP) 170 if(NOT EXISTS ${OUTPUT_BASE}.gz) 171 cleanup() 172 message(FATAL_ERROR "Cannot find gzip decompress input: ${OUTPUT_BASE}.gz") 173 endif() 174 175 # Check gzip can decompress our compressed output 176 set(GZ_DECOMPRESS_COMMAND ${GZIP} --decompress) 177 178 message(STATUS "Gzip decompress ${GZ_DECOMPRESS_COMMAND}") 179 message(STATUS " Input: ${OUTPUT_BASE}.gz") 180 message(STATUS " Output: ${OUTPUT_BASE}-ungzip") 181 182 execute_process(COMMAND ${CMAKE_COMMAND} 183 "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" 184 -DINPUT=${OUTPUT_BASE}.gz 185 -DOUTPUT=${OUTPUT_BASE}-ungzip 186 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 187 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 188 RESULT_VARIABLE CMD_RESULT) 189 190 if(CMD_RESULT) 191 cleanup() 192 message(FATAL_ERROR "Gzip decompress failed: ${CMD_RESULT}") 193 endif() 194 195 # Compare gzip output with original input file 196 execute_process(COMMAND ${CMAKE_COMMAND} 197 -E compare_files ${INPUT} ${OUTPUT_BASE}-ungzip 198 RESULT_VARIABLE CMD_RESULT) 199 200 if(CMD_RESULT) 201 diff(${INPUT} ${OUTPUT_BASE}-ungzip) 202 cleanup() 203 message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") 204 endif() 205 206 # Compress input file with gzip 207 set(GZ_COMPRESS_COMMAND ${GZIP} --stdout) 208 209 message(STATUS "Gzip compress ${GZ_COMPRESS_COMMAND}") 210 message(STATUS " Input: ${INPUT}") 211 message(STATUS " Output: ${OUTPUT_BASE}-gzip.gz") 212 213 execute_process(COMMAND ${CMAKE_COMMAND} 214 "-DCOMMAND=${GZ_COMPRESS_COMMAND}" 215 -DINPUT=${INPUT} 216 -DOUTPUT=${OUTPUT_BASE}-gzip.gz 217 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 218 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 219 RESULT_VARIABLE CMD_RESULT) 220 221 if(CMD_RESULT) 222 cleanup() 223 message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") 224 endif() 225 226 if(NOT EXISTS ${OUTPUT_BASE}-gzip.gz) 227 cleanup() 228 message(FATAL_ERROR "Cannot find decompress gzip input: ${OUTPUT_BASE}-gzip.gz") 229 endif() 230 231 message(STATUS "Decompress gzip ${DECOMPRESS_COMMAND}") 232 message(STATUS " Input: ${OUTPUT_BASE}-gzip.gz") 233 message(STATUS " Output: ${OUTPUT_BASE}-gzip") 234 235 # Check decompress target can handle gzip compressed output 236 execute_process(COMMAND ${CMAKE_COMMAND} 237 "-DCOMMAND=${DECOMPRESS_COMMAND}" 238 -DINPUT=${OUTPUT_BASE}-gzip.gz 239 -DOUTPUT=${OUTPUT_BASE}-gzip 240 "-DSUCCESS_EXIT=${SUCCESS_EXIT}" 241 -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake 242 RESULT_VARIABLE CMD_RESULT) 243 244 if(CMD_RESULT) 245 cleanup() 246 message(FATAL_ERROR "Decompress gzip failed: ${CMD_RESULT}") 247 endif() 248 249 if(COMPARE) 250 # Compare original input file with gzip decompressed output 251 execute_process(COMMAND ${CMAKE_COMMAND} 252 -E compare_files ${INPUT} ${OUTPUT_BASE}-gzip 253 RESULT_VARIABLE CMD_RESULT) 254 255 if(CMD_RESULT) 256 diff(${INPUT} ${OUTPUT_BASE}-gzip) 257 cleanup() 258 message(FATAL_ERROR "Compare decompress gzip failed: ${CMD_RESULT}") 259 endif() 260 endif() 261 endif() 262endif() 263 264cleanup_always() 265