diff options
author | Thomas Miedema <thomasmiedema@gmail.com> | 2015-08-29 15:52:43 +0200 |
---|---|---|
committer | Thomas Miedema <thomasmiedema@gmail.com> | 2016-05-17 18:06:05 +0200 |
commit | 3f3dc23ea64573a12e2f4bfdaaa3aa536ad3188d (patch) | |
tree | 19caf96220f19094efca6171fa980829f4b9794d | |
parent | dc94914eb0da985a2f006e2bd390fa1fdbafcc33 (diff) | |
download | haskell-3f3dc23ea64573a12e2f4bfdaaa3aa536ad3188d.tar.gz |
Testsuite: run tests in /tmp after copying required files
Major change to the testsuite driver.
For each TEST:
* create a directory `<testdir>` inside `/tmp`.
* link/copy all source files that the test needs into `<testdir>`.
* run the test inside `<testdir>`.
* delete `<testdir>`
Extra files are (temporarily) tracked in
`testsuite/driver/extra_files.py`, but can also be specified using the
`extra_files` setup function.
Differential Revision: https://phabricator.haskell.org/D1187
Reviewed by: Rufflewind, bgamari
Trac: #11980
-rw-r--r-- | testsuite/driver/extra_files.py | 535 | ||||
-rw-r--r-- | testsuite/driver/runtests.py | 30 | ||||
-rw-r--r-- | testsuite/driver/testglobals.py | 3 | ||||
-rw-r--r-- | testsuite/driver/testlib.py | 151 | ||||
-rw-r--r-- | testsuite/driver/testutil.py | 32 | ||||
-rw-r--r-- | testsuite/tests/plugins/all.T | 17 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_compile/all.T | 2 |
7 files changed, 743 insertions, 27 deletions
diff --git a/testsuite/driver/extra_files.py b/testsuite/driver/extra_files.py new file mode 100644 index 0000000000..d6e639dd28 --- /dev/null +++ b/testsuite/driver/extra_files.py @@ -0,0 +1,535 @@ +# Extra files that tests depend on. +# Maybe move this information to .T files at some point. + +extra_src_files = { + '10queens': ['Main.hs'], + 'Capi_Ctype_001': ['Capi_Ctype_A_001.hsc', 'capi_ctype_001.h', 'capi_ctype_001_c.c'], + 'Capi_Ctype_002': ['Capi_Ctype_A_002.hsc', 'capi_ctype_002_A.h', 'capi_ctype_002_B.h'], + 'Defer02': ['../../typecheck/should_run/Defer01.hs'], + 'DeprU': ['DeprM.hs'], + 'ExportSyntaxImport': ['ExportSyntax.hs'], + 'ExtraConstraintsWildcardInTypeSpliceUsed': ['ExtraConstraintsWildcardInTypeSplice.hs'], + 'GFunctor1': ['GFunctor.hs', 'Main.hs'], + 'GMap1': ['GMap.hs', 'Main.hs'], + 'GShow1': ['GShow.hs', 'Main.hs'], + 'GUniplate1': ['GUniplate.hs', 'Main.hs'], + 'ImpExp_Imp': ['ImpExp_Exp.hs'], + 'ImpSafeOnly01': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly02': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly03': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly04': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly05': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly06': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly07': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly08': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly09': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'ImpSafeOnly10': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'SplicesUsed': ['Splices.hs'], + 'T10138': ['.keepme.hpc.T10138/'], + 'T10255': ['Test10255.hs'], + 'T10268': ['Test10268.hs'], + 'T10269': ['Test10269.hs'], + 'T10276': ['Test10276.hs'], + 'T10278': ['Test10278.hs'], + 'T10280': ['Test10280.hs'], + 'T10294': ['annotation-plugin/'], + 'T10294a': ['annotation-plugin/'], + 'T10307': ['Test10307.hs'], + 'T10309': ['Test10309.hs'], + 'T10312': ['Test10312.hs'], + 'T10313': ['Test10313.hs', 'stringSource.hs'], + 'T10354': ['Test10354.hs'], + 'T10357': ['Test10357.hs'], + 'T10358': ['Test10358.hs'], + 'T10396': ['Test10396.hs'], + 'T10399': ['Test10399.hs'], + 'T10420': ['rule-defining-plugin/'], + 'T10458': ['A.c'], + 'T10529a': ['hpc_sample_non_existing_module.tix'], + 'T10529b': ['.hpc/Main.mix', 'hpc_sample_incompatible_hash.tix'], + 'T10529c': ['.hpc/NoParse.mix', 'hpc_sample_no_parse.tix'], + 'T10576a': ['T10576.hs'], + 'T10576b': ['T10576.hs'], + 'T10637': ['A.hs', 'A.hs-boot'], + 'T10672_x64': ['Main.hs', 'Printf.hs', 'cxxy.cpp'], + 'T10672_x86': ['Main.hs', 'Printf.hs', 'cxxy.cpp'], + 'T10890': ['A.hs', 'B.hs'], + 'T10890_1': ['Base.hs', 'Extends.hs'], + 'T10955': ['A.c', 'B.c'], + 'T10955dyn': ['A.c', 'B.c'], + 'T10971d': ['T10971c.hs'], + 'T11018': ['Test11018.hs'], + 'T11072gcc': ['A.c', 'T11072.hs'], + 'T11072msvc': ['A.c', 'T11072.hs', 'libAS.def', 'i686/', 'x86_64/'], + 'T11223_link_order_a_b_2_fail': ['bar.c', 'foo.c', 'foo3.hs'], + 'T11223_link_order_a_b_succeed': ['bar.c', 'foo.c', 'foo2.hs'], + 'T11223_link_order_b_a_2_succeed': ['bar.c', 'foo.c', 'foo3.hs'], + 'T11223_link_order_b_a_succeed': ['bar.c', 'foo.c', 'foo2.hs'], + 'T11223_simple_duplicate_lib': ['bar.c', 'foo.c', 'foo.hs'], + 'T11223_simple_link': ['foo.c', 'foo.hs'], + 'T11223_simple_link_lib': ['foo.c', 'foo.hs'], + 'T11223_simple_unused_duplicate_lib': ['bar.c', 'foo.c', 'foo.hs'], + 'T11223_weak_both_link_order_a_b_succeed': ['power.c', 'power3.hs', 'power_slow.c'], + 'T11223_weak_both_link_order_b_a_succeed': ['power.c', 'power3.hs', 'power_slow.c'], + 'T11223_weak_only_link_fail': ['power.c', 'power.hs'], + 'T11223_weak_only_link_succeed': ['power3.hs', 'power_slow.c'], + 'T11223_weak_single_link_order_a_b_succeed': ['power.c', 'power3.hs', 'power_slow.c'], + 'T11223_weak_single_link_order_b_a_succeed': ['power.c', 'power3.hs', 'power_slow.c'], + 'T11244': ['rule-defining-plugin/'], + 'T11321': ['Test11321.hs'], + 'T11332': ['Test11332.hs'], + 'T11430': ['Test11430.hs', 't11430.hs'], + 'T11824': ['TyCon.hs', 'Type.hs', 'Type.hs-boot', 'Unbound/'], + 'T11827': ['A.hs', 'A.hs-boot', 'B.hs'], + 'T1372': ['p1/', 'p2/'], + 'T1407': ['A.c'], + 'T1959': ['B.hs', 'C.hs', 'D.hs', 'E1.hs', 'E2.hs'], + 'T2014': ['A.hs', 'A.hs-boot', 'B.hs', 'C.hs'], + 'T2615': ['libfoo_T2615.c', 'libfoo_script_T2615.so'], + 'T3007': ['A/', 'B/'], + 'T3103': ['Foreign/', 'GHC/'], + 'T4198': ['exitminus1.c'], + 'T437': ['Test.hs', 'Test2.hs'], + 'T4491': ['A.hs'], + 'T4891': ['X.hs'], + 'T5147': ['A.hs', 'B1.hs', 'B2.hs'], + 'T5250': ['spalign.c'], + 'T5435_dyn_asm': ['T5435.hs', 'T5435_asm.c'], + 'T5435_dyn_gcc': ['T5435.hs', 'T5435_gcc.c'], + 'T5435_v_asm': ['T5435.hs', 'T5435_asm.c'], + 'T5435_v_gcc': ['T5435.hs', 'T5435_gcc.c'], + 'T5442a': ['test.pkg'], + 'T5442b': ['test.pkg'], + 'T5442c': ['test.pkg'], + 'T5442d': ['shadow1.pkg', 'shadow2.pkg', 'shadow4.pkg'], + 'T5462No1': ['GFunctor/'], + 'T5462Yes1': ['GEnum/', 'GEq/', 'GFunctor/'], + 'T5462Yes2': ['GFunctor/'], + 'T5644': ['Conf.hs', 'ManyQueue.hs', 'Util.hs', 'heap-overflow.hs'], + 'T6018fail': ['T6018Afail.hs', 'T6018Bfail.hs', 'T6018Cfail.hs', 'T6018Dfail.hs'], + 'T6106': ['../shell.hs'], + 'T7040_ghci': ['T7040_c.h'], + 'T7354a': ['T7354b.hs'], + 'T7373': ['D.hs', 'pkg/'], + 'T7478': ['A.hs', 'B.hs', 'C.hs'], + 'T7702': ['T7702plugin'], + 'T7835': ['Test.hs', 'TestPrim.hs', 'test-prims.cmm'], + 'T8184': ['A.hs', 'B.hs', 'B.hs-boot', 'C.hs'], + 'T8353': ['Defer03.hs'], + 'T8425': ['Arr.hs', 'Base.hs', 'BuggyOpt.hs', 'Good.hs', 'M.hs', 'Main.hs'], + 'T8526': ['A.hs'], + 'T8602': ['A.hs'], + 'T9293': ['ghci057.hs'], + 'T9562': ['A.hs', 'B.hs', 'B.hs-boot', 'C.hs', 'D.hs', 'Main.hs'], + 'T9579_outofheap_rtsall': ['OutOfHeap.hs'], + 'T9579_outofheap_rtsall_no_suggestions': ['OutOfHeap.hs'], + 'T9579_outofheap_rtsnone': ['OutOfHeap.hs'], + 'T9579_outofheap_rtssome': ['OutOfHeap.hs'], + 'T9579_stackoverflow_rtsall': ['StackOverflow.hs'], + 'T9579_stackoverflow_rtsall_no_suggestions': ['StackOverflow.hs'], + 'T9579_stackoverflow_rtsnone': ['StackOverflow.hs'], + 'T9579_stackoverflow_rtssome': ['StackOverflow.hs'], + 'T9619': ['.hpc', '.hpc.copy', 'hpc_sample.tix'], + 'T9646': ['Main.hs', 'Natural.hs', 'StrictPrim.hs', 'Type.hs'], + 'T9930fail': ['T9930'], + 'TH_import_loop': ['Main.hs', 'ModuleA.hs', 'ModuleA.hs-boot', 'ModuleB.hs', 'ModuleC.hs'], + 'TH_spliceViewPat': ['A.hs', 'Main.hs'], + 'andre_monad': ['Main.hs'], + 'andy_cherry': ['DataTypes.hs', 'GenUtils.hs', 'Interp.hs', 'InterpUtils.hs', 'Main.hs', 'Parser.hs', 'PrintTEX.hs', 'mygames.pgn'], + 'annfail04': ['Annfail04_Help.hs'], + 'annfail05': ['Annfail05_Help.hs'], + 'annfail06': ['Annfail06_Help.hs'], + 'annotations': ['AnnotationLet.hs'], + 'annrun01': ['Annrun01_Help.hs'], + 'annth_compunits': ['AnnHelper.hs', 'TestModule.hs', 'TestModuleTH.hs', 'annth.hs'], + 'annth_make': ['AnnHelper.hs', 'TestModule.hs', 'TestModuleTH.hs', 'annth.hs'], + 'apirecomp001': ['A.hs', 'B.hs', 'myghc.hs'], + 'barton-mangler-bug': ['Basic.hs', 'Expected.hs', 'Main.hs', 'Physical.hs', 'Plot.lhs', 'PlotExample.lhs', 'TypesettingTricks.hs'], + 'base01': ['GHC'], + 'boolFormula': ['TestBoolFormula.hs'], + 'break001': ['../Test2.hs'], + 'break002': ['../Test2.hs'], + 'break003': ['../Test3.hs'], + 'break005': ['../QSort.hs'], + 'break006': ['../Test3.hs'], + 'break007': ['Break007.hs'], + 'break008': ['../Test3.hs'], + 'break009': ['../Test6.hs'], + 'break010': ['../Test6.hs'], + 'break011': ['../Test7.hs'], + 'break017': ['../QSort.hs'], + 'break018': ['../mdo.hs'], + 'break019': ['../Test2.hs'], + 'break020': ['Break020b.hs'], + 'break021': ['Break020b.hs', 'break020.hs'], + 'break022': ['A1.hs', 'B.hs', 'B.hs-boot', 'C.hs'], + 'break023': ['A1.hs', 'B.hs', 'B.hs-boot', 'C.hs'], + 'break027': ['../QSort.hs'], + 'bug1465': ['B1.hs', 'B2.hs', 'C.hs', 'v1/', 'v2/'], + 'bug1677': ['Bar.hs', 'Foo.hs'], + 'bundle-export': ['BundleExport.hs'], + 'cabal01': ['A.hs', 'B/', 'MainA.hs', 'Setup.lhs', 'c_src/', 'hello.c', 'test.cabal'], + 'cabal03': ['Setup.lhs', 'p/', 'q/', 'r/'], + 'cabal04': ['Library.hs', 'Setup.lhs', 'TH.hs', 'thtest.cabal'], + 'cabal05': ['Setup.hs', 'p/', 'q/', 'r/', 's/', 't/'], + 'cabal06': ['Setup.hs', 'p-1.0/', 'p-1.1/', 'q/', 'r/'], + 'cabal08': ['Main.hs', 'Setup.hs', 'p1/', 'p2/'], + 'cabal09': ['Main.hs', 'Setup.hs', 'reexport.cabal'], + 'ccfail004': ['Ccfail004A.hs'], + 'cgrun067': ['Cgrun067A.hs'], + 'cholewo-eval': ['Arr.lhs', 'Main.lhs'], + 'comments': ['CommentsTest.hs'], + 'concio001.thr': ['concio001.hs'], + 'concprog001': ['Arithmetic.hs', 'Converter.hs', 'Mult.hs', 'Stream.hs', 'Thread.hs', 'Trit.hs', 'Utilities.hs'], + 'concprog002': ['Event.hs', 'Scheduler.hs', 'Server.hs', 'Thread.hs'], + 'concprog003': ['CASList.hs', 'Collection.hs', 'IOList.lhs', 'ImmList.hs', 'MVarListLockCoupling.hs', 'Main.lhs', 'RefInterface.hs', 'TestData.hs', 'TestDataParser.hs', 'TestRun.hs', 'test-8-3000-3000-2-1-4'], + 'cvh_unboxing': ['Append.lhs', 'Main.lhs', 'Types.lhs'], + 'determ002': ['A.hs'], + 'determ003': ['A.hs'], + 'determ005': ['A.hs'], + 'determ006': ['spec-inline-determ.hs'], + 'determ010': ['A.hs'], + 'dodgy': ['DodgyA.hs'], + 'driver011': ['A011.hs'], + 'driver012': ['A012.hs'], + 'driver013': ['A013.hs'], + 'driver014': ['A014.hs'], + 'driver015': ['A015.hs'], + 'driver016': ['F016.hs'], + 'driver017': ['F017.hs'], + 'driver018': ['F018.hs'], + 'driver018a': ['F018a.hs'], + 'driver019': ['F019.hs'], + 'driver021': ['B021/'], + 'driver022': ['B022/'], + 'driver023': ['B023/'], + 'driver024': ['B024/'], + 'driver025': ['B025/'], + 'driver026': ['d026/'], + 'driver027': ['B027/'], + 'driver028': ['B028/'], + 'driver031': ['A031.hs'], + 'driver032': ['A032.hs'], + 'driver033': ['A033.hs'], + 'driver034': ['F034.hs'], + 'driver035': ['F035.hs'], + 'driver041': ['B041/'], + 'driver042': ['B042/'], + 'driver042stub': ['B042stub/'], + 'driver043': ['B043/'], + 'driver044': ['B044/'], + 'driver045': ['B045/'], + 'driver051': ['d051_1/', 'd051_2/'], + 'driver052': ['d052_1/', 'd052_2/'], + 'driver053': ['d053_1/', 'd053_2/'], + 'driver061a': ['A061a.hs'], + 'driver061b': ['A061b.hs'], + 'driver063': ['D063.hs'], + 'driver064': ['A064.hs'], + 'driver065': ['A065.hs'], + 'driver066': ['A066.hs'], + 'driver067': ['A067.hs'], + 'driver070': ['A070.hs'], + 'driver071': ['A071.hs'], + 'driver100': ['overlap/'], + 'driver200': ['A200.hs', 'B200/', 'D200.hs'], + 'dynamicToo001': ['A.hs', 'B.hs', 'B1.hs', 'B2.hs', 'C.hs'], + 'dynamicToo002': ['A.hs', 'B.hs', 'C.hs'], + 'dynamicToo003': ['A003.hs'], + 'dynamicToo004': ['Setup.hs', 'pkg1/', 'pkg1dyn/', 'pkg2/', 'prog.hs'], + 'dynamicToo005': ['A005.hsig'], + 'dynamicToo006': ['A.hsig', 'B.hs'], + 'dynamic_flags_001': ['A.hs', 'B.hs', 'C.hs'], + 'dynamic_flags_002A': ['A_First.hs', 'A_Main.hs', 'A_Second.hs'], + 'dynamic_flags_002B': ['B_First.hs', 'B_Main.hs', 'B_Second.hs'], + 'dynamic_flags_002C': ['C_Child.hs', 'C_Main.hs'], + 'dynamic_flags_002D': ['D_Child.hs', 'D_Main.hs'], + 'dynamic_flags_002Many': ['ManyFirst.hs', 'ManySecond.hs', 'ManyThird.hs'], + 'dynbrk001': ['../QSort.hs'], + 'dynbrk002': ['../QSort.hs'], + 'dynbrk004': ['../mdo.hs'], + 'dynbrk005': ['TupleN.hs'], + 'encoding004': ['encoded-data/'], + 'enum01': ['enum_processor.py'], + 'enum02': ['enum_processor.py'], + 'enum03': ['enum_processor.py'], + 'exampleTest': ['AnnotationTuple.hs'], + 'fast2haskell': ['Fast2haskell.hs', 'Main.hs'], + 'ffi018_ghci': ['ffi018.h'], + 'frontend01': ['FrontendPlugin.hs'], + 'fun_insts': ['Main.hs'], + 'gadt17': ['Gadt17_help.hs'], + 'gadt23': ['Gadt23_AST.hs'], + 'galois_raytrace': ['CSG.hs', 'Construct.hs', 'Data.hs', 'Eval.hs', 'Geometry.hs', 'Illumination.hs', 'Intersections.hs', 'Interval.hs', 'Main.hs', 'Misc.hs', 'Parse.hs', 'Primitives.hs', 'Surface.hs', 'galois.gml'], + 'getargs': ['../getargs.hs'], + 'ghci.prog007': ['A.hs', 'B.hs', 'C.hs', 'C.hs-boot'], + 'ghci.prog008': ['A.hs'], + 'ghci.prog009': ['A1.hs', 'A2.hs', 'A3.hs', 'B.hs'], + 'ghci025': ['Ghci025B.hs', 'Ghci025C.hs', 'Ghci025D.hs'], + 'ghci026': ['../prog002'], + 'ghci038': ['../shell.hs'], + 'ghci058': ['../shell.hs'], + 'ghcilink001': ['TestLink.hs', 'f.c'], + 'ghcilink002': ['TestLink.hs', 'f.c'], + 'ghcilink004': ['TestLink.hs', 'f.c'], + 'ghcilink005': ['TestLink.hs', 'f.c'], + 'ghcpkg01': ['test.pkg', 'test2.pkg', 'test3.pkg'], + 'ghcpkg03': ['test.pkg', 'test2.pkg', 'test4.pkg'], + 'ghcpkg04': ['test.pkg', 'test5.pkg'], + 'ghcpkg05': ['test2.pkg', 'test3.pkg'], + 'ghcpkg06': ['test.pkg', 'testdup.pkg'], + 'ghcpkg07': ['test.pkg', 'test7a.pkg', 'test7b.pkg'], + 'haddock.Cabal': ['../../../../libraries/Cabal/Cabal/dist-install/haddock.t'], + 'haddock.Test': ['Hidden.hs', 'Test.hs', 'Visible.hs'], + 'haddock.base': ['../../../../libraries/base/dist-install/haddock.t'], + 'haddock.compiler': ['../../../../compiler/stage2/haddock.t'], + 'heapprof002': ['heapprof001.hs'], + 'hist001': ['../Test3.hs'], + 'hpc001': ['../hpcrun.pl'], + 'hpc_draft': ['.hpc/Main.mix', 'hpc001.hs', 'hpc_sample.tix'], + 'hpc_fork': ['../hpcrun.pl'], + 'hpc_ghc_ghci': ['A.hs', 'B.hs'], + 'hpc_hand_overlay': ['.hpc/Main.mix', 'hand_overlay.ovr', 'hpc001.hs', 'hpc_sample.tix'], + 'hpc_markup_001': ['.hpc/Main.mix', 'hpc001.hs', 'hpc_sample.tix'], + 'hpc_markup_002': ['.hpc/Main.mix', 'hpc001.hs', 'hpc_sample.tix'], + 'hpc_markup_multi_001': ['../Geometry.hs', '.hpc/', 'hpc_sample.tix'], + 'hpc_markup_multi_002': ['../CSG.hs', '../Construct.hs', '../Data.hs', '../Eval.hs', '../Geometry.hs', '../Illumination.hs', '../Intersections.hs', '../Interval.hs', '../Main.hs', '../Misc.hs', '../Parse.hs', '../Pixmap.hs', '../Primitives.hs', '../RayTrace.hs', '../Surface.hs', '.hpc/', 'hpc_sample.tix'], + 'hpc_markup_multi_003': ['../CSG.hs', '../Construct.hs', '../Data.hs', '../Eval.hs', '../Geometry.hs', '../Illumination.hs', '../Intersections.hs', '../Interval.hs', '../Main.hs', '../Misc.hs', '../Parse.hs', '../Pixmap.hs', '../Primitives.hs', '../RayTrace.hs', '../Surface.hs', '.hpc/', 'hpc_sample.tix'], + 'hpc_overlay': ['.hpc/Main.mix', 'hpc001.hs', 'hpc_sample.tix', 'sample_overlay.ovr'], + 'hpc_overlay2': ['.hpc/Main.mix', 'hpc001.hs', 'hpc_sample.tix', 'sample_overlay.ovr'], + 'hpc_raytrace': ['../hpcrun.pl', 'CSG.hs', 'Construct.hs', 'Data.hs', 'Eval.hs', 'Geometry.hs', 'Illumination.hs', 'Intersections.hs', 'Interval.hs', 'Main.hs', 'Misc.hs', 'Parse.hs', 'Primitives.hs', 'Surface.hs', 'galois.gml', 'galois.sample'], + 'hpc_report_001': ['.hpc/Main.mix', 'hpc_sample.tix'], + 'hpc_report_002': ['.hpc/Main.mix', 'hpc_sample.tix'], + 'hpc_report_003': ['.hpc/Main.mix', 'hpc_sample.tix'], + 'hpc_report_multi_001': ['.hpc/Geometry.mix', 'hpc_sample.tix'], + 'hpc_report_multi_002': ['.hpc/', 'hpc_sample.tix'], + 'hpc_report_multi_003': ['.hpc/Geometry.mix', 'hpc_sample.tix'], + 'hpc_show': ['.hpc/Main.mix', 'hpc_sample.tix'], + 'hpc_show_multi_001': ['.hpc/', 'hpc_sample.tix'], + 'hpc_show_multi_002': ['.hpc/Geometry.mix', 'hpc_sample.tix'], + 'hs-boot': ['A.hs', 'A.hs-boot', 'B.hs', 'C.hs', 'Main.hs'], + 'impexp': ['Exp.hs', 'Imp.hs'], + 'ind2': ['Ind2_help.hs'], + 'jl_defaults': ['Main.hs'], + 'joao-circular': ['Data_Lazy.hs', 'Funcs_Lexer.hs', 'Funcs_Parser_Lazy.hs', 'LrcPrelude.hs', 'Main.hs', 'Visfun_Lazy.hs', 'inp'], + 'jq_readsPrec': ['Main.hs'], + 'jtod_circint': ['Bit.hs', 'LogFun.hs', 'Main.hs', 'Signal.hs'], + 'jules_xref': ['Main.hs'], + 'jules_xref2': ['Main.hs'], + 'landmines': ['MineFixity.hs', 'MineKind.hs', 'MineNames.hs', 'MineType.hs'], + 'launchbury': ['Main.hs'], + 'lazy-bs-alloc': ['../../numeric/should_run/arith011.stdout'], + 'lennart_range': ['Main.hs'], + 'lex': ['Main.hs'], + 'life_space_leak': ['Main.hs'], + 'linker_error1': ['linker_error.c'], + 'linker_error2': ['linker_error.c'], + 'linker_error3': ['linker_error.c'], + 'linker_unload': ['LinkerUnload.hs', 'Test.hs'], + 'listCommand001': ['../Test3.hs'], + 'listcomps': ['ListComprehensions.hs'], + 'literals': ['LiteralsTest.hs'], + 'load_short_name': ['A.c'], + 'maessen_hashtab': ['Data/', 'HashTest.hs'], + 'memo001': ['Memo1.lhs'], + 'memo002': ['Memo2.lhs'], + 'mod101': ['Mod101_AuxA.hs', 'Mod101_AuxB.hs'], + 'mod102': ['Mod102_AuxA.hs', 'Mod102_AuxB.hs'], + 'mod114': ['Mod114_Help.hs'], + 'mod115': ['Mod115_A.hs', 'Mod115_B.hs'], + 'mod117': ['Mod117_A.hs', 'Mod117_B.hs'], + 'mod118': ['Mod118_A.hs', 'Mod118_B.hs'], + 'mod119': ['Mod119_A.hs', 'Mod119_B.hs'], + 'mod120': ['Mod120_A.hs'], + 'mod121': ['Mod121_A.hs'], + 'mod122': ['Mod122_A.hs'], + 'mod123': ['Mod123_A.hs'], + 'mod124': ['Mod124_A.hs'], + 'mod125': ['Mod125_A.hs'], + 'mod126': ['Mod126_A.hs'], + 'mod127': ['Mod127_A.hs'], + 'mod128': ['Mod128_A.hs'], + 'mod131': ['Mod131_A.hs', 'Mod131_B.hs'], + 'mod132': ['Mod132_A.hs', 'Mod132_B.hs'], + 'mod136': ['Mod136_A.hs'], + 'mod137': ['Mod137_A.hs'], + 'mod138': ['Mod138_A.hs'], + 'mod139': ['Mod139_A.hs', 'Mod139_B.hs'], + 'mod140': ['Mod140_A.hs'], + 'mod141': ['Mod141_A.hs'], + 'mod142': ['Mod142_A.hs'], + 'mod143': ['Mod143_A.hs'], + 'mod144': ['Mod144_A.hs'], + 'mod145': ['Mod145_A.hs'], + 'mod146': ['Mod145_A.hs'], + 'mod147': ['Mod147_A.hs'], + 'mod157': ['Mod157_A.hs', 'Mod157_B.hs', 'Mod157_C.hs', 'Mod157_D.hs'], + 'mod158': ['Mod157_A.hs', 'Mod157_B.hs', 'Mod157_C.hs', 'Mod157_D.hs'], + 'mod159': ['Mod159_A.hs', 'Mod159_B.hs', 'Mod159_C.hs', 'Mod159_D.hs'], + 'mod160': ['Mod159_A.hs', 'Mod159_B.hs', 'Mod159_C.hs', 'Mod159_D.hs'], + 'mod162': ['Mod162_A.hs'], + 'mod163': ['Mod163_A.hs'], + 'mod164': ['Mod164_A.hs', 'Mod164_B.hs'], + 'mod165': ['Mod164_A.hs', 'Mod164_B.hs'], + 'mod166': ['Mod164_A.hs', 'Mod164_B.hs'], + 'mod167': ['Mod164_A.hs', 'Mod164_B.hs'], + 'mod170': ['Mod170_A.hs'], + 'mod171': ['Mod171_A.hs', 'Mod171_B.hs'], + 'mod172': ['Mod172_B.hs', 'Mod172_C.hs'], + 'mod173': ['Mod173_Aux.hs'], + 'mod175': ['Test.hs', 'Test2.hs'], + 'mod178': ['Mod178_2.hs'], + 'mod179': ['Mod179_A.hs'], + 'mod180': ['Mod180_A.hs', 'Mod180_B.hs'], + 'north_array': ['Main.hs'], + 'okeefe_neural': ['Main.hs'], + 'overloadedlabelsrun04': ['OverloadedLabelsRun04_A.hs'], + 'overloadedrecfldsfail04': ['OverloadedRecFldsFail04_A.hs'], + 'overloadedrecfldsfail06': ['OverloadedRecFldsFail06_A.hs'], + 'overloadedrecfldsfail10': ['OverloadedRecFldsFail10_A.hs', 'OverloadedRecFldsFail10_B.hs', 'OverloadedRecFldsFail10_C.hs'], + 'overloadedrecfldsfail11': ['OverloadedRecFldsFail11_A.hs'], + 'overloadedrecfldsfail12': ['OverloadedRecFldsFail12_A.hs'], + 'overloadedrecfldsrun02': ['OverloadedRecFldsRun02_A.hs'], + 'p10': ['D.hs'], + 'p11': ['E.hs'], + 'p13': ['P13_A.hs'], + 'p7': ['A.hs'], + 'p8': ['B.hs'], + 'p9': ['C.hs'], + 'parseTree': ['AnnotationTuple.hs'], + 'parsed': ['LiteralsTest2.hs'], + 'parser.prog001': ['Read006.hs', 'Read007.hs'], + 'pat-syn-bundle': ['Bundle1.hs', 'BundleInternal1.hs'], + 'pat-syn-trans-bundle': ['Bundle.hs', 'BundleInternal.hs', 'TransBundle.hs'], + 'pkg02': ['A.hs', 'Foreign.hs'], + 'plugins01': ['simple-plugin/'], + 'plugins02': ['simple-plugin/'], + 'plugins03': ['simple-plugin/'], + 'plugins04': ['HomePackagePlugin.hs'], + 'plugins05': ['HomePackagePlugin.hs'], + 'plugins06': ['LinkerTicklingPlugin.hs'], + 'plugins07': ['rule-defining-plugin/'], + 'print002': ['../Test.hs'], + 'print003': ['../Test.hs'], + 'print005': ['../QSort.hs'], + 'print006': ['../Test.hs'], + 'print007': ['../Test.hs'], + 'print008': ['../Test.hs'], + 'print010': ['../Test.hs'], + 'print011': ['../Test.hs'], + 'print012': ['../GADT.hs', '../Test.hs'], + 'print013': ['../GADT.hs'], + 'print014': ['../GADT.hs'], + 'print016': ['../Test.hs'], + 'print017': ['../Test.hs'], + 'print018': ['../Test.hs'], + 'print019': ['../Test.hs'], + 'print020': ['../HappyTest.hs'], + 'print023': ['../Test.hs'], + 'print024': ['../Test.hs'], + 'print030': ['print029.hs'], + 'print032': ['print029.hs'], + 'print034': ['../GADT.hs', '../Test.hs'], + 'print035': ['../Unboxed.hs'], + 'prog001': ['../shell.hs', 'A.hs', 'B.hs', 'C1.hs', 'D1.hs', 'D2.hs'], + 'prog002': ['../shell.hs', 'A1.hs', 'A2.hs', 'B.hs', 'C.hs', 'D.hs'], + 'prog003': ['../shell.hs', 'A.hs', 'B.hs', 'C.hs', 'D1.hs', 'D2.hs'], + 'prog005': ['A1.hs', 'B.hs'], + 'prog006': ['A.hs', 'Boot.hs-boot', 'Boot1.hs', 'Boot2.hs'], + 'prog012': ['../shell.hs', 'Bar1.hs', 'Bar2.hs', 'Foo.hs', 'FooBar.hs'], + 'prog013': ['Bad.hs', 'Good.hs'], + 'prog014': ['Primop.hs', 'dummy.c'], + 'prog015': ['Level1.hs', 'Level2/', 'TopLevel.hs'], + 'prog016': ['Level1.hs', 'Level2/', 'TopLevel.hs'], + 'prog017': ['Level1.hs', 'Level2/', 'TopLevel.hs'], + 'qq005': ['Expr.hs', 'Main.hs'], + 'qq006': ['Expr.hs', 'Main.hs'], + 'qq007': ['QQ.hs', 'Test.hs'], + 'qq008': ['QQ.hs', 'Test.hs'], + 'qq009': ['QQ.hs', 'Test.hs'], + 'recomp001': ['A.hs', 'B1.hs', 'B2.hs', 'C.hs'], + 'recomp002': ['Q.hs', 'W.hs', 'W.hs-boot'], + 'recomp003': ['A.hs'], + 'recomp004': ['Main.hs', 'c.h', 'c1.c', 'c2.c'], + 'recomp005': ['A.hs', 'B.hs', 'C1.hs', 'C2.hs', 'D.hs', 'E.hs'], + 'recomp006': ['A.hs', 'B1.hs', 'B2.hs'], + 'recomp007': ['Setup.hs', 'a1/', 'a2/', 'b/'], + 'recomp008': ['A1.hs', 'A2.hs', 'B.hs', 'Main.hs'], + 'recomp009': ['Main.hs', 'Sub1.hs', 'Sub2.hs'], + 'recomp010': ['Main.hs', 'X1.hs', 'X2.hs'], + 'recomp011': ['Main.hs'], + 'recomp015': ['Generate.hs'], + 'record_upd': ['Main.hs'], + 'rename.prog001': ['Rn037Help.hs', 'rn037.hs'], + 'rename.prog002': ['Rn037Help.hs', 'rnfail037.hs'], + 'rename.prog003': ['A.hs', 'B.hs'], + 'rename.prog004': ['A.hs', 'B.hs', 'C.hs'], + 'rename.prog005': ['VersionGraphClient.hs', 'VersionGraphClient.hs-boot', 'View.hs', 'ViewType.hs'], + 'retc001': ['A.hs', 'B1.hs', 'B2.hs', 'C.hs'], + 'retc002': ['Q.hs', 'W.hs', 'W.hs-boot'], + 'retc003': ['A.hs'], + 'rittri': ['Main.hs'], + 'rn.prog006': ['A.hs', 'B/', 'Main.hs', 'pwd.hs'], + 'rn009': ['Imp10Aux.hs', 'Imp10Aux.hs-boot'], + 'rn011': ['Imp100Aux.hs', 'Imp100Aux.hs-boot'], + 'rn012': ['Imp500Aux.hs', 'Imp500Aux.hs-boot'], + 'rn017': ['RnAux017.hs', 'RnAux017.hs-boot'], + 'rn042': ['Rn042_A.hs'], + 'rn043': ['Rn043_A.hs', 'Rn043_B.hs'], + 'rn044': ['Rn044_A.hs', 'Rn044_B.hs'], + 'rn050': ['Rn050_A.hs'], + 'rn052': ['Rn052Aux.hs'], + 'rn053': ['Rn053_A.hs', 'Rn053_B.hs'], + 'rn059': ['Rn059_A.hs', 'Rn059_B.hs'], + 'rn065': ['Rn065A.hs'], + 'rn066': ['Rn066_A.hs'], + 'rn067': ['Rn067_A.hs'], + 'rnfail040': ['Rnfail040_A.hs'], + 'rnfail047': ['RnFail047_A.hs', 'RnFail047_A.hs-boot'], + 'rnfail055': ['RnFail055.hs', 'RnFail055.hs-boot', 'RnFail055_aux.hs'], + 'rtsopts001': ['rtsOpts.hs'], + 'safePkg01': ['M_SafePkg.hs', 'M_SafePkg2.hs', 'M_SafePkg3.hs', 'M_SafePkg4.hs', 'M_SafePkg5.hs', 'M_SafePkg6.hs', 'M_SafePkg7.hs', 'M_SafePkg8.hs', 'Setup.hs', 'p.cabal'], + 'sanders_array': ['Main.hs'], + 'seward-space-leak': ['Main.lhs'], + 'shared001': ['Shared001.hs'], + 'sigcabal01': ['Main.hs', 'Setup.hs', 'p/'], + 'sigof01': ['A.hs', 'B.hsig', 'Main.hs'], + 'sigof01m': ['A.hs', 'B.hsig', 'Main.hs'], + 'sigof02': ['Main.hs', 'Map.hsig'], + 'sigof02d': ['Double.hs', 'Map.hsig', 'MapAsSet.hsig'], + 'sigof02dm': ['Double.hs', 'Map.hsig', 'MapAsSet.hsig'], + 'sigof02dmt': ['Double.hs', 'Map.hsig', 'MapAsSet.hsig'], + 'sigof02dt': ['Double.hs', 'Map.hsig', 'MapAsSet.hsig'], + 'sigof02m': ['Main.hs', 'Map.hsig'], + 'sigof02mt': ['Main.hs', 'Map.hsig'], + 'sigof02t': ['Main.hs', 'Map.hsig'], + 'sigof03': ['A.hs', 'ASig1.hsig', 'ASig2.hsig', 'Main.hs'], + 'sigof03m': ['A.hs', 'ASig1.hsig', 'ASig2.hsig', 'Main.hs'], + 'sigof04': ['Sig.hsig'], + 'simpl020': ['Simpl020_A.hs'], + 'simpl021': ['Simpl021A.hs', 'Simpl021B.hs'], + 'simplCore.oneShot': ['OneShot1.hs', 'OneShot2.hs'], + 'simplCore.prog001': ['Simpl006Help.hs', 'simpl006.hs'], + 'simplCore.prog002': ['Simpl009Help.hs', 'simpl009.hs'], + 'stack002': ['stack001.hs'], + 'static001': ['Static001.hs'], + 'strict_anns': ['Main.hs'], + 'tc170': ['Tc170_Aux.hs'], + 'tc173': ['Tc173a.hs', 'Tc173b.hs'], + 'tc239': ['Tc239_Help.hs'], + 'tc245': ['Tc245_A.hs'], + 'tc251': ['Tc251_Help.hs'], + 'tc263': ['Tc263_Help.hs'], + 'tcfail186': ['Tcfail186_Help.hs'], + 'tcrun025': ['TcRun025_B.hs'], + 'tcrun038': ['TcRun038_B.hs'], + 'testwsdeque': ['../../../rts/WSDeque.h'], + 'thurston-modular-arith': ['Main.hs', 'TypeVal.hs'], + 'tough': ['../hpcrun.pl'], + 'tough2': ['../hpcrun.pl', 'subdir/'], + 'typecheck.prog001': ['A.hs', 'B.hs', 'C.hs'], + 'typecheck.prog002': ['A.hs', 'B.hs'], + 'typecheck.testeq1': ['FakePrelude.hs', 'Main.hs', 'TypeCast.hs', 'TypeEq.hs'], + 'write_interface_make': ['A011.hs'], + 'write_interface_oneshot': ['A011.hs'], +} diff --git a/testsuite/driver/runtests.py b/testsuite/driver/runtests.py index 0f751f2151..496fb35d3b 100644 --- a/testsuite/driver/runtests.py +++ b/testsuite/driver/runtests.py @@ -9,6 +9,8 @@ import os import string import getopt import platform +import shutil +import tempfile import time import re @@ -277,10 +279,31 @@ else: # set stdout to unbuffered (is this the best way to do it?) sys.stdout = os.fdopen(sys.__stdout__.fileno(), "w", 0) +# Create a unique temporary directory inside '/tmp/ghctest'. +ghctestdir = os.path.join(tempfile.gettempdir(), 'ghctest') +# Don't start from scratch (i.e. don't rmtree(ghctestdir)). Running +# 'make test' while another 'make test' hasn't completed yet should work. +#shutil.rmtree(ghctestdir, ignore_errors=True) +mkdirp(ghctestdir) +tempdir = normalise_slashes_(tempfile.mkdtemp('', '', dir=ghctestdir)) + +def cleanup_and_exit(exitcode): + if config.cleanup: + shutil.rmtree(tempdir, ignore_errors=True) + try: + os.rmdir(ghctestdir) + except OSError as e: + if e.errno == errno.ENOTEMPTY: + # Only delete ghctestdir if it is empty. + pass + else: + raise + exit(exitcode) + # First collect all the tests to be run for file in t_files: if_verbose(2, '====> Scanning %s' % file) - newTestDir(os.path.dirname(file)) + newTestDir(tempdir, os.path.dirname(file)) try: exec(open(file).read()) except Exception: @@ -291,7 +314,7 @@ for file in t_files: if config.only: # See Note [Mutating config.only] sys.stderr.write("ERROR: tests not found: {0}\n".format(list(config.only))) - sys.exit(1) + cleanup_and_exit(1) if config.list_broken: global brokens @@ -327,5 +350,4 @@ else: if config.summary_file != '': summary(t, open(config.summary_file, 'w')) -sys.exit(0) - +cleanup_and_exit(0) diff --git a/testsuite/driver/testglobals.py b/testsuite/driver/testglobals.py index d1976923a0..9f88acf445 100644 --- a/testsuite/driver/testglobals.py +++ b/testsuite/driver/testglobals.py @@ -210,6 +210,9 @@ class TestOptions: # extra files to clean afterward self.clean_files = [] + # extra files to copy to the testdir + self.extra_files = [] + # which -t numeric fields do we want to look at, and what bounds must # they fall within? # Elements of these lists should be things like diff --git a/testsuite/driver/testlib.py b/testsuite/driver/testlib.py index a7221847a7..f2e8a3d7d1 100644 --- a/testsuite/driver/testlib.py +++ b/testsuite/driver/testlib.py @@ -22,6 +22,7 @@ import subprocess from testglobals import * from testutil import * +from extra_files import extra_src_files try: basestring @@ -275,6 +276,12 @@ def extra_clean( files ): def _extra_clean( name, opts, v ): opts.clean_files = v +def extra_files(files): + return lambda name, opts: _extra_files(name, opts, files) + +def _extra_files(name, opts, files): + opts.extra_files.extend(files) + # ----- def stats_num_field( field, expecteds ): @@ -543,13 +550,27 @@ def executeSetups(fs, name, opts): # ----------------------------------------------------------------------------- # The current directory of tests -def newTestDir( dir ): +def newTestDir(tempdir, dir): + # Hack. A few tests depend on files in ancestor directories + # (e.g. extra_files(['../../../../libraries/base/dist-install/haddock.t'])) + # Make sure tempdir is sufficiently "deep", such that copying/linking those + # files won't cause any problems. + # + # If you received a framework failure about adding an extra level: + # * add one extra '../' to the startswith('../../../../../') in do_test + # * add one more number here: + tempdir = os.path.join(tempdir, '1', '2', '3') + global thisdir_settings # reset the options for this test directory - thisdir_settings = lambda name, opts, dir=dir: _newTestDir( name, opts, dir ) + def settings(name, opts, tempdir=tempdir, dir=dir): + return _newTestDir(name, opts, tempdir, dir) + thisdir_settings = settings -def _newTestDir( name, opts, dir ): - opts.testdir = dir + +def _newTestDir(name, opts, tempdir, dir): + opts.srcdir = os.path.join(os.getcwd(), dir) + opts.testdir = os.path.join(tempdir, dir, name) opts.compiler_always_flags = config.compiler_always_flags # ----------------------------------------------------------------------------- @@ -683,18 +704,48 @@ def test_common_work (name, opts, func, args): other_ways = list(filter(lambda way: way not in opts.extra_ways, do_ways)) do_ways = other_ways[:1] + explicit_ways + # Find all files in the source directory that this test + # depends on. Do this only once for all ways. + # Generously add all filenames that start with the name of + # the test to this set, as a convenience to test authors. + # They will have to use the `extra_files` setup function to + # specify all other files that their test depends on (but + # this seems to be necessary for only about 10% of all + # tests). + files = set((f for f in os.listdir(opts.srcdir) + if f.startswith(name))) + for filename in (opts.extra_files + extra_src_files.get(name, [])): + if filename.startswith('../../../../../'): + framework_fail(name, 'whole-test', + 'add extra level to testlib.py:newTestDir for: ' + filename) + + elif filename.startswith('/'): + framework_fail(name, 'whole-test', + 'no absolute paths in extra_files please: ' + filename) + + elif '*' in filename: + # Don't use wildcards in extra_files too much, as + # globbing is slow. + files.update((os.path.relpath(f, opts.srcdir) + for f in glob.iglob(in_srcdir(filename)))) + + else: + files.add(filename) + if not config.clean_only: # Run the required tests... for way in do_ways: if stopping(): break - do_test (name, way, func, args) + do_test(name, way, func, args, files) for way in all_ways: if way not in do_ways: skiptest (name,way) if config.cleanup and (config.clean_only or do_ways): + cleanup() + elif False: # TODO. Delete this code. pretest_cleanup(name) clean([name + suff for suff in [ '', '.exe', '.exe.manifest', '.genscript', @@ -755,6 +806,7 @@ def test_common_work (name, opts, func, args): framework_fail(name, 'runTest', 'Unhandled exception: ' + str(e)) def clean(strs): + return # TODO. Delete this function. for str in strs: if (str.endswith('.package.conf') or str.startswith('package.conf.') and not str.endswith('/*')): @@ -782,7 +834,9 @@ def clean_full_path(name): if e2.errno != errno.ENOENT: print(e2) -def do_test(name, way, func, args): +def do_test(name, way, func, args, files): + opts = getTestOpts() + full_name = name + '(' + way + ')' try: @@ -792,6 +846,66 @@ def do_test(name, way, func, args): t.n_unexpected_failures, \ t.n_framework_failures])) + # Clean up prior to the test, so that we can't spuriously conclude + # that it passed on the basis of old run outputs. + cleanup() + + # Link all source files for this test into a new directory in + # /tmp, and run the test in that directory. This makes it + # possible to run tests in parallel, without modification, that + # would otherwise (accidentally) write to the same output file. + # It also makes it easier to keep the testsuite clean. + + for filename in files: + src = in_srcdir(filename) + dst = in_testdir(filename) + + if os.path.isfile(src): + dirname = os.path.dirname(dst) + if dirname: + mkdirp(dirname) + try: + link_or_copy_file(src, dst) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isfile(dst): + # Some tests depend on files from ancestor + # directories (e.g. '../shell.hs'). It is + # possible such a file was already copied over + # for another test, since cleanup() doesn't + # delete them. + pass + else: + raise + elif os.path.isdir(src): + os.makedirs(dst) + lndir(src, dst) + else: + if not config.haddock and os.path.splitext(filename)[1] == '.t': + # When using a ghc built without haddock support, .t + # files are rightfully missing. Don't + # framework_fail. Test will be skipped later. + pass + else: + framework_fail(name, way, + 'extra_file does not exist: ' + filename) + + if not files: + # Always create the testdir, even when no files were copied + # (because user forgot to specify extra_files setup function), to + # prevent the confusing error: can't cd to <testdir>. + os.makedirs(opts.testdir) + + if func.__name__ == 'run_command' or opts.pre_cmd: + # When running 'MAKE' make sure 'TOP' still points to the + # root of the testsuite. + src_makefile = in_srcdir('Makefile') + dst_makefile = in_testdir('Makefile') + if os.path.exists(src_makefile): + with open(src_makefile, 'r') as src: + makefile = re.sub('TOP=.*', 'TOP=' + config.top, src.read(), 1) + with open(dst_makefile, 'w') as dst: + dst.write(makefile) + if config.use_threads: t.lock.release() @@ -1262,7 +1376,7 @@ def simple_run(name, way, prog, extra_run_opts): use_stdin = opts.stdin else: stdin_file = add_suffix(name, 'stdin') - if os.path.exists(in_testdir(stdin_file)): + if os.path.exists(in_srcdir(stdin_file)): use_stdin = stdin_file else: use_stdin = '/dev/null' @@ -1393,9 +1507,9 @@ def interpreter_run( name, way, extra_hc_opts, compile_only, top_mod ): # figure out what to use for stdin if getTestOpts().stdin != '': - stdin_file = in_testdir(getTestOpts().stdin) + stdin_file = in_srcdir(opts.stdin) else: - stdin_file = qualify(name, 'stdin') + stdin_file = in_srcdir(name, 'stdin') if os.path.exists(stdin_file): os.system('cat ' + stdin_file + ' >>' + qscriptname) @@ -1603,11 +1717,12 @@ def check_prof_ok(name, way): def compare_outputs(way, kind, normaliser, expected_file, actual_file, whitespace_normaliser=lambda x:x): - expected_path = in_testdir(expected_file) + expected_path = in_srcdir(expected_file) actual_path = in_testdir(actual_file) if os.path.exists(expected_path): expected_str = normaliser(read_no_crs(expected_path)) + # Create the .normalised file in the testdir, not in the srcdir. expected_normalised_file = add_suffix(expected_file, 'normalised') expected_normalised_path = in_testdir(expected_normalised_file) else: @@ -1651,7 +1766,7 @@ def compare_outputs(way, kind, normaliser, expected_file, actual_file, return 1 elif config.accept: if_verbose(1, 'No output. Deleting {0}.'.format(expected_path)) - rm_no_fail(expected_path) + os.remove(expected_path) return 1 else: return 0 @@ -2108,6 +2223,7 @@ if config.have_profiling: gsNotWorking(); def rm_no_fail( file ): + return # TODO. Delete this function. try: os.remove( file ) finally: @@ -2138,11 +2254,13 @@ def replace_suffix( name, suffix ): return base + '.' + suffix def in_testdir(name, suffix=''): - return getTestOpts().testdir + '/' + add_suffix(name, suffix) + return os.path.join(getTestOpts().testdir, add_suffix(name, suffix)) def qualify( name, suff ): return in_testdir(add_suffix(name, suff)) +def in_srcdir(name, suffix=''): + return os.path.join(getTestOpts().srcdir, add_suffix(name, suffix)) # Finding the sample output. The filename is of the form # @@ -2150,7 +2268,7 @@ def qualify( name, suff ): # def find_expected_file(name, suff): basename = add_suffix(name, suff) - basepath = in_testdir(basename) + basepath = in_srcdir(basename) files = [(platformSpecific, basename + ws + plat) for (platformSpecific, plat) in [(1, '-' + config.platform), @@ -2162,7 +2280,7 @@ def find_expected_file(name, suff): dir = [normalise_slashes_(d) for d in dir] for (platformSpecific, f) in files: - if in_testdir(f) in dir: + if in_srcdir(f) in dir: return (platformSpecific,f) return (0, basename) @@ -2170,6 +2288,7 @@ def find_expected_file(name, suff): # Clean up prior to the test, so that we can't spuriously conclude # that it passed on the basis of old run outputs. def pretest_cleanup(name): + return # TODO. Delete this function. if getTestOpts().outputdir != None: odir = in_testdir(getTestOpts().outputdir) try: @@ -2191,6 +2310,10 @@ def pretest_cleanup(name): # rm_nofail(qualify("")) # not interested in the return code +def cleanup(): + shutil.rmtree(getTestOpts().testdir, ignore_errors=True) + + # ----------------------------------------------------------------------------- # Return a list of all the files ending in '.T' below directories roots. diff --git a/testsuite/driver/testutil.py b/testsuite/driver/testutil.py index 029a3b6cb9..563ba3646c 100644 --- a/testsuite/driver/testutil.py +++ b/testsuite/driver/testutil.py @@ -1,7 +1,10 @@ # ----------------------------------------------------------------------------- # Utils +import errno +import os import subprocess +import shutil def version_to_ints(v): return [ int(x) for x in v.split('.') ] @@ -36,3 +39,32 @@ def getStdout(cmd_and_args): if stderr: raise Exception("stderr from command: " + str(cmd_and_args)) return stdout + +def mkdirp(path): + try: + os.makedirs(path) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise + +def lndir(srcdir, dstdir): + # Create symlinks for all files in src directory. + # Not all developers might have lndir installed. + # os.system('lndir -silent {0} {1}'.format(srcdir, dstdir)) + for filename in os.listdir(srcdir): + src = os.path.join(srcdir, filename) + dst = os.path.join(dstdir, filename) + if os.path.isfile(src): + link_or_copy_file(src, dst) + else: + os.mkdir(dst) + lndir(src, dst) + +# On Windows, os.symlink is not defined. Except when using msys2, as ghc +# does. Then it copies the source file, instead of creating a symbolic +# link to it. We define the following function to make this magic more +# explicit/discoverable. You are enouraged to use it instead of +# os.symlink. +link_or_copy_file = getattr(os, "symlink", shutil.copyfile) diff --git a/testsuite/tests/plugins/all.T b/testsuite/tests/plugins/all.T index 7cf412c260..caa831efc6 100644 --- a/testsuite/tests/plugins/all.T +++ b/testsuite/tests/plugins/all.T @@ -5,18 +5,19 @@ def f(name, opts): setTestOpts(f) test('plugins01', - [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins01'), + [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins01 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C simple-plugin clean.plugins01')], run_command, ['$MAKE -s --no-print-directory plugins01']) + test('plugins02', - [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins02'), + [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins02 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C simple-plugin clean.plugins02')], compile_fail, ['-package-db simple-plugin/pkg.plugins02/local.package.conf -fplugin Simple.BadlyTypedPlugin -package simple-plugin ' + config.plugin_way_flags]) test('plugins03', - [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins03'), + [pre_cmd('$MAKE -s --no-print-directory -C simple-plugin package.plugins03 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C simple-plugin clean.plugins03')], compile_fail, ['-package-db simple-plugin/pkg.plugins03/local.package.conf -fplugin Simple.NonExistantPlugin -package simple-plugin']) @@ -38,26 +39,26 @@ test('plugins06', multimod_compile_and_run, ['plugins06', '-package ghc']) test('plugins07', - [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.plugins07'), + [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.plugins07 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.plugins07')], run_command, ['$MAKE -s --no-print-directory plugins07']) test('T10420', - [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T10420'), + [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T10420 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.T10420')], run_command, ['$MAKE -s --no-print-directory T10420']) test('T10294', - [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294'), + [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C annotation-plugin clean.T10294'), unless(have_dynamic(),expect_broken(10301))], run_command, ['$MAKE -s --no-print-directory T10294']) test('T10294a', - [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294a'), + [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294a TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C annotation-plugin clean.T10294a')], run_command, ['$MAKE -s --no-print-directory T10294a']) @@ -69,7 +70,7 @@ test('frontend01', run_command, ['$MAKE -s --no-print-directory frontend01']) test('T11244', - [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T11244'), + [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T11244 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.T11244')], run_command, ['$MAKE -s --no-print-directory T11244']) diff --git a/testsuite/tests/simplCore/should_compile/all.T b/testsuite/tests/simplCore/should_compile/all.T index 7aba48508f..0e03b1696c 100644 --- a/testsuite/tests/simplCore/should_compile/all.T +++ b/testsuite/tests/simplCore/should_compile/all.T @@ -170,7 +170,7 @@ test('T5550', omit_ways(prof_ways), compile, ['']) test('T7865', normal, run_command, ['$MAKE -s --no-print-directory T7865']) test('T7785', only_ways(['optasm']), compile, ['-ddump-rules']) test('T7702', - [pre_cmd('$MAKE -s --no-print-directory -C T7702plugin package.T7702'), + [pre_cmd('$MAKE -s --no-print-directory -C T7702plugin package.T7702 TOP={top}'), clean_cmd('$MAKE -s --no-print-directory -C T7702plugin clean.T7702'), # we say 18mb peak allocated +/- 70% because other compiler flags have # a large effect on allocation which is hard to separate from the |