Skip to content

Commit bccbf0b

Browse files
committed
tests: implement ELN style crate writer test for ZipWriterTest
1 parent e41cfcf commit bccbf0b

7 files changed

Lines changed: 246 additions & 150 deletions

File tree

src/test/java/edu/kit/datamanager/ro_crate/HelpFunctions.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import java.io.File;
1818
import java.io.IOException;
1919
import java.io.InputStream;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
2022
import java.util.Map;
2123
import java.util.function.Function;
2224
import java.util.stream.Collectors;
@@ -152,4 +154,25 @@ public static boolean compareTwoDir(File dir1, File dir2) throws IOException {
152154
}
153155
return true;
154156
}
157+
158+
/**
159+
* Prints the file tree of the given directory for debugging and understanding
160+
* a test more quickly.
161+
*
162+
* @param directoryToPrint the directory to print
163+
* @throws IOException if an error occurs while printing the file tree
164+
*/
165+
@SuppressWarnings("resource")
166+
public static void printFileTree(Path directoryToPrint) throws IOException {
167+
// Print all files recursively in a tree structure for debugging
168+
System.out.printf("Files in %s:%n", directoryToPrint.getFileName().toString());
169+
Files.walk(directoryToPrint)
170+
.forEach(path -> {
171+
if (!path.toAbsolutePath().equals(directoryToPrint.toAbsolutePath())) {
172+
int depth = path.relativize(directoryToPrint).getNameCount();
173+
String prefix = " ".repeat(depth);
174+
System.out.printf("%s%s%s%n", prefix, "└── ", path.getFileName());
175+
}
176+
});
177+
}
155178
}

src/test/java/edu/kit/datamanager/ro_crate/writer/CrateWriterTest.java renamed to src/test/java/edu/kit/datamanager/ro_crate/writer/CommonWriterTest.java

Lines changed: 16 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,22 @@
11
package edu.kit.datamanager.ro_crate.writer;
22

3-
import edu.kit.datamanager.ro_crate.Crate;
43
import edu.kit.datamanager.ro_crate.HelpFunctions;
54
import edu.kit.datamanager.ro_crate.RoCrate;
65
import edu.kit.datamanager.ro_crate.entities.data.DataSetEntity;
7-
import edu.kit.datamanager.ro_crate.entities.data.FileEntity;
8-
import edu.kit.datamanager.ro_crate.preview.AutomaticPreview;
9-
import edu.kit.datamanager.ro_crate.preview.PreviewGenerator;
10-
import net.lingala.zip4j.ZipFile;
6+
117
import org.apache.commons.io.FileUtils;
12-
import org.junit.jupiter.api.Assertions;
138
import org.junit.jupiter.api.Test;
149
import org.junit.jupiter.api.io.TempDir;
1510

1611
import java.io.IOException;
17-
import java.io.InputStream;
1812
import java.nio.charset.Charset;
1913
import java.nio.file.Files;
2014
import java.nio.file.Path;
2115

2216
import static org.junit.jupiter.api.Assertions.assertFalse;
2317
import static org.junit.jupiter.api.Assertions.assertTrue;
2418

25-
abstract class CrateWriterTest {
26-
27-
/**
28-
* Saves the crate with the writer fitting to this test class.
29-
*
30-
* @param crate the crate to save
31-
* @param target the target path to the save location
32-
* @throws IOException if an error occurs while saving the crate
33-
*/
34-
abstract protected void saveCrate(Crate crate, Path target) throws IOException;
19+
interface CommonWriterTest extends TestableWriterStrategy {
3520

3621
/**
3722
* Test where the writer needs to rename files or folders in order to make a valid crate.
@@ -41,11 +26,11 @@ abstract class CrateWriterTest {
4126
* @throws IOException if an error occurs while writing the crate
4227
*/
4328
@Test
44-
void testFilesBeingAdjusted(@TempDir Path tempDir) throws IOException {
29+
default void testFilesBeingAdjusted(@TempDir Path tempDir) throws IOException {
4530
Path correctCrate = tempDir.resolve("compare_with_me");
4631
Path pathToFile = correctCrate.resolve("you-will-need-to-rename-this-file.ai");
4732
Path pathToDir = correctCrate.resolve("you-will-need-to-rename-this-dir");
48-
this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
33+
createManualCrateStructure(correctCrate, pathToFile, pathToDir);
4934

5035
Path writtenCrate = tempDir.resolve("written-crate");
5136
Path extractionPath = tempDir.resolve("checkMe");
@@ -60,11 +45,11 @@ void testFilesBeingAdjusted(@TempDir Path tempDir) throws IOException {
6045
)
6146
.build();
6247
this.saveCrate(builtCrate, writtenCrate);
63-
this.ensureCrateIsExtractedIn(writtenCrate, extractionPath);
48+
ensureCrateIsExtractedIn(writtenCrate, extractionPath);
6449
}
6550

66-
printFileTree(correctCrate);
67-
printFileTree(extractionPath);
51+
HelpFunctions.printFileTree(correctCrate);
52+
HelpFunctions.printFileTree(extractionPath);
6853

6954
// The actual file name should **not** appear in the crate
7055
String fileName = pathToFile.getFileName().toString();
@@ -111,15 +96,15 @@ void testFilesBeingAdjusted(@TempDir Path tempDir) throws IOException {
11196
* @throws IOException if an error occurs while writing the crate
11297
*/
11398
@Test
114-
void testWritingMakesCopy(@TempDir Path tempDir) throws IOException {
99+
default void testWritingMakesCopy(@TempDir Path tempDir) throws IOException {
115100
// We need a correct directory to compare with.
116101
// It is built manually to ensure we meet our expectations.
117102
// Reader-writer-consistency is tested at {@link CrateReaderTest}
118103
Path correctCrate = tempDir.resolve("compare_with_me");
119104
Path pathToFile = correctCrate.resolve("cp7glop.ai");
120105
Path pathToDir = correctCrate.resolve("lots_of_little_files");
121106

122-
this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
107+
createManualCrateStructure(correctCrate, pathToFile, pathToDir);
123108

124109
// Now use the builder to build the same crate independently.
125110
// The files will be reused (we need a place to take a copy from)
@@ -130,9 +115,9 @@ void testWritingMakesCopy(@TempDir Path tempDir) throws IOException {
130115

131116
// extract the zip file to a temporary directory
132117
Path extractionPath = tempDir.resolve("extracted_for_testing");
133-
this.ensureCrateIsExtractedIn(pathToZip, extractionPath);
134-
printFileTree(correctCrate);
135-
printFileTree(extractionPath);
118+
ensureCrateIsExtractedIn(pathToZip, extractionPath);
119+
HelpFunctions.printFileTree(correctCrate);
120+
HelpFunctions.printFileTree(extractionPath);
136121

137122
// compare the extracted directory with the correct one
138123
assertTrue(HelpFunctions.compareTwoDir(
@@ -151,12 +136,12 @@ void testWritingMakesCopy(@TempDir Path tempDir) throws IOException {
151136
* @throws IOException if an error occurs while writing the crate
152137
*/
153138
@Test
154-
void testWritingOnlyConsidersAddedFiles(@TempDir Path tempDir) throws IOException {
139+
default void testWritingOnlyConsidersAddedFiles(@TempDir Path tempDir) throws IOException {
155140
Path correctCrate = tempDir.resolve("compare_with_me");
156141
Path pathToFile = correctCrate.resolve("cp7glop.ai");
157142
Path pathToDir = correctCrate.resolve("lots_of_little_files");
158143

159-
this.createManualCrateStructure(correctCrate, pathToFile, pathToDir);
144+
createManualCrateStructure(correctCrate, pathToFile, pathToDir);
160145
{
161146
// This file is not part of the crate, and should therefore not be present
162147
Path falseFile = correctCrate.resolve("new");
@@ -176,8 +161,8 @@ void testWritingOnlyConsidersAddedFiles(@TempDir Path tempDir) throws IOExceptio
176161
// extract and compare
177162
Path extractionPath = tempDir.resolve("extracted_for_testing");
178163
ensureCrateIsExtractedIn(pathToZip, extractionPath);
179-
printFileTree(correctCrate);
180-
printFileTree(extractionPath);
164+
HelpFunctions.printFileTree(correctCrate);
165+
HelpFunctions.printFileTree(extractionPath);
181166

182167
assertFalse(HelpFunctions.compareTwoDir(
183168
correctCrate.toFile(),
@@ -187,116 +172,4 @@ void testWritingOnlyConsidersAddedFiles(@TempDir Path tempDir) throws IOExceptio
187172
roCrate,
188173
"/json/crate/fileAndDir.json");
189174
}
190-
191-
/**
192-
* Prints the file tree of the given directory for debugging and understanding
193-
* a test more quickly.
194-
*
195-
* @param directoryToPrint the directory to print
196-
* @throws IOException if an error occurs while printing the file tree
197-
*/
198-
@SuppressWarnings("resource")
199-
protected static void printFileTree(Path directoryToPrint) throws IOException {
200-
// Print all files recursively in a tree structure for debugging
201-
System.out.printf("Files in %s:%n", directoryToPrint.getFileName().toString());
202-
Files.walk(directoryToPrint)
203-
.forEach(path -> {
204-
if (!path.toAbsolutePath().equals(directoryToPrint.toAbsolutePath())) {
205-
int depth = path.relativize(directoryToPrint).getNameCount();
206-
String prefix = " ".repeat(depth);
207-
System.out.printf("%s%s%s%n", prefix, "└── ", path.getFileName());
208-
}
209-
});
210-
}
211-
212-
/**
213-
* Ensures the crate is in extracted form in the given path.
214-
*
215-
* @param pathToCrate the path to the crate, may not be a folder yet
216-
* @param expectedPath the path where the crate should be in extracted form
217-
* @throws IOException if an error occurs while extracting the crate
218-
*/
219-
protected void ensureCrateIsExtractedIn(Path pathToCrate, Path expectedPath) throws IOException {
220-
try (ZipFile zf = new ZipFile(pathToCrate.toFile())) {
221-
zf.extractAll(expectedPath.toFile().getAbsolutePath());
222-
}
223-
}
224-
225-
/**
226-
* Creates a crate structure manually.
227-
*
228-
* @param correctCrate the path to the crate
229-
* @param pathToFile the path to the file
230-
* @param pathToDir the path to the directory
231-
* @throws IOException if an error occurs while creating the crate structure
232-
*/
233-
protected void createManualCrateStructure(Path correctCrate, Path pathToFile, Path pathToDir) throws IOException {
234-
FileUtils.forceMkdir(correctCrate.toFile());
235-
InputStream fileJson = ZipStreamStrategyTest.class
236-
.getResourceAsStream("/json/crate/fileAndDir.json");
237-
Assertions.assertNotNull(fileJson);
238-
// fill the directory with expected files and dirs
239-
// starting with the .json of our crate
240-
Path json = correctCrate.resolve("ro-crate-metadata.json");
241-
FileUtils.copyInputStreamToFile(fileJson, json.toFile());
242-
// create preview
243-
PreviewGenerator.generatePreview(correctCrate.toFile().getAbsolutePath());
244-
// create the files and directories
245-
FileUtils.writeStringToFile(pathToFile.toFile(), "content of Local File", Charset.defaultCharset());
246-
// creates the directory and a subdirectory
247-
Path subdir = pathToDir.resolve("subdir");
248-
FileUtils.forceMkdir(subdir.toFile());
249-
FileUtils.writeStringToFile(
250-
subdir.resolve("subsubfirst.txt").toFile(),
251-
"content of subsub file in subsubdir",
252-
Charset.defaultCharset());
253-
FileUtils.writeStringToFile(
254-
pathToDir.resolve("first.txt").toFile(),
255-
"content of first file in dir",
256-
Charset.defaultCharset());
257-
FileUtils.writeStringToFile(
258-
pathToDir.resolve("second.txt").toFile(),
259-
"content of second file in dir",
260-
Charset.defaultCharset());
261-
FileUtils.writeStringToFile(
262-
pathToDir.resolve("third.txt").toFile(),
263-
"content of third file in dir",
264-
Charset.defaultCharset());
265-
}
266-
267-
/**
268-
* Creates a crate resembling the one we manually create in these tests.
269-
*
270-
* @param pathToFile the file to add
271-
* @param pathToSubdir the directory to add
272-
* @return the crate builder
273-
*/
274-
protected RoCrate.RoCrateBuilder getCrateWithFileAndDir(Path pathToFile, Path pathToSubdir) {
275-
return new RoCrate.RoCrateBuilder(
276-
"Example RO-Crate",
277-
"The RO-Crate Root Data Entity",
278-
"2024",
279-
"https://creativecommons.org/licenses/by-nc-sa/3.0/au/"
280-
)
281-
.addDataEntity(
282-
new FileEntity.FileEntityBuilder()
283-
.addProperty("name", "Diagram showing trend to increase")
284-
.addProperty("contentSize", "383766")
285-
.addProperty("description", "Illustrator file for Glop Pot")
286-
.setEncodingFormat("application/pdf")
287-
.setLocationWithExceptions(pathToFile)
288-
.setId("cp7glop.ai")
289-
.build()
290-
)
291-
.addDataEntity(
292-
new DataSetEntity.DataSetBuilder()
293-
.addProperty("name", "Too many files")
294-
.addProperty("description",
295-
"This directory contains many small files, that we're not going to describe in detail.")
296-
.setLocationWithExceptions(pathToSubdir)
297-
.setId("lots_of_little_files/")
298-
.build()
299-
)
300-
.setPreview(new AutomaticPreview());
301-
}
302175
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package edu.kit.datamanager.ro_crate.writer;
2+
3+
import edu.kit.datamanager.ro_crate.Crate;
4+
import edu.kit.datamanager.ro_crate.HelpFunctions;
5+
import edu.kit.datamanager.ro_crate.RoCrate;
6+
7+
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.api.io.TempDir;
9+
10+
import java.io.IOException;
11+
import java.nio.file.Path;
12+
13+
import static org.junit.jupiter.api.Assertions.*;
14+
15+
public interface ElnFileFormatTest extends TestableWriterStrategy {
16+
17+
/**
18+
* Write in ELN format style, meaning with a subfolder in the zip file.
19+
*
20+
* @param crate the crate to write
21+
* @param target the target path to the save location
22+
* @throws IOException if an error occurs
23+
*/
24+
void saveCrateElnStyle(Crate crate, Path target) throws IOException;
25+
26+
@Test
27+
default void testMakesElnStyleCrate(@TempDir Path tempDir) throws IOException {
28+
// We need a correct directory to compare with.
29+
// It is built manually to ensure we meet our expectations.
30+
// Reader-writer-consistency is tested at {@link CrateReaderTest}
31+
32+
// We compare the ELN style like this:
33+
// tempDir
34+
// └── compare_with_me
35+
// └── crate-subfolder
36+
// ├── ...
37+
// └── extracted_for_testing
38+
// └── crate-subfolder
39+
// ├── ...
40+
String crateName = "crate-subfolder";
41+
Path correctCrate = tempDir
42+
.resolve("compare_with_me")
43+
.resolve(crateName);
44+
Path pathToFile = correctCrate.resolve("cp7glop.ai");
45+
Path pathToDir = correctCrate.resolve("lots_of_little_files");
46+
47+
createManualCrateStructure(correctCrate, pathToFile, pathToDir);
48+
49+
// Now use the builder to build the same crate independently.
50+
// The files will be reused (we need a place to take a copy from)
51+
RoCrate builtCrate = getCrateWithFileAndDir(pathToFile, pathToDir).build();
52+
53+
Path pathToZip = tempDir.resolve("%s.eln".formatted(crateName));
54+
this.saveCrateElnStyle(builtCrate, pathToZip);
55+
56+
// extract the zip file to a temporary directory
57+
Path extractionPath = tempDir.resolve("extracted_for_testing");
58+
ensureCrateIsExtractedIn(pathToZip, extractionPath);
59+
HelpFunctions.printFileTree(correctCrate);
60+
HelpFunctions.printFileTree(extractionPath);
61+
62+
// compare the extracted directory with the correct one
63+
assertTrue(HelpFunctions.compareTwoDir(
64+
correctCrate.toFile(),
65+
extractionPath.toFile()));
66+
HelpFunctions.compareCrateJsonToFileInResources(
67+
builtCrate,
68+
"/json/crate/fileAndDir.json");
69+
}
70+
}

src/test/java/edu/kit/datamanager/ro_crate/writer/FolderWriterTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
* @author Nikola Tzotchev on 9.2.2022 г.
1212
* @version 1
1313
*/
14-
class FolderWriterTest extends CrateWriterTest {
14+
class FolderWriterTest implements CommonWriterTest {
1515

1616
@Override
17-
protected void saveCrate(Crate crate, Path target) throws IOException {
17+
public void saveCrate(Crate crate, Path target) throws IOException {
1818
Writers.newFolderWriter()
1919
.save(crate, target.toAbsolutePath().toString());
2020
}
2121

2222
@Override
23-
protected void ensureCrateIsExtractedIn(Path pathToCrate, Path expectedPath) throws IOException {
23+
public void ensureCrateIsExtractedIn(Path pathToCrate, Path expectedPath) throws IOException {
2424
FileUtils.copyDirectory(pathToCrate.toFile(), expectedPath.toFile());
2525
}
2626
}

0 commit comments

Comments
 (0)