2016-05-28 21:04:12 +02:00
#!/usr/bin/python3
2017-01-30 15:53:19 +01:00
# Lexesis - A language agnostic lexical analyser generator
# Copyright © 2016-2017 Thomas Avé, Robin Jadoul
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2016-05-28 21:04:12 +02:00
import unittest , subprocess , filecmp , argparse , os . path , os , shutil
REFERENCE_DIR = os . path . join ( os . path . abspath ( os . path . dirname ( __file__ ) ) , " tests " )
2016-05-30 16:09:56 +02:00
REGEXES_DATA = [ # (regexes, should be accepted)
( [ r " [a-zA-Z0-9]* " ] , True ) ,
2016-05-30 16:57:46 +02:00
( [ r " [a-dD-F9-0]* " ] , True ) ,
2016-05-30 16:09:56 +02:00
( [ r " a " , r " a|b " ] , True ) ,
( [ r " a|b " , r " a " ] , True ) ,
2016-05-30 16:57:46 +02:00
( [ r " [[] " , r " []] " , r " []-[] " , r " [][-] " ] , True ) ,
( [ r " [^^] " , r " [^]-[] " , r " [^][-] " ] , True ) ,
( [ r " [ ^] " , r " [ ^-X ] " , r " []-^] " ] , True ) ,
( [ r " [^-X] " , r " [^][] " ] , True ) ,
( [ r " [-] " , r " []-] " ] , True ) ,
( [ r " [^-] " , " [^]] " , r " [^-] " , r " [^-^] " ] , True ) ,
( [ r " [^--] " , r " [--] " ] , True ) ,
( [ r " [^] " ] , False ) ,
( [ r " [] " ] , False ) ,
( [ r " \ r " , r " \ n " , r " \ f " , r " \ v " , r " \ a " , r " \ t " , r " \ b " , r " \ s " , r " " ] , True ) ,
( [ r " \\ " , r " \ * " , r " \ + " , r " \ | " , r " \ ( " , r " \ ) " , r " \ [ " , r " \ [ " , r " \ ? " , r " \ . " ] , True ) ,
( [ r " . " , r " a* " , r " a+ " , r " a? " , r " (ab)* " , r " a|b " ] , True ) ,
( [ r " (a|b)* " , r " (a|b)+ " , r " a** " , r " a?? " , r " (ab)? " ] , True ) ,
( [ r " ( " ] , False ) ,
( [ r " ) " ] , False ) ,
( [ r " [ " ] , False ) ,
( [ r " ] " ] , False ) ,
( [ r " (test(a)qwerty " ] , False ) ,
( [ r " test(a)qwerty) " ] , False ) ,
( [ r " ab| " ] , False ) ,
( [ r " |ab " ] , False ) ,
( [ r " ab(c|)de " ] , False ) ,
( [ r " ab(|c)de " ] , False ) ,
( [ r " " ] , False ) ,
( [ r " () " ] , False ) ,
( [ r " (?) " ] , False ) ,
( [ r " ((ab)c()de) " ] , False ) ,
( [ r " | " ] , False ) ,
( [ r " (|) " ] , False ) ,
( [ r " ? " ] , False ) ,
( [ r " * " ] , False ) ,
( [ r " (*) " ] , False ) ,
( [ r " + " ] , False ) ,
( [ r " (+) " ] , False ) ,
2016-05-28 21:04:12 +02:00
]
2016-05-29 20:21:43 +02:00
EXAMPLE_TESTS = { #Mapping from test name to executable and number of available test input files
2016-05-29 20:33:13 +02:00
" keywords " : ( " examples/keywords/keywords " , 2 ) ,
2016-05-30 22:38:06 +02:00
" highlighter " : ( " examples/SyntaxHighlighter/highlighter " , 8 ) ,
2016-05-30 18:51:22 +02:00
" leopard " : ( " examples/leopard/leopard " , 8 ) ,
2016-05-29 20:21:43 +02:00
}
2016-05-30 16:09:56 +02:00
def make_pipeline_test ( regexes , should_accept , idx ) :
2016-05-28 21:04:12 +02:00
def test ( self ) :
2016-05-30 16:57:46 +02:00
p = subprocess . Popen ( [ os . path . join ( args . builddir , " src " , " Lexesis-test " ) , " test_ %s " % idx , data_dir ] , stdin = subprocess . PIPE , stderr = subprocess . DEVNULL )
p . communicate ( bytes ( " \n " . join ( regexes ) + " \n " , " utf-8 " ) )
2016-05-30 16:09:56 +02:00
if should_accept :
self . assertEqual ( 0 , p . returncode )
2016-05-30 16:57:46 +02:00
self . assertTrue ( filecmp . cmp ( os . path . join ( REFERENCE_DIR , " test_ %s .re " % idx ) , os . path . join ( data_dir , " test_ %s .re " % idx ) ) , " The regex for testcase %s is incorrect " % idx )
self . assertTrue ( filecmp . cmp ( os . path . join ( REFERENCE_DIR , " test_ %s .enfa " % idx ) , os . path . join ( data_dir , " test_ %s .enfa " % idx ) ) , " The eNFA for testcase %s is incorrect " % idx )
self . assertTrue ( filecmp . cmp ( os . path . join ( REFERENCE_DIR , " test_ %s .mssc " % idx ) , os . path . join ( data_dir , " test_ %s .mssc " % idx ) ) , " The mssc ' d DFA for testcase %s is incorrect " % idx )
self . assertTrue ( filecmp . cmp ( os . path . join ( REFERENCE_DIR , " test_ %s .min " % idx ) , os . path . join ( data_dir , " test_ %s .min " % idx ) ) , " The minimized DFA for testcase %s is incorrect " % idx )
2016-05-30 16:09:56 +02:00
else :
self . assertNotEqual ( 0 , p . returncode )
2016-05-28 21:04:12 +02:00
return test
2016-05-29 20:21:43 +02:00
def make_functional_test ( name , prog , idx ) :
def test ( self ) :
inpath = os . path . join ( REFERENCE_DIR , " %s _ %s .in " % ( name , idx ) )
infile = open ( inpath )
outpath = os . path . join ( data_dir , " %s _ %s .out " % ( name , idx ) )
outfile = open ( outpath , " w " )
checkpath = os . path . join ( REFERENCE_DIR , " %s _ %s .exp " % ( name , idx ) )
p = subprocess . Popen ( [ prog ] , stdin = infile , stdout = outfile )
p . communicate ( )
infile . close ( )
outfile . close ( )
self . assertTrue ( filecmp . cmp ( checkpath , outpath ) , " Testcase %s for example program %s failed " % ( idx , name ) )
return test
2016-05-28 21:04:12 +02:00
class Tests ( unittest . TestCase ) :
pass
if __name__ == " __main__ " :
parser = argparse . ArgumentParser ( )
parser . add_argument ( " --builddir " , metavar = " builddir " , default = os . path . join ( os . path . abspath ( os . path . dirname ( __file__ ) ) , " build " ) , required = False )
args = parser . parse_args ( )
data_dir = os . path . join ( args . builddir , " test_data " )
try :
shutil . rmtree ( data_dir )
except Exception as err :
pass
os . mkdir ( data_dir )
2016-05-30 16:09:56 +02:00
for i , ( regexes , should_accept ) in enumerate ( REGEXES_DATA ) :
t = make_pipeline_test ( regexes , should_accept , i )
2016-05-28 21:04:12 +02:00
setattr ( Tests , " test_ %s " % i , t )
2016-05-29 20:21:43 +02:00
for test , ( prog , num ) in EXAMPLE_TESTS . items ( ) :
for i in range ( num ) :
t = make_functional_test ( test , os . path . join ( args . builddir , prog ) , i )
setattr ( Tests , " test_ %s _ %s " % ( test , i ) , t )
2016-05-28 21:04:12 +02:00
unittest . main ( )