common.filter 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #!/usr/bin/env bash
  2. #
  3. # Copyright Red Hat
  4. # Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation.
  9. #
  10. # This program is distributed in the hope that it would be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. #
  18. #
  19. # standard filters
  20. #
  21. _filter_date()
  22. {
  23. sed -Ee 's/[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/yyyy-mm-dd hh:mm:ss/'
  24. }
  25. _filter_vmstate_size()
  26. {
  27. sed -E -e 's/[0-9. ]{5} [KMGT]iB/ SIZE/' \
  28. -e 's/[0-9. ]{5} B/ SIZE/'
  29. }
  30. _filter_generated_node_ids()
  31. {
  32. sed -Ee 's/\#block[0-9]{3,}/NODE_NAME/'
  33. }
  34. _filter_qom_path()
  35. {
  36. gsed -e '/Attached to:/s/\device[[0-9]\+\]/device[N]/g'
  37. }
  38. # replace occurrences of the actual TEST_DIR value with TEST_DIR
  39. _filter_testdir()
  40. {
  41. sed -e "s#$TEST_DIR/#TEST_DIR/#g" \
  42. -e "s#$SOCK_DIR/#SOCK_DIR/#g" \
  43. -e "s#SOCK_DIR/fuse-#TEST_DIR/#g"
  44. }
  45. # replace occurrences of the actual IMGFMT value with IMGFMT
  46. _filter_imgfmt()
  47. {
  48. sed -e "s#$IMGFMT#IMGFMT#g"
  49. }
  50. # Replace error message when the format is not supported and delete
  51. # the output lines after the first one
  52. _filter_qemu_img_check()
  53. {
  54. gsed -e '/allocated.*fragmented.*compressed clusters/d' \
  55. -e 's/qemu-img: This image format does not support checks/No errors were found on the image./' \
  56. -e '/Image end offset: [0-9]\+/d'
  57. }
  58. # Removes \r from messages
  59. _filter_win32()
  60. {
  61. gsed -e 's/\r//g'
  62. }
  63. # sanitize qemu-io output
  64. _filter_qemu_io()
  65. {
  66. _filter_win32 | \
  67. gsed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/" \
  68. -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\| Killed\)/:\1/" \
  69. -e "s/qemu-io> //g"
  70. }
  71. # replace occurrences of QEMU_PROG with "qemu"
  72. _filter_qemu()
  73. {
  74. gsed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" \
  75. -e 's#^QEMU [0-9]\+\.[0-9]\+\.[0-9]\+ monitor#QEMU X.Y.Z monitor#' \
  76. -e $'s#\r##' # QEMU monitor uses \r\n line endings
  77. }
  78. # replace problematic QMP output like timestamps
  79. _filter_qmp()
  80. {
  81. _filter_win32 | \
  82. gsed -e 's#\("\(micro\)\?seconds": \)[0-9]\+#\1 TIMESTAMP#g' \
  83. -e 's#^{"QMP":.*}$#QMP_VERSION#' \
  84. -e '/^ "QMP": {\s*$/, /^ }\s*$/ c\' \
  85. -e ' QMP_VERSION'
  86. }
  87. # readline makes HMP command strings so long that git complains
  88. _filter_hmp()
  89. {
  90. gsed -e $'s/^\\((qemu) \\)\\?.*\e\\[D/\\1/g' \
  91. -e $'s/\e\\[K//g'
  92. }
  93. # replace block job offset
  94. _filter_block_job_offset()
  95. {
  96. gsed -e 's/, "offset": [0-9]\+,/, "offset": OFFSET,/'
  97. }
  98. # replace block job len
  99. _filter_block_job_len()
  100. {
  101. gsed -e 's/, "len": [0-9]\+,/, "len": LEN,/g'
  102. }
  103. # replace actual image size (depends on the host filesystem)
  104. _filter_actual_image_size()
  105. {
  106. gsed -s 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
  107. }
  108. # Filename filters for qemu-img create
  109. _filter_img_create_filenames()
  110. {
  111. sed \
  112. -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
  113. -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
  114. -e "s#$TEST_DIR#TEST_DIR#g" \
  115. -e "s#$SOCK_DIR#SOCK_DIR#g" \
  116. -e 's#SOCK_DIR/fuse-#TEST_DIR/#g' \
  117. -e "s#$IMGFMT#IMGFMT#g" \
  118. -e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g'
  119. }
  120. # replace driver-specific options in the "Formatting..." line
  121. _do_filter_img_create()
  122. {
  123. # Split the line into the pre-options part ($filename_part, which
  124. # precedes ", fmt=") and the options part ($options, which starts
  125. # with "fmt=")
  126. # (And just echo everything before the first "^Formatting")
  127. readarray formatting_line < <(gsed -e 's/, fmt=/\n/')
  128. filename_part=${formatting_line[0]}
  129. unset formatting_line[0]
  130. options="fmt=${formatting_line[@]}"
  131. # Set grep_data_file to '\|data_file' to keep it; make it empty
  132. # to drop it.
  133. # We want to drop it if it is part of the global $IMGOPTS, and we
  134. # want to keep it otherwise (if the test specifically wants to
  135. # test data files).
  136. grep_data_file=(-e data_file)
  137. if _get_data_file "$TEST_IMG" > /dev/null; then
  138. grep_data_file=()
  139. fi
  140. filename_part=$(echo "$filename_part" | _filter_img_create_filenames)
  141. # Break the option line before each option (preserving pre-existing
  142. # line breaks by replacing them by \0 and restoring them at the end),
  143. # then filter out the options we want to keep and sort them according
  144. # to some order that all block drivers used at the time of writing
  145. # this function.
  146. options=$(
  147. echo "$options" \
  148. | tr '\n' '\0' \
  149. | gsed -e 's/ \([a-z0-9_.-]*\)=/\n\1=/g' \
  150. | grep -a -e '^fmt' -e '^size' -e '^backing' -e '^preallocation' \
  151. -e '^encryption' "${grep_data_file[@]}" \
  152. | _filter_img_create_filenames \
  153. | sed \
  154. -e 's/^\(fmt\)/0-\1/' \
  155. -e 's/^\(size\)/1-\1/' \
  156. -e 's/^\(backing\)/2-\1/' \
  157. -e 's/^\(data_file\)/3-\1/' \
  158. -e 's/^\(encryption\)/4-\1/' \
  159. -e 's/^\(preallocation\)/8-\1/' \
  160. | LC_ALL=C sort \
  161. | sed -e 's/^[0-9]-//' \
  162. | tr '\n\0' ' \n' \
  163. | sed -e 's/^ *$//' -e 's/ *$//'
  164. )
  165. if [ -n "$options" ]; then
  166. echo "$filename_part, $options"
  167. elif [ -n "$filename_part" ]; then
  168. echo "$filename_part"
  169. fi
  170. }
  171. # Filter qemu-img create output:
  172. # Pipe all ^Formatting lines through _do_filter_img_create, and all
  173. # other lines through _filter_img_create_filenames
  174. _filter_img_create()
  175. {
  176. while read -r line; do
  177. if echo "$line" | grep -q '^Formatting'; then
  178. echo "$line" | _do_filter_img_create
  179. else
  180. echo "$line" | _filter_img_create_filenames
  181. fi
  182. done
  183. }
  184. _filter_img_create_size()
  185. {
  186. gsed -e "s# size=[0-9]\\+# size=SIZE#g"
  187. }
  188. _filter_img_info()
  189. {
  190. if [[ "$1" == "--format-specific" ]]; then
  191. local format_specific=1
  192. shift
  193. else
  194. local format_specific=0
  195. fi
  196. discard=0
  197. regex_json_spec_start='^ *"format-specific": \{'
  198. regex_json_child_start='^ *"children": \['
  199. gsed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \
  200. -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \
  201. -e "s#$TEST_DIR#TEST_DIR#g" \
  202. -e "s#$SOCK_DIR#SOCK_DIR#g" \
  203. -e "s#$IMGFMT#IMGFMT#g" \
  204. -e 's#nbd+unix:///\??socket=SOCK_DIR/nbd#TEST_DIR/t.IMGFMT#g' \
  205. -e 's#SOCK_DIR/fuse-#TEST_DIR/#g' \
  206. -e "/encrypted: yes/d" \
  207. -e "/cluster_size: [0-9]\\+/d" \
  208. -e "/table_size: [0-9]\\+/d" \
  209. -e "/compat: '[^']*'/d" \
  210. -e "/compat6: \\(on\\|off\\)/d" \
  211. -e "s/cid: [0-9]\+/cid: XXXXXXXXXX/" \
  212. -e "/static: \\(on\\|off\\)/d" \
  213. -e "/zeroed_grain: \\(on\\|off\\)/d" \
  214. -e "/subformat: '[^']*'/d" \
  215. -e "/adapter_type: '[^']*'/d" \
  216. -e "/hwversion: '[^']*'/d" \
  217. -e "/lazy_refcounts: \\(on\\|off\\)/d" \
  218. -e "/extended_l2=\\(on\\|off\\)/d" \
  219. -e "/block_size: [0-9]\\+/d" \
  220. -e "/block_state_zero: \\(on\\|off\\)/d" \
  221. -e "/log_size: [0-9]\\+/d" \
  222. -e "s/iters: [0-9]\\+/iters: 1024/" \
  223. -e 's/\(compression type: \)\(zlib\|zstd\)/\1COMPRESSION_TYPE/' \
  224. -e "s/uuid: [-a-f0-9]\\+/uuid: 00000000-0000-0000-0000-000000000000/" | \
  225. while IFS='' read -r line; do
  226. if [[ $discard == 0 ]]; then
  227. if [[ $format_specific == 0 && $line == "Format specific information:" ]]; then
  228. discard=1
  229. elif [[ $line =~ "Child node '/" ]]; then
  230. discard=1
  231. elif [[ $line =~ $regex_json_spec_start ]]; then
  232. discard=2
  233. regex_json_end="^${line%%[^ ]*}\\},? *$"
  234. elif [[ $line =~ $regex_json_child_start ]]; then
  235. discard=2
  236. regex_json_end="^${line%%[^ ]*}\\],? *$"
  237. fi
  238. fi
  239. if [[ $discard == 0 ]]; then
  240. echo "$line"
  241. elif [[ $discard == 1 && ! $line ]]; then
  242. echo
  243. discard=0
  244. elif [[ $discard == 2 && $line =~ $regex_json_end ]]; then
  245. discard=0
  246. fi
  247. done
  248. }
  249. # filter out offsets and file names from qemu-img map; good for both
  250. # human and json output
  251. _filter_qemu_img_map()
  252. {
  253. # Assuming the data_file value in $IMGOPTS contains a '$TEST_IMG',
  254. # create a filter that replaces the data file name by $TEST_IMG.
  255. # Example:
  256. # In $IMGOPTS: 'data_file=$TEST_IMG.data_file'
  257. # Then data_file_pattern == '\(.*\).data_file'
  258. # And data_file_filter == -e 's#\(.*\).data_file#\1#
  259. data_file_filter=()
  260. if data_file_pattern=$(_get_data_file '\\(.*\\)'); then
  261. data_file_filter=(-e "s#$data_file_pattern#\\1#")
  262. fi
  263. sed -e 's/\([0-9a-fx]* *[0-9a-fx]* *\)[0-9a-fx]* */\1/g' \
  264. -e 's/"offset": [0-9]\+/"offset": OFFSET/g' \
  265. -e 's/Mapped to *//' \
  266. "${data_file_filter[@]}" \
  267. | _filter_testdir | _filter_imgfmt
  268. }
  269. _filter_nbd()
  270. {
  271. # nbd.c error messages contain function names and line numbers that are
  272. # prone to change. Message ordering depends on timing between send and
  273. # receive callbacks sometimes, making them unreliable.
  274. #
  275. # Filter out the TCP port number since this changes between runs.
  276. sed -e '/nbd\/.*\.c:/d' \
  277. -e 's#127\.0\.0\.1:[0-9]*#127.0.0.1:PORT#g' \
  278. -e 's#localhost:[0-9]*#localhost:PORT#g' \
  279. -e 's#host=127\.0\.0\.1,port=[0-9]*#host=127.0.0.1,port=PORT#g' \
  280. -e 's#host=localhost,port=[0-9]*#host=localhost,port=PORT#g' \
  281. -e "s#path=$SOCK_DIR#path=SOCK_DIR#g" \
  282. -e "s#?socket=$SOCK_DIR#?socket=SOCK_DIR#g" \
  283. -e 's#\(foo\|PORT/\?\|.sock\): Failed to .*$#\1#'
  284. }
  285. _filter_qemu_nbd_exports()
  286. {
  287. grep '\(exports available\|export\|size\|min block\|qemu-nbd\):'
  288. }
  289. _filter_qmp_empty_return()
  290. {
  291. grep -v '{"return": {}}'
  292. }
  293. _filter_json_filename()
  294. {
  295. $PYTHON -c 'import sys
  296. result, *fnames = sys.stdin.read().split("json:{")
  297. depth = 0
  298. for fname in fnames:
  299. depth += 1 # For the opening brace in the split separator
  300. for chr_i, chr in enumerate(fname):
  301. if chr == "{":
  302. depth += 1
  303. elif chr == "}":
  304. depth -= 1
  305. if depth == 0:
  306. break
  307. # json:{} filenames may be nested; filter out everything from
  308. # inside the outermost one
  309. if depth == 0:
  310. chr_i += 1 # First character past the filename
  311. result += "json:{ /* filtered */ }" + fname[chr_i:]
  312. sys.stdout.write(result)'
  313. }
  314. _filter_authz_check_tls()
  315. {
  316. sed -e 's/TLS x509 authz check for .* is denied/TLS x509 authz check for DISTINGUISHED-NAME is denied/'
  317. }
  318. _filter_qcow2_compression_type_bit()
  319. {
  320. gsed -e 's/\(incompatible_features\s\+\)\[3\(, \)\?/\1[/' \
  321. -e 's/\(incompatible_features.*\), 3\]/\1]/' \
  322. -e 's/\(incompatible_features.*\), 3\(,.*\)/\1\2/'
  323. }
  324. # make sure this script returns success
  325. true