1212import static org .hamcrest .Matchers .not ;
1313import static org .hamcrest .Matchers .nullValue ;
1414import static org .junit .jupiter .api .Assertions .assertEquals ;
15- import static org .junit .jupiter .api .Assertions .assertNull ;
15+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
1616import static org .junit .jupiter .api .DynamicContainer .dynamicContainer ;
1717import static org .junit .jupiter .api .DynamicTest .dynamicTest ;
1818
3636import java .util .ArrayList ;
3737import java .util .Arrays ;
3838import java .util .List ;
39- import java .util .concurrent .atomic .AtomicReference ;
4039import java .util .function .Predicate ;
4140import java .util .regex .Pattern ;
4241import java .util .stream .IntStream ;
4342import java .util .stream .Stream ;
43+ import lombok .Getter ;
4444import lombok .SneakyThrows ;
4545import lombok .extern .slf4j .Slf4j ;
4646import org .apache .commons .io .FileUtils ;
47+ import org .apache .commons .lang .UnhandledException ;
4748import org .apache .maven .cli .MavenCli ;
4849import org .codehaus .plexus .classworlds .ClassWorld ;
50+ import org .hamcrest .Matchers ;
4951import org .junit .jupiter .api .BeforeAll ;
5052import org .junit .jupiter .api .DynamicNode ;
5153import org .junit .jupiter .api .DynamicTest ;
@@ -298,14 +300,13 @@ private void verifyGeneratedClasses(File projectDir) throws Exception {
298300 new URL []{classesDir .toURI ().toURL ()},
299301 BoatSpringTemplatesTests .class .getClassLoader ()
300302 );
301- String testedModelClassName = buildTestedModelClassName ( );
302- verifyModelClassSerializesAndDeserializesFromJson (classLoader , testedModelClassName );
303+ verifyReceivableRequestModelJsonConversion ( classLoader );
304+ verifyMultiLineRequest (classLoader );
303305 }
304306
305- private void verifyModelClassSerializesAndDeserializesFromJson (ClassLoader classLoader ,
306- String testedModelClassName ) throws InterruptedException {
307+ private void verifyReceivableRequestModelJsonConversion (ClassLoader classLoader ) throws InterruptedException {
308+ String testedModelClassName = buildReceivableRequestModelClassName ();
307309 var objectMapper = new ObjectMapper ();
308- final AtomicReference <Exception > exceptionRef = new AtomicReference <>();
309310 Runnable verification = () -> {
310311 try {
311312 Class <?> modelClass = classLoader .loadClass (testedModelClassName );
@@ -332,19 +333,32 @@ private void verifyModelClassSerializesAndDeserializesFromJson(ClassLoader class
332333 assertEquals (modelClass , deserializedObject1 .getClass ());
333334
334335 } catch (Exception e ) {
335- log .warn ("Verification error" , e );
336- exceptionRef .set (e );
336+ throw new UnhandledException (e );
337337 }
338338 };
339+ runVerification (verification , classLoader );
340+ }
339341
340- runVerification (verification , classLoader ).join ();
341- assertNull (exceptionRef .get (), "Classes verification failed" );
342+ private void verifyMultiLineRequest (ClassLoader classLoader ) throws InterruptedException {
343+ String testedModelClassName = buildMultiLineRequestModelClassName ();
344+ Runnable verification = () -> {
345+ try {
346+ Class <?> modelClass = classLoader .loadClass (testedModelClassName );
347+ Constructor <?> constructor = modelClass .getConstructor ();
348+ Object modelObject = constructor .newInstance ();
349+ List <?> listProperty = (List <?>) modelClass .getDeclaredMethod ("getLines" ).invoke (modelObject );
350+ assertNotNull (listProperty );
351+ } catch (Exception e ) {
352+ throw new UnhandledException (e );
353+ }
354+ };
355+ runVerification (verification , classLoader );
342356 }
343357
344358 /**
345359 * Build proper class name for `ReceivableRequest`.
346360 */
347- private String buildTestedModelClassName () {
361+ private String buildReceivableRequestModelClassName () {
348362 var modelPackage = param .name .replace ('-' , '.' ) + ".model" ;
349363 var classNameSuffix = org .apache .commons .lang3 .StringUtils .capitalize (
350364 param .name .indexOf ('-' ) > -1
@@ -354,14 +368,21 @@ private String buildTestedModelClassName() {
354368 return modelPackage + ".ReceivableRequest" + classNameSuffix ;
355369 }
356370
357- private Thread runVerification (Runnable verification , ClassLoader classLoader ) {
358- var verificationThread = new Thread (verification );
359- verificationThread .setName ("verify-classes-" + param .name );
360- verificationThread .setContextClassLoader (classLoader );
361- verificationThread .setUncaughtExceptionHandler (
362- (t1 , e ) -> log .error ("Uncaught exception in classes verifier: " , e ));
363- verificationThread .start ();
364- return verificationThread ;
371+ private String buildMultiLineRequestModelClassName () {
372+ var modelPackage = param .name .replace ('-' , '.' ) + ".model" ;
373+ var classNameSuffix = org .apache .commons .lang3 .StringUtils .capitalize (
374+ param .name .indexOf ('-' ) > -1
375+ ? CaseFormat .LOWER_HYPHEN .to (CaseFormat .LOWER_CAMEL , param .name )
376+ : param .name
377+ );
378+ return modelPackage + ".MultiLinePaymentRequest" + classNameSuffix ;
379+ }
380+
381+ private void runVerification (Runnable verification , ClassLoader classLoader ) throws InterruptedException {
382+ var thread = new ExceptionInterceptingThread (verification , "verify-classes-" + param .name , classLoader );
383+ thread .start ();
384+ thread .join ();
385+ assertThat (thread .getUncaughtExceptions (), Matchers .empty ());
365386 }
366387
367388 private boolean findPattern (String filePattern , String linePattern ) {
@@ -413,9 +434,9 @@ private List<File> generateFrom(String templates, String combination) {
413434 gcf .addAdditionalProperty (BoatSpringCodeGen .USE_CLASS_LEVEL_BEAN_VALIDATION , true );
414435 gcf .addAdditionalProperty (BoatSpringCodeGen .ADD_SERVLET_REQUEST , this .param .addServletRequest );
415436 gcf .addAdditionalProperty (BoatSpringCodeGen .ADD_BINDING_RESULT ,this .param .addBindingResult );
416- if (this .param .addBindingResult ){
437+ if (this .param .addBindingResult ) {
417438 gcf .addAdditionalProperty (BeanValidationFeatures .USE_BEANVALIDATION , true );
418- }else {
439+ } else {
419440 gcf .addAdditionalProperty (BeanValidationFeatures .USE_BEANVALIDATION , this .param .useBeanValidation );
420441 }
421442 gcf .addAdditionalProperty (BoatSpringCodeGen .USE_LOMBOK_ANNOTATIONS , this .param .useLombokAnnotations );
@@ -465,4 +486,18 @@ private List<File> generateFrom(String templates, String combination) {
465486
466487 return new DefaultGenerator ().opts (coi ).generate ();
467488 }
489+
490+ private class ExceptionInterceptingThread extends Thread {
491+ @ Getter
492+ private final List <Throwable > uncaughtExceptions = new ArrayList <>();
493+
494+ public ExceptionInterceptingThread (Runnable target , String name , ClassLoader classLoader ) {
495+ super (target , name );
496+ setContextClassLoader (classLoader );
497+ setUncaughtExceptionHandler ((t , e ) -> {
498+ log .warn ("Uncaught exception in classes verifier: " , e );
499+ uncaughtExceptions .add (e );
500+ });
501+ }
502+ }
468503}
0 commit comments