-- FILE:     COMPRESS.EX
-- PROJECT:  Lib2 (Unit testing)
-- PURPOSE:  Verify the results of COMPRESS.E library.
-- AUTHOR:   Shian Lee
-- VERSION:  1.02  January/17/2022
-- LANGUAGE: Euphoria version 3.1.1 (http://www.RapidEuphoria311.com)
-- PLATFORM: Any
-- LICENCE:  Free. Use at your own risk.
-- NOTE:     * Using 'euphoria' sub-directories for source files.
--           * Created using EDU 3.04.
-- HISTORY:  1.00: Initial version. (Dec-2021)
--           1.02: now with OS menu.
-----------------------------------------------------------------------------


include machine2.e
include file.e
include graphics.e
include machine.e
include get.e

-- Lib2 1.48+
include compress.e


constant SLASH = iif(platform() = LINUX, '/', '\\')
constant EUDIR = getenv("EUDIR") & SLASH


integer os

function os_menu()
-- select OS for test, return test #
    integer n
    
    clear_screen()
    n = floor(prompt_number(
	" Select OS for test (0=Quit):\n" &
	" ----------------------------\n\n" &
	" 1. FreeDOS\n" & 
	" 2. DOSBox on Linux\n" & 
	" 3. Windows XP / Windows 10 (using exwc)\n" &
	" 4. TinyCore Linux\n" &
	" 5. Linux Mint\n" &
	" 6. FreeBSD (GhostBSD)\n" &
	" 7. Linux on FreeBSD\n\n ",
	{0, 7}
    ))
    if n >= 1 and n <= 7 then
	return n
    end if
    abort(0)
end function
os = os_menu()

--------------------------- Start of user defined ---------------------------

-- note: path is case sensitive on Linux/FreeBSD
constant HOME = iif(os < 4, "C:\\",             -- DOS/Windows
		iif(os = 4, "/home/tc/",        -- tc Linux
		iif(os = 5, "/home/shian/",     -- Linux Mint
			    "/usr/home/shian/"  -- FreeBSD (6,7)
		)))

constant WORK_DIR = HOME & "data" -- work directory

-- * delete COMP_DIR & DECOMP_DIR manually when done test.

constant COMP_DIR = WORK_DIR & SLASH & "~COMP" & SLASH,  -- compressed out
       DECOMP_DIR = WORK_DIR & SLASH & "~DECOMP" & SLASH -- decompressed out

---------------------------- End of user defined ----------------------------


procedure normal_color()
-- restore black & white screen colors
    text_color(WHITE)
    puts(1, '\n')
end procedure


procedure fatal(sequence msg)
-- abort with red message on any error
    normal_color()
    text_color(BRIGHT_RED)
    puts(1, msg & " abort...")
    pause()
    normal_color()
    abort(1)
end procedure


procedure success(sequence msg)
-- print success message and new line
    text_color(BRIGHT_GREEN)
    puts(1, msg)
    normal_color()
end procedure


procedure verify(sequence src, sequence dest, sequence compfile, atom ratio)
-- compare the source file (src) with the decompressed file (dest),
-- also verify the compression ratio of the compressed file (compfile)
    integer fn1, fn2
    atom l1, l2, l3, r
    sequence d

    -- files size equal?
    d = dir(src)
    l1 = d[1][D_SIZE]
    d = dir(dest)
    l2 = d[1][D_SIZE]
    if l1 != l2 then
	fatal("Verify size ERROR: " & src & " != " & dest)
    end if

    -- compression ratio equal?
    d = dir(compfile) -- compressed file
    l3 = d[1][D_SIZE]
    r = (1.0 - (l3 / l1)) * 100 -- new ratio
    if r != ratio then
	fatal(sprintf("Verify ratio ERROR: %g != %g", {ratio, r}))
    end if

    -- open source file and decompressed file
    fn1 = open(src, "rb")
    fn2 = open(dest, "rb")
    if fn1 = -1 or fn2 = -1 then
	fatal("Cannot open file(s) for verify!")
    end if

    -- files equal (byte by byte)?
    for i = 1 to l1 do
	if getc(fn1) != getc(fn2) then
	    fatal("Verify ERROR: " & src & " != " & dest)
	end if
    end for

    close(fn1)
    close(fn2)

    -- verify successful
    success(src & " <=> " & dest & sprintf(" [%d%%]", r))
    puts(1, '\n')
end procedure


procedure init_program()
    -- current dir warning
    if chdir(WORK_DIR) then
    end if
    puts(1, "Work dir (^C=abort): " & current_dir() & '\n')
    pause()

    -- create test directories if needed
    system("mkdir " & COMP_DIR[1..$ - 1], 2)
    system("mkdir " & DECOMP_DIR[1..$ - 1], 2)

    tick_rate(100) -- for calculating speed on DOS

    normal_color()
    clear_screen()

    puts(1, "\n *** COMPRESS.E TEST ***\n" &
	    " <Space>=Pause, <Esc>=Quit, (^C=Abort) ...\n")
    pause()
end procedure


procedure statistics(atom avg, integer count, atom speed, atom despeed)
-- print statistics when test ends
    success(sprintf("\nTESTING <%d> FILES SUCCESSFUL!", count))
    success(sprintf("Average compression ratio: %g%% (%d%%)",
	{avg / count, avg / count}))
    success(sprintf(
	"Average/Total speed: compress %.2fs/%.2fs, decompress %.2fs/%.2fs",
	{speed / count, speed, despeed / count, despeed}))
end procedure


procedure main()
-- compress/decompress/verify files
    sequence path, src, dest, dest2
    object s
    atom r, ratio, avg          -- compression ratio
    atom t, t2, speed, despeed  -- speed
    integer count, key

    avg = 0
    count = 0
    speed = 0
    despeed = 0

    -- * you can change the start/end values of i to test specific dirs.
    -- * you can specify any other directory in i = 10+.
    for i = 1 to 9 do
	if i = 1 then
	    path = EUDIR & "include"
	elsif i = 2 then
	    path = EUDIR & "doc"
	elsif i = 3 then
	    path = EUDIR & "html"
	elsif i = 4 then
	    path = EUDIR & "tutorial"
	elsif i = 5 then
	    path = EUDIR & "demo"
	elsif i = 6 then
	    path = EUDIR & "demo" & SLASH & "japi"
	elsif i = 7 then
	    path = EUDIR & "source"
	elsif i = 8 then
	    path = EUDIR & "bin"
	elsif i = 9 then
	    path = EUDIR & "demo" & SLASH & "japi" & SLASH & "images"

	elsif i = 10 then
	    path = "C:\\FDOS\\BIN"
	elsif i = 11 then
	    path = "C:\\FDOS\\PACKAGES"
	end if

	s = dir(path)
	if atom(s) or length(s) = 0 then
	    fatal(path & " directory is empty or not exist!")
	end if

	-- compress, decompress, verify files
	for j = 1 to length(s) do
	    if not find('d', s[j][D_ATTRIBUTES]) then -- skip directories
		src = path & SLASH & s[j][D_NAME]
		dest = COMP_DIR & s[j][D_NAME]
		dest2 = DECOMP_DIR & s[j][D_NAME]

		-- compress source file
		t = time()
		ratio = compress_file(src, dest)
		t2 = time() - t
		speed += t2

		if ratio then
		    text_color(WHITE)
		    printf(1, "%s --> %s [%d%%, %.1fs]\n",
			{src, dest, ratio, t2})
		    avg += ratio    -- avrage compression ratio
		    count += 1      -- count files for avrage
		else
		    fatal("Error compressing file: '" & src & "'!")
		end if

		-- decompress file
		t = time()
		r = decompress_file(dest, dest2)
		t2 = time() - t
		despeed += t2

		if r then
		    text_color(BRIGHT_WHITE)
		    printf(1, "%s ->> %s [%.1fs]\n", {dest, dest2, t2})
		else
		    fatal("Error decompressing file '" & dest & "'!")
		end if

		-- compare source file to decompressed file
		verify(src, dest2, dest, ratio)

		-- user want to pause/stop?
		key = get_key()
		if key = 32 then
		    pause()
		elsif key = 27 then
		    fatal(" *** User pressed Escape *** ")
		end if
	    end if
	end for
    end for

    -- test done, print statistics
    statistics(avg, count, speed, despeed)
    pause()
end procedure


-- start test
init_program()
main()


-- End of file.
