#!/usr/bin/env python
#
#    test_gvidm.py - some tests of gvidm
#    Copyright (C) 2004 Matthew Mueller <donut AT dakotacom DOT net>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import os,sys,re,unittest
import commands


#allow gvidm executable to be tested to be overriden with TEST_GVIDM env var.
gvidmexe = os.environ.get('TEST_GVIDM',os.path.join(os.pardir, 'gvidm'))
if os.sep in gvidmexe or (os.altsep and os.altsep in gvidmexe):
	gvidmexe = os.path.abspath(gvidmexe)



def exitstatus(st):
	if not hasattr(os, 'WEXITSTATUS'): #the os.W* funcs are only on *ix
		return st
	if os.WIFSTOPPED(st):
		return 'stopped',os.WSTOPSIG(st)
	if os.WIFSIGNALED(st):
		return 'signal',os.WTERMSIG(st)
	if os.WIFEXITED(st):
		return os.WEXITSTATUS(st)
	return 'unknown',st


class TestCase(unittest.TestCase):
	def vfailIf(self, expr, msg=None):
		"Include the expr in the error message"
		if expr:
			if msg:
				msg = '(%r) %s'%(expr, msg)
			else:
				msg = '(%r)'%(expr,)
			raise self.failureException, msg

	def failIfCmd(self, ret, msg=None):
		status,output = ret
		self.vfailIf(status,'output=%r msg=%s'%(output,msg))
		return output
		

resre = re.compile(r'^(?:\d+:)?(\d+)x(\d+)@(\d+)$')

def isvalidres(res):
	x = resre.match(res)
	if not x: return 0
	w,h,r = map(int, x.groups())
	return w>0 and h>0 and r>0

def sort_list_output(output):
	lines = output.splitlines()
	sortbuf = []
	cur = None
	for line in lines:
		if line.endswith(" *"):
			lres,foo = line.split(' ')
			assert cur is None
			assert foo=="*"
			cur = lres
		else:
			lres = line
		w,h,r = map(int, resre.match(lres).groups())
		sortbuf.append(((w*h,r),lres))
	sortbuf.sort()
	sortbuf.reverse()
	assert cur is not None
	return cur, [e[-1] for e in sortbuf]
			

class VidModeTest_base:
	def test_query(self):
		output = self.failIfCmd(self.run("-q 0"))
		self.failUnlessEqual(1, len(output.splitlines()))
		self.failUnless(isvalidres(output), repr(output))

	def test_list(self):
		output = self.failIfCmd(self.run("-l 0"))
		lines = output.splitlines()
		curcount = 0
		for line in lines:
			if line.endswith(" *"):
				lres,foo = line.split(' ')
				qoutput = self.failIfCmd(self.run("-q 0"))
				self.failUnlessEqual(qoutput, lres)
				curcount += 1
			else:
				lres = line
			self.failUnless(isvalidres(lres), repr(line))
		self.failUnlessEqual(1, curcount)
	
	def test_set_max(self):
		output = self.failIfCmd(self.run("-l 0"))
		orig,sorted = sort_list_output(output)
		assert len(sorted)>1
		try:
			if orig==sorted[0]:
				assert sorted[0] != sorted[1]
				self.failIfCmd(self.run(sorted[1]))
				output = self.failIfCmd(self.run("-l 0"))
				cur,nsorted = sort_list_output(output)
				assert cur!=orig and cur==sorted[1]

			self.failIfCmd(self.run("0:max"))
			output = self.failIfCmd(self.run("-l 0"))
			cur,nsorted = sort_list_output(output)
			self.failUnlessEqual(sorted[0], cur)
			output = self.failIfCmd(self.run("-q 0"))
			self.failUnlessEqual(cur, output)
		finally:
			self.failIfCmd(self.run(orig))
			


	
class XVidModeTestCase(TestCase, VidModeTest_base):
	def run(self, args):
		status,output = commands.getstatusoutput(gvidmexe + ' ' + args)
		return exitstatus(status),output
	

class XRandRTestCase(TestCase, VidModeTest_base):
	def run(self, args):
		status,output = commands.getstatusoutput(gvidmexe + ' -r ' + args)
		return exitstatus(status),output
	

if __name__=="__main__":
	#little hack to allow to run only tests matching a certain prefix
	#run with ./test_gvidm.py [unittest args] [TestCases...] -X<testMethodPrefix>
	if len(sys.argv)>1 and sys.argv[-1].startswith('-X'):
		myTestLoader=unittest.TestLoader()
		myTestLoader.testMethodPrefix=sys.argv[-1][2:]
		unittest.main(argv=sys.argv[:-1], testLoader=myTestLoader)
	else:
		unittest.main()

