|
2 | 2 |
|
3 | 3 | import static java.util.Arrays.asList;
|
4 | 4 | import static java.util.Arrays.stream;
|
| 5 | +import static java.util.stream.Collectors.joining; |
| 6 | +import static java.util.stream.Collectors.toList; |
| 7 | +import static java.util.stream.Stream.concat; |
5 | 8 | import static org.hamcrest.MatcherAssert.assertThat;
|
6 | 9 | import static org.hamcrest.Matchers.equalTo;
|
7 | 10 | import static org.hamcrest.Matchers.hasSize;
|
8 | 11 | import static org.hamcrest.Matchers.is;
|
9 | 12 | import static org.hamcrest.Matchers.not;
|
10 | 13 | import static org.hamcrest.Matchers.nullValue;
|
11 |
| -import static org.junit.jupiter.api.DynamicContainer.*; |
12 |
| -import static org.junit.jupiter.api.DynamicTest.*; |
13 |
| -import static java.util.stream.Collectors.joining; |
14 |
| -import static java.util.stream.Collectors.toList; |
15 |
| -import static java.util.stream.Stream.*; |
| 14 | +import static org.junit.jupiter.api.Assertions.assertEquals; |
| 15 | +import static org.junit.jupiter.api.Assertions.assertNull; |
| 16 | +import static org.junit.jupiter.api.DynamicContainer.dynamicContainer; |
| 17 | +import static org.junit.jupiter.api.DynamicTest.dynamicTest; |
| 18 | + |
| 19 | +import com.fasterxml.jackson.databind.ObjectMapper; |
| 20 | +import com.fasterxml.jackson.databind.type.ArrayType; |
| 21 | +import com.fasterxml.jackson.databind.type.TypeBindings; |
| 22 | +import com.fasterxml.jackson.databind.type.TypeFactory; |
| 23 | +import com.google.common.base.CaseFormat; |
16 | 24 | import java.io.File;
|
17 | 25 | import java.io.IOException;
|
18 | 26 | import java.lang.annotation.ElementType;
|
19 | 27 | import java.lang.annotation.Retention;
|
20 | 28 | import java.lang.annotation.RetentionPolicy;
|
21 | 29 | import java.lang.annotation.Target;
|
| 30 | +import java.lang.reflect.Constructor; |
22 | 31 | import java.lang.reflect.Method;
|
| 32 | +import java.net.URL; |
| 33 | +import java.net.URLClassLoader; |
23 | 34 | import java.nio.file.Files;
|
24 | 35 | import java.nio.file.Paths;
|
25 | 36 | import java.util.ArrayList;
|
26 | 37 | import java.util.List;
|
| 38 | +import java.util.concurrent.atomic.AtomicReference; |
27 | 39 | import java.util.function.Predicate;
|
28 | 40 | import java.util.regex.Pattern;
|
29 | 41 | import java.util.stream.IntStream;
|
30 | 42 | import java.util.stream.Stream;
|
31 |
| - |
32 | 43 | import lombok.SneakyThrows;
|
33 | 44 | import lombok.extern.slf4j.Slf4j;
|
34 | 45 | import org.apache.commons.io.FileUtils;
|
| 46 | +import org.apache.maven.cli.MavenCli; |
| 47 | +import org.codehaus.plexus.classworlds.ClassWorld; |
35 | 48 | import org.junit.jupiter.api.BeforeAll;
|
36 | 49 | import org.junit.jupiter.api.DynamicNode;
|
37 | 50 | import org.junit.jupiter.api.DynamicTest;
|
38 | 51 | import org.junit.jupiter.api.TestFactory;
|
| 52 | +import org.junit.platform.commons.util.StringUtils; |
39 | 53 | import org.openapitools.codegen.ClientOptInput;
|
40 | 54 | import org.openapitools.codegen.CodegenConstants;
|
41 | 55 | import org.openapitools.codegen.DefaultGenerator;
|
@@ -222,6 +236,98 @@ void useWithModifiers() {
|
222 | 236 | equalTo(this.param.useWithModifiers));
|
223 | 237 | }
|
224 | 238 |
|
| 239 | + @Check |
| 240 | + void checkCompiles() throws Exception { |
| 241 | + final var projectDir = new File(TEST_OUTPUT, param.name); |
| 242 | + assertThat(projectDir + " is not a directory", projectDir.isDirectory()); |
| 243 | + compileGeneratedProject(projectDir); |
| 244 | + verifyGeneratedClasses(projectDir); |
| 245 | + } |
| 246 | + |
| 247 | + private static void compileGeneratedProject(File projectDir) { |
| 248 | + var mavenCli = new MavenCli(new ClassWorld("myRealm", BoatSpringTemplatesTests.class.getClassLoader())); |
| 249 | + final String initialDir = System.getProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY); |
| 250 | + try { |
| 251 | + System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, projectDir.getAbsolutePath()); |
| 252 | + String[] args = {"clean", "compile"}; |
| 253 | + int compileStatus = mavenCli.doMain(args, projectDir.getAbsolutePath(), System.out, System.out); |
| 254 | + assertEquals(0, compileStatus, "Could not compile generated project in dir: " + projectDir); |
| 255 | + } finally { |
| 256 | + if (StringUtils.isBlank(initialDir)) { |
| 257 | + System.clearProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY); |
| 258 | + } else { |
| 259 | + System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, initialDir); |
| 260 | + } |
| 261 | + } |
| 262 | + } |
| 263 | + |
| 264 | + private void verifyGeneratedClasses(File projectDir) throws Exception { |
| 265 | + var classesDir = new File(projectDir, "target/classes"); |
| 266 | + var classLoader = URLClassLoader.newInstance( |
| 267 | + new URL[]{classesDir.toURI().toURL()}, |
| 268 | + BoatSpringTemplatesTests.class.getClassLoader() |
| 269 | + ); |
| 270 | + String testedModelClassName = buildTestedModelClassName(); |
| 271 | + verifyModelClassSerializesAndDeserializesFromJson(classLoader, testedModelClassName); |
| 272 | + } |
| 273 | + |
| 274 | + private void verifyModelClassSerializesAndDeserializesFromJson(ClassLoader classLoader, |
| 275 | + String testedModelClassName) throws InterruptedException { |
| 276 | + var objectMapper = new ObjectMapper(); |
| 277 | + final AtomicReference<Exception> exceptionRef = new AtomicReference<>(); |
| 278 | + Runnable verification = () -> { |
| 279 | + try { |
| 280 | + Class<?> modelClass = classLoader.loadClass(testedModelClassName); |
| 281 | + Constructor<?> constructor = modelClass.getConstructor(String.class, String.class, String.class); |
| 282 | + Object modelObject1 = constructor.newInstance("OK_status", "ref123", "EUR"); |
| 283 | + Object modelObject2 = constructor.newInstance("BAD_status", "ref456", "USD"); |
| 284 | + List<?> modelObjects = List.of(modelObject1, modelObject2); |
| 285 | + |
| 286 | + String serializedObjects = objectMapper.writeValueAsString(modelObjects); |
| 287 | + Object[] deserializedModelObjects = objectMapper.readValue( |
| 288 | + serializedObjects, |
| 289 | + ArrayType.construct( |
| 290 | + TypeFactory.defaultInstance().constructFromCanonical(modelClass.getName()), |
| 291 | + TypeBindings.emptyBindings() |
| 292 | + ) |
| 293 | + ); |
| 294 | + |
| 295 | + assertEquals(modelObjects.size(), deserializedModelObjects.length); |
| 296 | + assertEquals(modelObject1.getClass(), deserializedModelObjects[0].getClass()); |
| 297 | + |
| 298 | + } catch (Exception e) { |
| 299 | + log.warn("Verification error", e); |
| 300 | + exceptionRef.set(e); |
| 301 | + } |
| 302 | + }; |
| 303 | + |
| 304 | + runVerification(verification, classLoader).join(); |
| 305 | + assertNull(exceptionRef.get(), "Classes verification failed"); |
| 306 | + } |
| 307 | + |
| 308 | + /** |
| 309 | + * Build proper class name for `ReceivableRequest`. |
| 310 | + */ |
| 311 | + private String buildTestedModelClassName() { |
| 312 | + var modelPackage = param.name.replace('-', '.') + ".model"; |
| 313 | + var classNameSuffix = org.apache.commons.lang3.StringUtils.capitalize( |
| 314 | + param.name.indexOf('-') > -1 |
| 315 | + ? CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, param.name) |
| 316 | + : param.name |
| 317 | + ); |
| 318 | + return modelPackage + ".ReceivableRequest" + classNameSuffix; |
| 319 | + } |
| 320 | + |
| 321 | + private Thread runVerification(Runnable verification, ClassLoader classLoader) { |
| 322 | + var verificationThread = new Thread(verification); |
| 323 | + verificationThread.setName("verify-classes-" + param.name); |
| 324 | + verificationThread.setContextClassLoader(classLoader); |
| 325 | + verificationThread.setUncaughtExceptionHandler( |
| 326 | + (t1, e) -> log.error("Uncaught exception in classes verifier: ", e)); |
| 327 | + verificationThread.start(); |
| 328 | + return verificationThread; |
| 329 | + } |
| 330 | + |
225 | 331 | private boolean findPattern(String filePattern, String linePattern) {
|
226 | 332 | final Predicate<String> fileMatch = Pattern.compile(filePattern).asPredicate();
|
227 | 333 | log.info("Files: {}", files);
|
|
0 commit comments