'OHRRPGCE - Routines for test programs
'(C) Copyright 1997-2020 James Paige, Ralph Versteegen, and the OHRRPGCE Developers
'Dual licensed under the GNU GPL v2+ and MIT Licenses. Read LICENSE.txt for terms and disclaimer of liability.

#include "config.bi"
#include "string.bi"
#include "const.bi"
#include "util.bi"  'Ensures all tests call lowlevel_init
#include "lumpfile.bi"

extern "C"
	type FnDebugHook as sub (byval errorlevel as ErrorLevelEnum, byval msg as zstring ptr)
	declare sub set_debug_hook (byval new_debug_hook as FnDebugHook)  'In miscc.c
end extern

TYPE testPtr as function() as integer

extern pauseTime as double
extern errorpos as integer
extern errorfile as string
extern startTest_name as string
extern startTest_line as integer
extern show_tests as bool
dim pauseTime as double
dim errorpos as integer
dim errorfile as string
dim startTest_name as string
dim startTest_line as integer
dim show_tests as bool = YES

' Parse command line arguments
for argidx as integer = 1 to 255
	dim arg as string = command(argidx)
	if arg = "" then exit for
	if arg = "-q" or arg = "--quiet" then
		show_tests = NO
	end if
next

Randomize 42

sub testprint(msg as string = "")
	if show_tests then print msg
end sub

sub doTest(byval theTest as testPtr)
	static num as integer = 0

	num += 1

	if show_tests then print "Test #" & num & ": " & startTest_name & "... ";

	dim as double start, finish, diff
	dim as integer ret
	
	pauseTime = 0
	
	start = timer
	
	ret = theTest()
	
	finish = timer - pauseTime
	
	diff = finish - start

	if ret > 0 then
		print "FAIL on line " & errorpos & " in " & errorfile & " (line " _
		      & (errorpos - startTest_line) & " of " & startTest_name & ")"
		close_lazy_files  'Avoid "double close" messages
		end num
	elseif ret = 0 then
		testprint "Pass"
	else
		testprint "SKIP"
	end if

	if show_tests then
		if diff < 1 then
			diff *= 1000
			if diff < 10 then
				diff *= 1000
				print "Took " & int(diff) & " us "
			elseif diff < 100 then
				print "Took " & format(diff, "0.0") & " ms "
			else
				print "Took " & int(diff) & " ms "
			end if
		else
			print "Took " & format(diff, "0.00") & " s "
		end if
	end if
	
end sub

#define passed return 0
#define fail errorfile = __FILE__ : errorpos = __LINE__ : return 1
#define skip_test return -1

#macro startTest(t)
	Declare Function t##_TEST() as integer
	startTest_name = #t
	startTest_line = __LINE__
	doTest(@t##_TEST)
	function t##_TEST() as integer
#endmacro
#define endTest pass : end Function

#macro testEqual(exp1, exp2)
	Scope
		var temp1 = exp1, temp2 = exp2
		if temp1 <> temp2 then
			print
			print "Expected " #exp1 " = " #exp2
			print "Actually " #exp1 " = " & temp1
			print "         " #exp2 " = " & temp2
			errorfile = __FILE__
			errorpos = __LINE__
			return 1
		end if
	End Scope
#endmacro

function ask(q as string) as integer
	dim ret as string, r as integer
	
	dim as double s, f, d
	
	s = timer
	
	q = q & " (y/n)"
	
	again:
	print q
	ret = input(1)
	
	if lcase(ret) <> "y" and lcase(ret) <> "n" then goto again
	
	r = lcase(ret) = "y"
	
	f = timer
	
	d = s - f
	
	do while d < 0
		d += 86400
	loop
	
	pauseTime += d
	
	return r
end function
