#!/bin/sh -e
# NAME=USB flash drive
# DESCRIPTION=This test allows to check the working ability of USB ports and/or plugged USB storage devices. A user has to plug the USB storage devices (such as USB flash drives) in every USB port of system under test. A number of USB storage drives is passed then as a COUNT parameter to this test script. First of all, it checks if a required number of USB devices is plugged in: the test won't start if it's not so. This way, a non-working USB port would be diagnosed. The test itself does the following for every detected USB storage device: it writes a number of blocks wit random data (start position is choosen randomly to increase an USB drive's lifetime) and remembers their checksum, then it clears the disk cache and reads these blocks back, calculating checksum. If checksums match, USB device and port work properly. This test also acts as a benchmark: it measures write and read speeds. This metric can be used  to diagnose bad ports/USB devices (due to speed lower than required minimum).
# DESTROYS_HDD=true
# IS_INTERACTIVE=true
# POWEROFF_DURING_TEST=false
# VERSION=0.1
# TAGS=benchmark,usb,usb-storage
# DEPENDS=USB, USB Mass Storage
# VAR=SIZE:int:20:Size of test file to be written, Blocksizes
# VAR=BLOCKSIZE:int:1024:Blocksize used for reading and writing by dd, KiB
# VAR=COUNT:int:2:There should be this many devices

. _inq-config-global; . $SHARE_DIR/functions-test

exit_handler()
{
	[ -f $FIFOFILE ] && rm $FIFOFILE
	[ -f $FIFOFILE.md5 ] && rm $FIFOFILE.md5
	[ -f $FIFOFILE.read_speed ] && rm $FIFOFILE.read_speed
}

FIFOFILE=`mktemp`

# Check for ready for testing drives
STORAGE_QUANTITY=0
for UDI in `hal-find-by-property --key storage.bus --string usb`; do
	hal-get-property --udi "$UDI" --key storage.drive_type |
		grep -q "^disk$" || continue
	STORAGE_QUANTITY=$(( $STORAGE_QUANTITY + 1 ))
done
if [ "$STORAGE_QUANTITY" -ne "$COUNT" ]; then
	STORAGE_QUANTITY=0
	# Wait user for inserting needed flash drives
	require_attention
	print_green_message "Insert $COUNT USB Flash drives and press enter"
	read foobar #dummy variable
	dismiss_attention

	for UDI in `hal-find-by-property --key storage.bus --string usb`; do
		hal-get-property --udi "$UDI" --key storage.drive_type |
			grep -q "^disk$" || continue

		vendor=`hal-get-property --udi "$UDI" --key storage.vendor`
		product=`hal-get-property --udi "$UDI" --key info.product`
		STORAGE_QUANTITY=$(( $STORAGE_QUANTITY + 1 ))
		print_green_message "Vendor: $vendor Product: $product"
	done
	print_green_message "Total USB drives quantity: $STORAGE_QUANTITY"
fi

TESTED_QUANTITY=0
# Check if there are right number of devices
if [ "$STORAGE_QUANTITY" -lt "$COUNT" ]; then
	print_red_message "Found $STORAGE_QUANTITY drives insted of $COUNT"
	test_failed "$STORAGE_QUANTITY drives insted of $COUNT"
else
for UDI in `hal-find-by-property --key storage.bus --string usb`; do
	hal-get-property --udi "$UDI" --key storage.drive_type |
		grep -q "^disk$" || continue
	block_dev=`hal-get-property --udi "$UDI" --key block.device`
	echo -n "Drive $block_dev..."

	# Detecting drive size and random seed
	drive_size=`hal-get-property --udi "$UDI" --key storage.removable.media_size`
	seed=$(( $RANDOM % ($drive_size / 1048576 / $SIZE - 1) ))
	
	echo -n "writing..."
	rm $FIFOFILE
	mkfifo $FIFOFILE
	md5sum -b $FIFOFILE | awk '{print $1}' > ${FIFOFILE}.md5 &
	write_speed_result=`dd if=/dev/urandom bs=${BLOCKSIZE}k count=${SIZE} \
		2>/dev/null | tee $FIFOFILE |
		dd of=${block_dev} bs=${BLOCKSIZE}k oflag=sync seek=$(($SIZE * $seed)) 2>&1 |
		sed -n '$ p'` ||
		test_failed "Drive $block_dev writing error"

	echo -n "reading..."
	read_md5=`dd if=${block_dev} bs=${BLOCKSIZE}k count=${SIZE} skip=$(($SIZE * $seed)) \
		2>${FIFOFILE}.read_speed | md5sum -b | awk '{print $1}'` ||
		test_failed "Drive $block_dev reading error"

	echo -n "comparing..."
	[ `cat ${FIFOFILE}.md5` = "$read_md5" ] ||
		test_failed "Drive $block_dev comparing error"
	write_speed=`echo "$write_speed_result" | awk '{print $(NF-1)}'`
	write_speed_unit=`echo "$write_speed_result" | awk '{print $NF}'`
	read_speed=`sed -n '$ p' < ${FIFOFILE}.read_speed | 
		awk '{print $(NF-1)}'`
	read_speed_unit=`sed -n '$ p' < ${FIFOFILE}.read_speed |
		awk '{print $NF}'`
	benchmark_submit_float "Drive $block_dev writing speed, ${write_speed_unit}" $write_speed
	benchmark_submit_float "Drive $block_dev reading speed, ${read_speed_unit}" $read_speed
	echo_success

	TESTED_QUANTITY=$(( $TESTED_QUANTITY + 1 ))
	test_progress $TESTED_QUANTITY $COUNT
done
fi

test_succeeded
