1+ package org .eclipse .golo .cli .command ;
2+
3+ import com .beust .jcommander .Parameter ;
4+ import com .beust .jcommander .Parameters ;
5+ import org .eclipse .golo .cli .command .spi .CliCommand ;
6+ import org .eclipse .golo .compiler .GoloClassLoader ;
7+ import org .eclipse .golo .compiler .GoloCompilationException ;
8+
9+ import java .io .File ;
10+ import java .io .FileInputStream ;
11+ import java .io .IOException ;
12+ import java .lang .invoke .MethodHandle ;
13+ import java .lang .invoke .MethodType ;
14+ import java .lang .reflect .Method ;
15+ import java .net .URLClassLoader ;
16+ import java .nio .file .Files ;
17+ import java .nio .file .Path ;
18+ import java .nio .file .Paths ;
19+ import java .util .*;
20+ import java .util .function .Consumer ;
21+ import java .util .stream .Stream ;
22+
23+ import static java .lang .invoke .MethodHandles .lookup ;
24+ import static java .lang .invoke .MethodType .genericMethodType ;
25+
26+ @ Parameters (commandNames = {"test" }, commandDescription = "Run golo tests" )
27+ public class TestCommand implements CliCommand {
28+
29+ public static final String TEST_METHOD_NAME = "spec" ;
30+ public static final MethodType TEST_METHOD_TYPE = genericMethodType (1 );
31+ public static final String BUILD_METHOD_NAME = "build" ;
32+
33+ @ Parameter (names = "--files" , variableArity = true , description = "Test files (*.golo and directories)" , required = true )
34+ List <String > files = new LinkedList <>();
35+
36+ @ Parameter (names = "--classpath" , variableArity = true , description = "Classpath elements (.jar and directories)" )
37+ List <String > classpath = new LinkedList <>();
38+
39+ private final GoloClassLoader loader ;
40+
41+ public TestCommand () throws Throwable {
42+ URLClassLoader primaryClassLoader = primaryClassLoader (this .classpath );
43+ Thread .currentThread ().setContextClassLoader (primaryClassLoader );
44+ this .loader = new GoloClassLoader (primaryClassLoader );
45+ }
46+
47+ private Object runner () throws Throwable {
48+ Class runnerClass = Class .forName ("gololang.testing.Runner" );
49+ //TODO replace the search with the exact signature when the Runner struct will be stabilized
50+ Method m = Arrays .asList (runnerClass .getDeclaredMethods ()).stream ().filter (method -> method .getName ().equals (BUILD_METHOD_NAME )).findFirst ().get ();
51+ MethodHandle mh = lookup ().unreflect (m );
52+ return mh .invokeExact ();
53+ }
54+
55+ @ Override
56+ public void execute () throws Throwable {
57+ Object runner = runner ();
58+ Consumer <Class > loadSpecification = clazz -> loadSpecification (runner , clazz );
59+ files .stream ()
60+ .map (Paths ::get )
61+ .flatMap (this ::treeFiles )
62+ .map (this ::pathToClass )
63+ .forEach (loadSpecification );
64+ run (runner );
65+ }
66+
67+ private Stream <Path > treeFiles (Path path ) {
68+ return listFiles (path ).flatMap (it ->
69+ it .toFile ().isDirectory () ?
70+ treeFiles (path ) :
71+ Stream .of (it )
72+ );
73+ }
74+
75+ private Stream <Path > listFiles (Path path ) {
76+ if (path .toFile ().isDirectory ()) {
77+ try {
78+ return Files .list (path ).filter (testFile -> testFile .toString ().endsWith (".golo" ));
79+ } catch (IOException e ) {
80+ System .out .println (e .getMessage ());
81+ }
82+ }
83+ return Stream .of (path );
84+ }
85+
86+ private void run (Object runner ) throws Throwable {
87+ Class augmentions = Class .forName ("gololang.testing.Runner$gololang$testing$Runner$types$Runner" );
88+ MethodHandle run = lookup ().findStatic (augmentions , "run" , genericMethodType (1 ));
89+ run .invoke (runner );
90+ }
91+
92+ //TODO refactor with CLICommand file loader
93+ private Class <?> pathToClass (Path filepath ) {
94+ File file = filepath .toFile ();
95+ try (FileInputStream in = new FileInputStream (file )) {
96+ return loader .load (file .getName (), in );
97+ } catch (GoloCompilationException e ) {
98+ handleCompilationException (e );
99+ } catch (IOException e ) {
100+ e .printStackTrace ();
101+ }
102+ return null ;
103+ }
104+
105+ //TODO refactor with CLICommand#callRun method
106+ private void loadSpecification (Object runner , Class <?> klass ) {
107+ MethodHandle mh = null ;
108+ try {
109+ mh = lookup ().findStatic (klass , TEST_METHOD_NAME , TEST_METHOD_TYPE );
110+ } catch (NoSuchMethodException e ) {
111+ System .out .println (e .getMessage ());
112+ } catch (IllegalAccessException e ) {
113+ System .out .println (e .getMessage ());
114+ }
115+ if (mh != null ) {
116+ try {
117+ mh .invoke (runner );
118+ } catch (Throwable throwable ) {
119+ throwable .printStackTrace ();
120+ }
121+ }
122+ }
123+ }
0 commit comments