fs-test.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. #!/bin/bash
  2. #
  3. # (C) Copyright 2014 Suriyan Ramasami
  4. #
  5. # SPDX-License-Identifier: GPL-2.0+
  6. #
  7. # Invoke this test script from U-Boot base directory as ./test/fs/fs-test.sh
  8. # It currently tests the fs/sb and native commands for ext4 and fat partitions
  9. # Expected results are as follows:
  10. # EXT4 tests:
  11. # fs-test.sb.ext4.out: Summary: PASS: 17 FAIL: 2
  12. # fs-test.ext4.out: Summary: PASS: 11 FAIL: 8
  13. # fs-test.fs.ext4.out: Summary: PASS: 11 FAIL: 8
  14. # FAT tests:
  15. # fs-test.sb.fat.out: Summary: PASS: 17 FAIL: 2
  16. # fs-test.fat.out: Summary: PASS: 19 FAIL: 0
  17. # fs-test.fs.fat.out: Summary: PASS: 19 FAIL: 0
  18. # Total Summary: TOTAL PASS: 94 TOTAL FAIL: 20
  19. # pre-requisite binaries list.
  20. PREREQ_BINS="md5sum mkfs mount umount dd fallocate mkdir"
  21. # All generated output files from this test will be in $OUT_DIR
  22. # Hence everything is sandboxed.
  23. OUT_DIR="sandbox/test/fs"
  24. # Location of generated sandbox u-boot
  25. UBOOT="./sandbox/u-boot"
  26. # Our mount directory will be in the sandbox
  27. MOUNT_DIR="${OUT_DIR}/mnt"
  28. # The file system image we create will have the $IMG prefix.
  29. IMG="${OUT_DIR}/3GB"
  30. # $SMALL_FILE is the name of the 1MB file in the file system image
  31. SMALL_FILE="1MB.file"
  32. # $BIG_FILE is the name of the 2.5GB file in the file system image
  33. BIG_FILE="2.5GB.file"
  34. # $MD5_FILE will have the expected md5s when we do the test
  35. # They shall have a suffix which represents their file system (ext4/fat)
  36. MD5_FILE="${OUT_DIR}/md5s.list"
  37. # $OUT shall be the prefix of the test output. Their suffix will be .out
  38. OUT="${OUT_DIR}/fs-test"
  39. # Full Path of the 1 MB file that shall be created in the fs image.
  40. MB1="${MOUNT_DIR}/${SMALL_FILE}"
  41. GB2p5="${MOUNT_DIR}/${BIG_FILE}"
  42. # ************************
  43. # * Functions start here *
  44. # ************************
  45. # Check if the prereq binaries exist, or exit
  46. function check_prereq() {
  47. for prereq in $PREREQ_BINS; do
  48. if [ ! -x `which $prereq` ]; then
  49. echo "Missing $prereq binary. Exiting!"
  50. exit
  51. fi
  52. done
  53. # We use /dev/urandom to create files. Check if it exists.
  54. if [ ! -c /dev/urandom ]; then
  55. echo "Missing character special /dev/urandom. Exiting!"
  56. exit
  57. fi
  58. }
  59. # If 1st param is "clean", then clean out the generated files and exit
  60. function check_clean() {
  61. if [ "$1" = "clean" ]; then
  62. rm -rf "$OUT_DIR"
  63. echo "Cleaned up generated files. Exiting"
  64. exit
  65. fi
  66. }
  67. # Generate sandbox U-Boot - gleaned from /test/dm/test-dm.sh
  68. function compile_sandbox() {
  69. unset CROSS_COMPILE
  70. NUM_CPUS=$(cat /proc/cpuinfo |grep -c processor)
  71. make O=sandbox sandbox_config
  72. make O=sandbox -s -j${NUM_CPUS}
  73. # Check if U-Boot exists
  74. if [ ! -x "$UBOOT" ]; then
  75. echo "$UBOOT does not exist or is not executable"
  76. echo "Build error?"
  77. echo "Please run this script as ./test/fs/`basename $0`"
  78. exit
  79. fi
  80. }
  81. # Clean out all generated files other than the file system images
  82. # We save time by not deleting and recreating the file system images
  83. function prepare_env() {
  84. rm -f ${MD5_FILE}.* ${OUT}.*
  85. mkdir ${OUT_DIR}
  86. }
  87. # 1st parameter is the name of the image file to be created
  88. # 2nd parameter is the filesystem - fat ext4 etc
  89. # -F cant be used with fat as it means something else.
  90. function create_image() {
  91. # Create image if not already present - saves time, while debugging
  92. if [ "$2" = "ext4" ]; then
  93. MKFS_OPTION="-F"
  94. else
  95. MKFS_OPTION=""
  96. fi
  97. if [ ! -f "$1" ]; then
  98. fallocate -l 3G "$1" &> /dev/null
  99. mkfs -t "$2" $MKFS_OPTION "$1" &> /dev/null
  100. if [ $? -ne 0 -a "$2" = "fat" ]; then
  101. # If we fail and we did fat, try vfat.
  102. mkfs -t vfat $MKFS_OPTION "$1" &> /dev/null
  103. fi
  104. fi
  105. }
  106. # 1st parameter is the FS type: fat/ext4
  107. # 2nd parameter is the name of small file
  108. # Returns filename which can be used for fat or ext4 for writing
  109. function fname_for_write() {
  110. case $1 in
  111. ext4)
  112. # ext4 needs absolute path name of file
  113. echo /${2}.w
  114. ;;
  115. *)
  116. echo ${2}.w
  117. ;;
  118. esac
  119. }
  120. # 1st parameter is image file
  121. # 2nd parameter is file system type - fat/ext4
  122. # 3rd parameter is name of small file
  123. # 4th parameter is name of big file
  124. # 5th parameter is fs/nonfs/sb - to dictate generic fs commands or
  125. # otherwise or sb hostfs
  126. # 6th parameter is the directory path for the files. Its "" for generic
  127. # fs and ext4/fat and full patch for sb hostfs
  128. # UBOOT is set in env
  129. function test_image() {
  130. addr="0x01000008"
  131. length="0x00100000"
  132. case "$2" in
  133. fat)
  134. PREFIX="fat"
  135. WRITE="write"
  136. ;;
  137. ext4)
  138. PREFIX="ext4"
  139. WRITE="write"
  140. ;;
  141. *)
  142. echo "Unhandled filesystem $2. Exiting!"
  143. exit
  144. ;;
  145. esac
  146. case "$5" in
  147. fs)
  148. PREFIX=""
  149. WRITE="save"
  150. SUFFIX=" 0:0"
  151. ;;
  152. nonfs)
  153. SUFFIX=" 0:0"
  154. ;;
  155. sb)
  156. PREFIX="sb "
  157. WRITE="save"
  158. SUFFIX="fs -"
  159. ;;
  160. *)
  161. echo "Unhandled mode $5. Exiting!"
  162. exit
  163. ;;
  164. esac
  165. if [ -z "$6" ]; then
  166. FILE_WRITE=`fname_for_write $2 $3`
  167. FILE_SMALL=$3
  168. FILE_BIG=$4
  169. else
  170. FILE_WRITE=$6/`fname_for_write $2 $3`
  171. FILE_SMALL=$6/$3
  172. FILE_BIG=$6/$4
  173. fi
  174. # In u-boot commands, <interface> stands for host or hostfs
  175. # hostfs maps to the host fs.
  176. # host maps to the "sb bind" that we do
  177. $UBOOT << EOF
  178. sb=$5
  179. setenv bind 'if test "\$sb" != sb; then sb bind 0 "$1"; fi'
  180. run bind
  181. # Test Case 1 - ls
  182. ${PREFIX}ls host${SUFFIX} $6
  183. #
  184. # We want ${PREFIX}size host 0:0 $3 for host commands and
  185. # sb size hostfs - $3 for hostfs commands.
  186. # 1MB is 0x0010 0000
  187. # Test Case 2 - size of small file
  188. ${PREFIX}size host${SUFFIX} $FILE_SMALL
  189. printenv filesize
  190. setenv filesize
  191. # 2.5GB (1024*1024*2500) is 0x9C40 0000
  192. # Test Case 3 - size of big file
  193. ${PREFIX}size host${SUFFIX} $FILE_BIG
  194. printenv filesize
  195. setenv filesize
  196. # Notes about load operation
  197. # If I use 0x01000000 I get DMA misaligned error message
  198. # Last two parameters are size and offset.
  199. # Test Case 4a - Read full 1MB of small file
  200. ${PREFIX}load host${SUFFIX} $addr $FILE_SMALL
  201. printenv filesize
  202. # Test Case 4b - Read full 1MB of small file
  203. md5sum $addr \$filesize
  204. setenv filesize
  205. # Test Case 5a - First 1MB of big file
  206. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x0
  207. printenv filesize
  208. # Test Case 5b - First 1MB of big file
  209. md5sum $addr \$filesize
  210. setenv filesize
  211. # fails for ext as no offset support
  212. # Test Case 6a - Last 1MB of big file
  213. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x9C300000
  214. printenv filesize
  215. # Test Case 6b - Last 1MB of big file
  216. md5sum $addr \$filesize
  217. setenv filesize
  218. # fails for ext as no offset support
  219. # Test Case 7a - One from the last 1MB chunk of 2GB
  220. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF00000
  221. printenv filesize
  222. # Test Case 7b - One from the last 1MB chunk of 2GB
  223. md5sum $addr \$filesize
  224. setenv filesize
  225. # fails for ext as no offset support
  226. # Test Case 8a - One from the start 1MB chunk from 2GB
  227. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x80000000
  228. printenv filesize
  229. # Test Case 8b - One from the start 1MB chunk from 2GB
  230. md5sum $addr \$filesize
  231. setenv filesize
  232. # fails for ext as no offset support
  233. # Test Case 9a - One 1MB chunk crossing the 2GB boundary
  234. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG $length 0x7FF80000
  235. printenv filesize
  236. # Test Case 9b - One 1MB chunk crossing the 2GB boundary
  237. md5sum $addr \$filesize
  238. setenv filesize
  239. # Generic failure case
  240. # Test Case 10 - 2MB chunk from the last 1MB of big file
  241. ${PREFIX}load host${SUFFIX} $addr $FILE_BIG 0x00200000 0x9C300000
  242. printenv filesize
  243. #
  244. # Read 1MB from small file
  245. ${PREFIX}load host${SUFFIX} $addr $FILE_SMALL
  246. # Write it back to test the writes
  247. # Test Case 11a - Check that the write succeeded
  248. ${PREFIX}${WRITE} host${SUFFIX} $addr $FILE_WRITE \$filesize
  249. mw.b $addr 00 100
  250. ${PREFIX}load host${SUFFIX} $addr $FILE_WRITE
  251. # Test Case 11b - Check md5 of written to is same as the one read from
  252. md5sum $addr \$filesize
  253. setenv filesize
  254. #
  255. reset
  256. EOF
  257. }
  258. # 1st argument is the name of the image file.
  259. # 2nd argument is the file where we generate the md5s of the files
  260. # generated with the appropriate start and length that we use to test.
  261. # It creates the necessary files in the image to test.
  262. # $GB2p5 is the path of the big file (2.5 GB)
  263. # $MB1 is the path of the small file (1 MB)
  264. # $MOUNT_DIR is the path we can use to mount the image file.
  265. function create_files() {
  266. # Mount the image so we can populate it.
  267. mkdir -p "$MOUNT_DIR"
  268. sudo mount -o loop,rw "$1" "$MOUNT_DIR"
  269. # Create big file in this image.
  270. # Note that we work only on the start 1MB, couple MBs in the 2GB range
  271. # and the last 1 MB of the huge 2.5GB file.
  272. # So, just put random values only in those areas.
  273. if [ ! -f "${GB2p5}" ]; then
  274. sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 \
  275. &> /dev/null
  276. sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=2 seek=2047 \
  277. &> /dev/null
  278. sudo dd if=/dev/urandom of="${GB2p5}" bs=1M count=1 seek=2499 \
  279. &> /dev/null
  280. fi
  281. # Create a small file in this image.
  282. if [ ! -f "${MB1}" ]; then
  283. sudo dd if=/dev/urandom of="${MB1}" bs=1M count=1 \
  284. &> /dev/null
  285. fi
  286. # Delete the small file which possibly is written as part of a
  287. # previous test.
  288. sudo rm -f "${MB1}.w"
  289. # Generate the md5sums of reads that we will test against small file
  290. dd if="${MB1}" bs=1M skip=0 count=1 2> /dev/null | md5sum > "$2"
  291. # Generate the md5sums of reads that we will test against big file
  292. # One from beginning of file.
  293. dd if="${GB2p5}" bs=1M skip=0 count=1 \
  294. 2> /dev/null | md5sum >> "$2"
  295. # One from end of file.
  296. dd if="${GB2p5}" bs=1M skip=2499 count=1 \
  297. 2> /dev/null | md5sum >> "$2"
  298. # One from the last 1MB chunk of 2GB
  299. dd if="${GB2p5}" bs=1M skip=2047 count=1 \
  300. 2> /dev/null | md5sum >> "$2"
  301. # One from the start 1MB chunk from 2GB
  302. dd if="${GB2p5}" bs=1M skip=2048 count=1 \
  303. 2> /dev/null | md5sum >> "$2"
  304. # One 1MB chunk crossing the 2GB boundary
  305. dd if="${GB2p5}" bs=512K skip=4095 count=2 \
  306. 2> /dev/null | md5sum >> "$2"
  307. sync
  308. sudo umount "$MOUNT_DIR"
  309. rmdir "$MOUNT_DIR"
  310. }
  311. # 1st parameter is the text to print
  312. # if $? is 0 its a pass, else a fail
  313. # As a side effect it shall update env variable PASS and FAIL
  314. function pass_fail() {
  315. if [ $? -eq 0 ]; then
  316. echo pass - "$1"
  317. PASS=$((PASS + 1))
  318. else
  319. echo FAIL - "$1"
  320. FAIL=$((FAIL + 1))
  321. fi
  322. }
  323. # 1st parameter is the string which leads to an md5 generation
  324. # 2nd parameter is the file we grep, for that string
  325. # 3rd parameter is the name of the file which has md5s in it
  326. # 4th parameter is the line # in the md5 file that we match it against
  327. # This function checks if the md5 of the file in the sandbox matches
  328. # that calculated while generating the file
  329. # 5th parameter is the string to print with the result
  330. check_md5() {
  331. # md5sum in u-boot has output of form:
  332. # md5 for 01000008 ... 01100007 ==> <md5>
  333. # the 7th field is the actual md5
  334. md5_src=`grep -A3 "$1" "$2" | grep "md5 for"`
  335. md5_src=($md5_src)
  336. md5_src=${md5_src[6]}
  337. # The md5 list, each line is of the form:
  338. # - <md5>
  339. # the 2nd field is the actual md5
  340. md5_dst=`sed -n $4p $3`
  341. md5_dst=($md5_dst)
  342. md5_dst=${md5_dst[0]}
  343. # For a pass they should match.
  344. [ "$md5_src" = "$md5_dst" ]
  345. pass_fail "$5"
  346. }
  347. # 1st parameter is the name of the output file to check
  348. # 2nd parameter is the name of the file containing the md5 expected
  349. # 3rd parameter is the name of the small file
  350. # 4th parameter is the name of the big file
  351. # 5th paramter is the name of the written file
  352. # This function checks the output file for correct results.
  353. function check_results() {
  354. echo "** Start $1"
  355. PASS=0
  356. FAIL=0
  357. # Check if the ls is showing correct results for 2.5 gb file
  358. grep -A6 "Test Case 1 " "$1" | egrep -iq "2621440000 *$4"
  359. pass_fail "TC1: ls of $4"
  360. # Check if the ls is showing correct results for 1 mb file
  361. grep -A6 "Test Case 1 " "$1" | egrep -iq "1048576 *$3"
  362. pass_fail "TC1: ls of $3"
  363. # Check size command on 1MB.file
  364. egrep -A3 "Test Case 2 " "$1" | grep -q "filesize=100000"
  365. pass_fail "TC2: size of $3"
  366. # Check size command on 2.5GB.file
  367. egrep -A3 "Test Case 3 " "$1" | grep -q "filesize=9c400000"
  368. pass_fail "TC3: size of $4"
  369. # Check read full mb of 1MB.file
  370. grep -A6 "Test Case 4a " "$1" | grep -q "filesize=100000"
  371. pass_fail "TC4: load of $3 size"
  372. check_md5 "Test Case 4b " "$1" "$2" 1 "TC4: load from $3"
  373. # Check first mb of 2.5GB.file
  374. grep -A6 "Test Case 5a " "$1" | grep -q "filesize=100000"
  375. pass_fail "TC5: load of 1st MB from $4 size"
  376. check_md5 "Test Case 5b " "$1" "$2" 2 "TC5: load of 1st MB from $4"
  377. # Check last mb of 2.5GB.file
  378. grep -A6 "Test Case 6a " "$1" | grep -q "filesize=100000"
  379. pass_fail "TC6: load of last MB from $4 size"
  380. check_md5 "Test Case 6b " "$1" "$2" 3 "TC6: load of last MB from $4"
  381. # Check last 1mb chunk of 2gb from 2.5GB file
  382. grep -A6 "Test Case 7a " "$1" | grep -q "filesize=100000"
  383. pass_fail "TC7: load of last 1mb chunk of 2GB from $4 size"
  384. check_md5 "Test Case 7b " "$1" "$2" 4 \
  385. "TC7: load of last 1mb chunk of 2GB from $4"
  386. # Check first 1mb chunk after 2gb from 2.5GB file
  387. grep -A6 "Test Case 8a " "$1" | grep -q "filesize=100000"
  388. pass_fail "TC8: load 1st MB chunk after 2GB from $4 size"
  389. check_md5 "Test Case 8b " "$1" "$2" 5 \
  390. "TC8: load 1st MB chunk after 2GB from $4"
  391. # Check 1mb chunk crossing the 2gb boundary from 2.5GB file
  392. grep -A6 "Test Case 9a " "$1" | grep -q "filesize=100000"
  393. pass_fail "TC9: load 1MB chunk crossing 2GB boundary from $4 size"
  394. check_md5 "Test Case 9b " "$1" "$2" 6 \
  395. "TC9: load 1MB chunk crossing 2GB boundary from $4"
  396. # Check 2mb chunk from the last 1MB of 2.5GB file - generic failure case
  397. grep -A6 "Test Case 10 " "$1" | grep -q 'Error: "filesize" not defined'
  398. pass_fail "TC10: load 2MB from the last 1MB of $4 - generic fail case"
  399. # Check 1mb chunk write
  400. grep -A3 "Test Case 11a " "$1" | \
  401. egrep -q '1048576 bytes written|update journal'
  402. pass_fail "TC11: 1MB write to $5 - write succeeded"
  403. check_md5 "Test Case 11b " "$1" "$2" 1 \
  404. "TC11: 1MB write to $5 - content verified"
  405. echo "** End $1"
  406. }
  407. # Takes in one parameter which is "fs" or "nonfs", which then dictates
  408. # if a fs test (size/load/save) or a nonfs test (fatread/extread) needs to
  409. # be performed.
  410. function test_fs_nonfs() {
  411. echo "Creating files in $fs image if not already present."
  412. create_files $IMAGE $MD5_FILE_FS
  413. OUT_FILE="${OUT}.fs.${fs}.out"
  414. test_image $IMAGE $fs $SMALL_FILE $BIG_FILE $1 "" \
  415. > ${OUT_FILE}
  416. check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
  417. $WRITE_FILE
  418. TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
  419. TOTAL_PASS=$((TOTAL_PASS + PASS))
  420. echo "Summary: PASS: $PASS FAIL: $FAIL"
  421. echo "--------------------------------------------"
  422. }
  423. # ********************
  424. # * End of functions *
  425. # ********************
  426. check_clean "$1"
  427. check_prereq
  428. compile_sandbox
  429. prepare_env
  430. # Track TOTAL_FAIL and TOTAL_PASS
  431. TOTAL_FAIL=0
  432. TOTAL_PASS=0
  433. # In each loop, for a given file system image, we test both the
  434. # fs command, like load/size/write, the file system specific command
  435. # like: ext4load/ext4size/ext4write and the sb load/ls/save commands.
  436. for fs in ext4 fat; do
  437. echo "Creating $fs image if not already present."
  438. IMAGE=${IMG}.${fs}.img
  439. MD5_FILE_FS="${MD5_FILE}.${fs}"
  440. create_image $IMAGE $fs
  441. # sb commands test
  442. echo "Creating files in $fs image if not already present."
  443. create_files $IMAGE $MD5_FILE_FS
  444. # Lets mount the image and test sb hostfs commands
  445. mkdir -p "$MOUNT_DIR"
  446. if [ "$fs" = "fat" ]; then
  447. uid="uid=`id -u`"
  448. else
  449. uid=""
  450. fi
  451. sudo mount -o loop,rw,$uid "$IMAGE" "$MOUNT_DIR"
  452. sudo chmod 777 "$MOUNT_DIR"
  453. OUT_FILE="${OUT}.sb.${fs}.out"
  454. test_image $IMAGE $fs $SMALL_FILE $BIG_FILE sb `pwd`/$MOUNT_DIR \
  455. > ${OUT_FILE}
  456. sudo umount "$MOUNT_DIR"
  457. rmdir "$MOUNT_DIR"
  458. check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE \
  459. $WRITE_FILE
  460. TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
  461. TOTAL_PASS=$((TOTAL_PASS + PASS))
  462. echo "Summary: PASS: $PASS FAIL: $FAIL"
  463. echo "--------------------------------------------"
  464. test_fs_nonfs nonfs
  465. test_fs_nonfs fs
  466. done
  467. echo "Total Summary: TOTAL PASS: $TOTAL_PASS TOTAL FAIL: $TOTAL_FAIL"
  468. echo "--------------------------------------------"
  469. if [ $TOTAL_FAIL -eq 0 ]; then
  470. echo "PASSED"
  471. exit 0
  472. else
  473. echo "FAILED"
  474. exit 1
  475. fi