1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.cloud.contract.maven.verifier;
18
19 import java.io.File;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.maven.execution.MavenSession;
25 import org.apache.maven.model.Dependency;
26 import org.apache.maven.model.Resource;
27 import org.apache.maven.plugin.AbstractMojo;
28 import org.apache.maven.plugin.MojoExecution;
29 import org.apache.maven.plugin.MojoExecutionException;
30 import org.apache.maven.plugin.MojoFailureException;
31 import org.apache.maven.plugins.annotations.LifecyclePhase;
32 import org.apache.maven.plugins.annotations.Mojo;
33 import org.apache.maven.plugins.annotations.Parameter;
34 import org.apache.maven.plugins.annotations.ResolutionScope;
35 import org.apache.maven.project.MavenProject;
36 import org.eclipse.aether.RepositorySystemSession;
37
38 import org.springframework.cloud.contract.spec.ContractVerifierException;
39 import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
40 import org.springframework.cloud.contract.verifier.TestGenerator;
41 import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
42 import org.springframework.cloud.contract.verifier.config.TestFramework;
43 import org.springframework.cloud.contract.verifier.config.TestMode;
44
45
46
47
48
49
50
51 @Mojo(name = "generateTests", defaultPhase = LifecyclePhase.GENERATE_TEST_SOURCES,
52 requiresDependencyResolution = ResolutionScope.TEST)
53 public class GenerateTestsMojo extends AbstractMojo {
54
55 @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
56 private RepositorySystemSession repoSession;
57
58 @Parameter(property = "spring.cloud.contract.verifier.contractsDirectory",
59 defaultValue = "${project.basedir}/src/test/resources/contracts")
60 private File contractsDirectory;
61
62 @Parameter(defaultValue = "${project.build.directory}/generated-test-sources/contracts")
63 private File generatedTestSourcesDir;
64
65 @Parameter(defaultValue = "${project.build.directory}/generated-test-resources/contracts")
66 private File generatedTestResourcesDir;
67
68 @Parameter
69 private String basePackageForTests;
70
71 @Parameter
72 private String baseClassForTests;
73
74 @Parameter(defaultValue = "MOCKMVC")
75 private TestMode testMode;
76
77 @Parameter(defaultValue = "JUNIT5")
78 private TestFramework testFramework;
79
80 @Parameter
81 private String ruleClassForTests;
82
83 @Parameter
84 private String nameSuffixForTests;
85
86
87
88
89 @Parameter
90 private String[] imports;
91
92
93
94
95 @Parameter
96 private String[] staticImports;
97
98
99
100
101 @Parameter
102 private List<String> excludedFiles;
103
104
105
106
107 @Parameter(property = "includedFiles")
108 private List<String> includedFiles;
109
110
111
112
113
114 @Parameter(property = "spring.cloud.contract.verifier.assert.size", defaultValue = "false")
115 private boolean assertJsonSize;
116
117
118
119
120 @Parameter
121 private List<String> ignoredFiles;
122
123 @Parameter(defaultValue = "${project}", readonly = true)
124 private MavenProject project;
125
126 @Parameter(property = "spring.cloud.contract.verifier.skip", defaultValue = "false")
127 private boolean skip;
128
129 @Parameter(property = "maven.test.skip", defaultValue = "false")
130 private boolean mavenTestSkip;
131
132 @Parameter(property = "skipTests", defaultValue = "false")
133 private boolean skipTests;
134
135
136
137
138
139
140 @Parameter(property = "contractsRepositoryUrl")
141 private String contractsRepositoryUrl;
142
143 @Parameter(property = "contractDependency")
144 private Dependency contractDependency;
145
146
147
148
149
150
151
152 @Parameter(property = "contractsPath")
153 private String contractsPath;
154
155
156
157
158 @Parameter(property = "contractsMode", defaultValue = "CLASSPATH")
159 private StubRunnerProperties.StubsMode contractsMode;
160
161
162
163
164
165
166
167
168
169
170 @Parameter(property = "packageWithBaseClasses")
171 private String packageWithBaseClasses;
172
173
174
175
176
177
178
179
180
181 @Parameter(property = "baseClassMappings")
182 private List<BaseClassMapping> baseClassMappings;
183
184
185
186
187 @Parameter(property = "contractsRepositoryUsername")
188 private String contractsRepositoryUsername;
189
190
191
192
193 @Parameter(property = "contractsRepositoryPassword")
194 private String contractsRepositoryPassword;
195
196
197
198
199 @Parameter(property = "contractsRepositoryProxyHost")
200 private String contractsRepositoryProxyHost;
201
202
203
204
205 @Parameter(property = "contractsRepositoryProxyPort")
206 private Integer contractsRepositoryProxyPort;
207
208
209
210
211
212
213 @Parameter(property = "contractsSnapshotCheckSkip", defaultValue = "false")
214 @Deprecated
215 private boolean contractsSnapshotCheckSkip;
216
217
218
219
220
221 @Parameter(property = "deleteStubsAfterTest", defaultValue = "true")
222 private boolean deleteStubsAfterTest;
223
224
225
226
227
228 @Parameter(property = "contractsProperties")
229 private Map<String, String> contractsProperties = new HashMap<>();
230
231
232
233
234
235 @Parameter(property = "failOnNoContracts", defaultValue = "true")
236 private boolean failOnNoContracts;
237
238
239
240
241
242
243
244 @Parameter(property = "failOnInProgress", defaultValue = "true")
245 private boolean failOnInProgress = true;
246
247
248
249
250
251 @Parameter(property = "incrementalContractTests", defaultValue = "true")
252 private boolean incrementalContractTests = true;
253
254 @Parameter(defaultValue = "${mojoExecution}", readonly = true, required = true)
255 private MojoExecution mojoExecution;
256
257 @Parameter(defaultValue = "${session}", readonly = true, required = true)
258 private MavenSession session;
259
260 @Override
261 public void execute() throws MojoExecutionException, MojoFailureException {
262 if (this.skip || this.mavenTestSkip || this.skipTests) {
263 if (this.skip) {
264 getLog().info("Skipping Spring Cloud Contract Verifier execution: spring.cloud.contract.verifier.skip="
265 + this.skip);
266 }
267 if (this.mavenTestSkip) {
268 getLog().info(
269 "Skipping Spring Cloud Contract Verifier execution: maven.test.skip=" + this.mavenTestSkip);
270 }
271 if (this.skipTests) {
272 getLog().info("Skipping Spring Cloud Contract Verifier execution: skipTests" + this.skipTests);
273 }
274 return;
275 }
276 getLog().info("Generating server tests source code for Spring Cloud Contract Verifier contract verification");
277 final ContractVerifierConfigProperties config = new ContractVerifierConfigProperties();
278 config.setFailOnInProgress(this.failOnInProgress);
279
280 File contractsDirectory = new MavenContractsDownloader(this.project, this.contractDependency,
281 this.contractsPath, this.contractsRepositoryUrl, this.contractsMode, getLog(),
282 this.contractsRepositoryUsername, this.contractsRepositoryPassword, this.contractsRepositoryProxyHost,
283 this.contractsRepositoryProxyPort, this.deleteStubsAfterTest, this.contractsProperties,
284 this.failOnNoContracts).downloadAndUnpackContractsIfRequired(config, this.contractsDirectory);
285 getLog().info("Directory with contract is present at [" + contractsDirectory + "]");
286
287 if (this.incrementalContractTests
288 && !ChangeDetector.inputFilesChangeDetected(contractsDirectory, mojoExecution, session)) {
289 getLog().info("Nothing to generate - all classes are up to date");
290 return;
291 }
292
293 setupConfig(config, contractsDirectory);
294 this.project.addTestCompileSourceRoot(this.generatedTestSourcesDir.getAbsolutePath());
295 Resource resource = new Resource();
296 resource.setDirectory(this.generatedTestResourcesDir.getAbsolutePath());
297 this.project.addTestResource(resource);
298 if (getLog().isInfoEnabled()) {
299 getLog().info("Test Source directory: " + this.generatedTestSourcesDir.getAbsolutePath() + " added.");
300 getLog().info("Using [" + config.getBaseClassForTests() + "] as base class for test classes, ["
301 + config.getBasePackageForTests() + "] as base " + "package for tests, ["
302 + config.getPackageWithBaseClasses() + "] as package with " + "base classes, base class mappings "
303 + this.baseClassMappings);
304 }
305 try {
306 LeftOverPrevention leftOverPrevention = new LeftOverPrevention(this.generatedTestSourcesDir, mojoExecution,
307 session);
308 TestGenerator generator = new TestGenerator(config);
309 int generatedClasses = generator.generate();
310 getLog().info("Generated " + generatedClasses + " test classes.");
311 leftOverPrevention.deleteLeftOvers();
312 }
313 catch (ContractVerifierException e) {
314 throw new MojoExecutionException(
315 String.format("Spring Cloud Contract Verifier Plugin exception: %s", e.getMessage()), e);
316 }
317 }
318
319 private void setupConfig(ContractVerifierConfigProperties config, File contractsDirectory) {
320 config.setContractsDslDir(contractsDirectory);
321 config.setGeneratedTestSourcesDir(this.generatedTestSourcesDir);
322 config.setGeneratedTestResourcesDir(this.generatedTestResourcesDir);
323 config.setTestFramework(this.testFramework);
324 config.setTestMode(this.testMode);
325 config.setBasePackageForTests(this.basePackageForTests);
326 config.setBaseClassForTests(this.baseClassForTests);
327 config.setRuleClassForTests(this.ruleClassForTests);
328 config.setNameSuffixForTests(this.nameSuffixForTests);
329 config.setImports(this.imports);
330 config.setStaticImports(this.staticImports);
331 config.setIgnoredFiles(this.ignoredFiles);
332 config.setExcludedFiles(this.excludedFiles);
333 config.setIncludedFiles(this.includedFiles);
334 config.setAssertJsonSize(this.assertJsonSize);
335 config.setPackageWithBaseClasses(this.packageWithBaseClasses);
336 if (this.baseClassMappings != null) {
337 config.setBaseClassMappings(mappingsToMap());
338 }
339 }
340
341 public Map<String, String> mappingsToMap() {
342 Map<String, String> map = new HashMap<>();
343 if (this.baseClassMappings == null) {
344 return map;
345 }
346 for (BaseClassMapping mapping : this.baseClassMappings) {
347 map.put(mapping.getContractPackageRegex(), mapping.getBaseClassFQN());
348 }
349 return map;
350 }
351
352 public List<String> getExcludedFiles() {
353 return this.excludedFiles;
354 }
355
356 public void setExcludedFiles(List<String> excludedFiles) {
357 this.excludedFiles = excludedFiles;
358 }
359
360 public List<String> getIgnoredFiles() {
361 return this.ignoredFiles;
362 }
363
364 public void setIgnoredFiles(List<String> ignoredFiles) {
365 this.ignoredFiles = ignoredFiles;
366 }
367
368 public boolean isAssertJsonSize() {
369 return this.assertJsonSize;
370 }
371
372 public void setAssertJsonSize(boolean assertJsonSize) {
373 this.assertJsonSize = assertJsonSize;
374 }
375
376 }