Skip to content

Commit 64895d6

Browse files
authored
fix attachments when results dir isn't normalized (fixes #3278, via #3280)
1 parent db98dac commit 64895d6

File tree

8 files changed

+139
-14
lines changed

8 files changed

+139
-14
lines changed

allure-generator/src/main/java/io/qameta/allure/allure1/Allure1Plugin.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,10 @@ private Attachment convert(final Path source,
346346
.setSize(0L);
347347
}
348348

349-
final Path attachmentFile = source.resolve(attachmentSource).normalize();
349+
final Path normalizedSource = source.normalize();
350+
final Path attachmentFile = normalizedSource.resolve(attachmentSource).normalize();
350351

351-
if (attachmentFile.startsWith(source)
352+
if (attachmentFile.startsWith(normalizedSource)
352353
&& Files.isRegularFile(attachmentFile, LinkOption.NOFOLLOW_LINKS)) {
353354
final Attachment found = visitor.visitAttachmentFile(attachmentFile);
354355
if (Objects.nonNull(attachment.getType())) {
@@ -363,7 +364,7 @@ private Attachment convert(final Path source,
363364
}
364365
return found;
365366
} else {
366-
visitor.error("Could not find attachment " + attachmentSource + " in directory " + source);
367+
visitor.error("Could not find attachment " + attachmentSource + " in directory " + normalizedSource);
367368
return new Attachment()
368369
.setType(attachment.getType())
369370
.setName(attachment.getTitle())
@@ -599,7 +600,7 @@ private Map<String, String> processEnvironmentXml(final Path directory) {
599600
final Path envXmlFile = directory.resolve("environment.xml");
600601
final Map<String, String> items = new LinkedHashMap<>();
601602
if (Files.exists(envXmlFile)) {
602-
try (InputStream envXmlInputStream =
603+
try (InputStream envXmlInputStream =
603604
Files.newInputStream(envXmlFile)) {
604605
xmlMapper
605606
.readValue(envXmlInputStream, ru.yandex.qatools.commons.model.Environment.class)

allure-generator/src/main/java/io/qameta/allure/allure2/Allure2Plugin.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ private Attachment convert(final Path source,
276276
.setName(attachment.getName())
277277
.setSize(0L);
278278
}
279+
final Path normalizedSource = source.normalize();
280+
final Path attachmentFile = normalizedSource.resolve(attachmentSource).normalize();
279281

280-
final Path attachmentFile = source.resolve(attachmentSource).normalize();
281-
282-
if (attachmentFile.startsWith(source)
282+
if (attachmentFile.startsWith(normalizedSource)
283283
&& Files.isRegularFile(attachmentFile, LinkOption.NOFOLLOW_LINKS)) {
284284
final Attachment found = visitor.visitAttachmentFile(attachmentFile);
285285
if (nonNull(attachment.getType())) {
@@ -294,7 +294,7 @@ private Attachment convert(final Path source,
294294
}
295295
return found;
296296
} else {
297-
visitor.error("Could not find attachment " + attachmentSource + " in directory " + source);
297+
visitor.error("Could not find attachment " + attachmentSource + " in directory " + normalizedSource);
298298
return new Attachment()
299299
.setType(attachment.getType())
300300
.setName(attachment.getName())

allure-generator/src/test/java/io/qameta/allure/allure1/Allure1PluginTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,35 @@ void shouldPreserveContentTypeFromAttachment() throws IOException {
358358
assertThat(attachments.get(0).getSource()).endsWith(".txt");
359359
}
360360

361+
@Test
362+
void shouldResolveAttachmentsWithRelativeResultsPath() throws IOException {
363+
final Path allureResults = directory.resolve("allure-results");
364+
Files.createDirectories(allureResults);
365+
366+
copyFile(allureResults, "allure1/text-attachment-link.xml", generateTestSuiteXmlName());
367+
copyFile(allureResults, "allure1/sample-attachment.txt", "link.txt");
368+
final Allure1Plugin reader = new Allure1Plugin();
369+
final Configuration configuration = ConfigurationBuilder.bundled().build();
370+
final DefaultResultsVisitor resultsVisitor = new DefaultResultsVisitor(configuration);
371+
final Path relative = allureResults.resolve("..").resolve("allure-results");
372+
reader.readResults(configuration, resultsVisitor, relative);
373+
final LaunchResults results = resultsVisitor.getLaunchResults();
374+
375+
assertThat(results.getResults())
376+
.hasSize(1);
377+
378+
final TestResult tr = results.getResults().iterator().next();
379+
final List<Attachment> attachments = tr.getTestStage().getAttachments();
380+
assertThat(attachments)
381+
.extracting(Attachment::getName, Attachment::getType, Attachment::getSize)
382+
.containsExactlyInAnyOrder(
383+
tuple("String attachment in test", "text/plain", 25L)
384+
);
385+
386+
assertThat(attachments.get(0).getSource()).endsWith(".txt");
387+
}
388+
389+
361390
@SuppressWarnings("unchecked")
362391
@Test
363392
void shouldReadEnvironmentPropertiesUtf8() throws Exception {

allure-generator/src/test/java/io/qameta/allure/allure2/Allure2PluginTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,34 @@ void shouldNotAllowAttachmentSourceSymbolicLink() throws IOException {
395395

396396
}
397397

398+
@Test
399+
void shouldResolveAttachmentsWithRelativeResultsPath() throws IOException {
400+
final Path allureResults = directory.resolve("allure-results");
401+
Files.createDirectories(allureResults);
402+
copyFile(allureResults, "allure2/text-attachment-link.json", generateTestResultName());
403+
copyFile(allureResults, "allure2/test-sample-attachment.txt", "link.txt");
404+
405+
final Allure2Plugin reader = new Allure2Plugin();
406+
final Configuration configuration = ConfigurationBuilder.bundled().build();
407+
final DefaultResultsVisitor resultsVisitor = new DefaultResultsVisitor(configuration);
408+
final Path relative = allureResults.resolve("..").resolve("allure-results");
409+
reader.readResults(configuration, resultsVisitor, relative);
410+
final LaunchResults results = resultsVisitor.getLaunchResults();
411+
412+
assertThat(results.getResults())
413+
.hasSize(1);
414+
415+
final TestResult tr = results.getResults().iterator().next();
416+
final List<Attachment> attachments = tr.getTestStage().getAttachments();
417+
assertThat(attachments)
418+
.extracting(Attachment::getName, Attachment::getType, Attachment::getSize)
419+
.containsExactlyInAnyOrder(
420+
tuple("String attachment in test", "text/plain", 24L)
421+
);
422+
423+
assertThat(attachments.get(0).getSource()).endsWith(".txt");
424+
}
425+
398426
private LaunchResults process(String... strings) throws IOException {
399427
Iterator<String> iterator = Arrays.asList(strings).iterator();
400428
while (iterator.hasNext()) {

plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,12 @@ private Optional<Path> getLogFile(final Path resultsDirectory, final String clas
235235
}
236236

237237
try {
238-
final Path normalized = resultsDirectory.resolve(possibleLogFileName).normalize();
239-
if (normalized.startsWith(resultsDirectory)
240-
&& Files.isRegularFile(normalized, LinkOption.NOFOLLOW_LINKS)) {
241-
return Optional.of(normalized);
238+
final Path normalizedResultsDir = resultsDirectory.normalize();
239+
final Path normalizedSource = normalizedResultsDir
240+
.resolve(possibleLogFileName).normalize();
241+
if (normalizedSource.startsWith(normalizedResultsDir)
242+
&& Files.isRegularFile(normalizedSource, LinkOption.NOFOLLOW_LINKS)) {
243+
return Optional.of(normalizedSource);
242244
}
243245
} catch (InvalidPathException e) {
244246
LOGGER.debug("Can not find log file: invalid className {}", className, e);

plugins/junit-xml-plugin/src/test/java/io/qameta/allure/junitxml/JunitXmlPluginTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,28 @@ void shouldAddLogAsAttachment() throws Exception {
133133
.containsExactly(Tuple.tuple("System out", "some-uid"));
134134
}
135135

136+
@Test
137+
void shouldResolveAttachmentsWithRelativeResultsPath() throws Exception {
138+
final Attachment hey = new Attachment().setUid("some-uid");
139+
when(visitor.visitAttachmentFile(any())).thenReturn(hey);
140+
final Path junitResults = resultsDirectory.resolve("junit-results");
141+
Files.createDirectories(junitResults);
142+
143+
copyFile(junitResults, "junitdata/TEST-test.SampleTest.xml", "TEST-test.SampleTest.xml");
144+
copyFile(junitResults, "junitdata/test.SampleTest.txt", "test.SampleTest.txt");
145+
JunitXmlPlugin reader = new JunitXmlPlugin(ZoneOffset.UTC);
146+
final Path relative = junitResults.resolve("..").resolve("junit-results");
147+
reader.readResults(configuration, visitor, relative);
148+
149+
final ArgumentCaptor<Path> attachmentCaptor = ArgumentCaptor.captor();
150+
verify(visitor, times(1)).visitAttachmentFile(attachmentCaptor.capture());
151+
152+
assertThat(attachmentCaptor.getValue())
153+
.isRegularFile()
154+
.hasContent("some-test-log");
155+
156+
}
157+
136158
@Test
137159
void shouldNotAllowPathTraversal() throws Exception {
138160
final Attachment hey = new Attachment().setUid("some-uid");

plugins/xctest-plugin/src/main/java/io/qameta/allure/xctest/XcTestPlugin.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ private void addScreenshots(final Path directory,
174174
return;
175175
}
176176

177-
final Path attachments = directory.resolve(ATTACHMENTS);
177+
final Path attachments = directory.resolve(ATTACHMENTS).normalize();
178178
for (String ext : ALLOWED_SCREENSHOT_EXT) {
179179
final Path resolved = attachments
180180
.resolve(String.format("Screenshot_%s.%s", uuid, ext))
@@ -192,7 +192,7 @@ private void addAttachments(final Path directory,
192192
final ResultsVisitor visitor,
193193
final Map<String, Object> props,
194194
final Step step) {
195-
final Path attachments = directory.resolve(ATTACHMENTS);
195+
final Path attachments = directory.resolve(ATTACHMENTS).normalize();
196196
for (Object o : asList(props.get(ATTACHMENTS))) {
197197
final Map<String, Object> p = asMap(o);
198198
final String fileName = p.get(ATTACHMENT_FILENAME).toString();

plugins/xctest-plugin/src/test/java/io/qameta/allure/xctest/XcTestPluginTest.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,28 @@ public void shouldParseHasScreenShotData() throws Exception {
118118
.visitAttachmentFile(screenshot);
119119
}
120120

121+
@Test
122+
public void shouldAddScreenshotsWhenRelativeResultsDir() throws Exception {
123+
final Path xctestResults = resultsDirectory.resolve("xctest-results");
124+
Files.createDirectories(xctestResults);
125+
try (InputStream is = getClass().getClassLoader().getResourceAsStream("has-screenshot-data.plist")) {
126+
Files.copy(Objects.requireNonNull(is), xctestResults.resolve("sample.plist"));
127+
}
128+
final Path attachments = xctestResults.resolve("Attachments");
129+
Files.createDirectories(attachments);
130+
131+
final Path screenshot = attachments.resolve("Screenshot_92D015E5-965D-4171-849C-35CC0945FEA2.png");
132+
try (InputStream is = getClass().getClassLoader().getResourceAsStream("screenshot.png")) {
133+
Files.copy(Objects.requireNonNull(is), screenshot);
134+
}
135+
136+
final Path relative = xctestResults.resolve("..").resolve("xctest-results");
137+
new XcTestPlugin().readResults(configuration, visitor, relative);
138+
139+
verify(visitor, times(1))
140+
.visitAttachmentFile(screenshot);
141+
}
142+
121143
@Test
122144
public void shouldNotAllowPathTraversalForScreenshots() throws Exception {
123145
try (InputStream is = getClass().getClassLoader().getResourceAsStream("has-screenshot-data-path-traversal.plist")) {
@@ -176,4 +198,25 @@ public void shouldParseAttachmentsData() throws Exception {
176198
verify(visitor, times(1))
177199
.visitAttachmentFile(screenshot);
178200
}
201+
202+
@Test
203+
public void shouldAllureAttachmentsDataWithRelativeResultsDir() throws Exception {
204+
final Path xctestResults = resultsDirectory.resolve("xctest-results");
205+
Files.createDirectories(xctestResults);
206+
try (InputStream is = getClass().getClassLoader().getResourceAsStream("attachments-data.plist")) {
207+
Files.copy(Objects.requireNonNull(is), xctestResults.resolve("sample.plist"));
208+
}
209+
final Path attachments = xctestResults.resolve("Attachments");
210+
Files.createDirectories(attachments);
211+
212+
final Path screenshot = attachments.resolve("Screenshot_1_1FBB627A-3D11-41E3-B4E6-5C717C75F175.jpeg");
213+
try (InputStream is = getClass().getClassLoader().getResourceAsStream("screenshot.png")) {
214+
Files.copy(Objects.requireNonNull(is), screenshot);
215+
}
216+
final Path relative = xctestResults.resolve("..").resolve("xctest-results");
217+
new XcTestPlugin().readResults(configuration, visitor, relative);
218+
219+
verify(visitor, times(1))
220+
.visitAttachmentFile(screenshot);
221+
}
179222
}

0 commit comments

Comments
 (0)