Skip to content

Commit

Permalink
DD-1605: unit test (#5)
Browse files Browse the repository at this point in the history
* added unit tests
* added annotations to BatchProcessor because it did not fail fast on a missing action
* more informative (error)message
* new method batchProcessor in AbstractSubcommandContainer can replace builder methods for all commands but one
  • Loading branch information
jo-pol authored Sep 2, 2024
1 parent 6fcbed2 commit be134dd
Show file tree
Hide file tree
Showing 10 changed files with 961 additions and 10 deletions.
16 changes: 15 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,26 @@
<dependency>
<groupId>nl.knaw.dans</groupId>
<artifactId>dans-dataverse-client-lib</artifactId>

</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/nl/knaw/dans/dvcli/action/BatchProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package nl.knaw.dans.dvcli.action;

import lombok.Builder;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
Expand All @@ -34,17 +35,20 @@ public class BatchProcessor<I, R> {
/**
* The labeled items to process.
*/
@NonNull
private final List<Pair<String, I>> labeledItems;

/**
* The action to apply to each item.
*/
@NonNull
private final ThrowingFunction<I, R, Exception> action;

/**
* The report to which the results of the actions are reported.
*/
private final Report<I, R> report;
@Builder.Default
private final Report<I, R> report = new ConsoleReport<>();

/**
* The delay in milliseconds between processing items. A delay of 0 or less means no delay.
Expand All @@ -60,7 +64,7 @@ public void process() {
log.info("Processing item {} of {}", ++i, labeledItems.size());
callAction(labeledItem.getFirst(), labeledItem.getSecond());
}
log.info("Finished batch processing");
log.info("Finished batch processing of {} items", labeledItems.size());
}

private void callAction(String label, I item) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Stream<String> getPids() throws IOException {
return Stream.of(defaultId);
}

Stream<String> lines = null;
Stream<String> lines;

if ("-".equals(singleIdOrIdFile)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Expand All @@ -47,6 +47,9 @@ public Stream<String> getPids() throws IOException {
else {
var pidFile = Paths.get(singleIdOrIdFile);
if (Files.exists(pidFile)) {
if (!Files.isRegularFile(pidFile)) {
throw new IOException(singleIdOrIdFile + " is not a regular file");
}
lines = Files.lines(pidFile)
.flatMap(line -> Arrays.stream(line.trim().split("\\s+")));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import nl.knaw.dans.dvcli.action.BatchProcessor;
import nl.knaw.dans.dvcli.action.Pair;
import nl.knaw.dans.dvcli.action.SingleIdOrIdsFile;
import nl.knaw.dans.dvcli.action.ThrowingFunction;
import nl.knaw.dans.lib.dataverse.DataverseClient;
import nl.knaw.dans.lib.dataverse.DataverseException;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;

Expand All @@ -28,7 +30,7 @@

public abstract class AbstractSubcommandContainer<T> extends AbstractCmd {
private static final long DEFAULT_DELAY = 1000;

protected DataverseClient dataverseClient;

public AbstractSubcommandContainer(@NonNull DataverseClient dataverseClient) {
Expand All @@ -37,7 +39,7 @@ public AbstractSubcommandContainer(@NonNull DataverseClient dataverseClient) {

@Parameters(index = "0", description = "The target(s) of the operation; this is either an ID a file with a with a list of IDs, or - if the subcommand supports it - a parameters file.",
paramLabel = "targets", defaultValue = SingleIdOrIdsFile.DEFAULT_TARGET_PLACEHOLDER)

protected String targets;

@Option(names = { "-d", "--delay" }, description = "Delay in milliseconds between requests to the server (default: ${DEFAULT-VALUE}).", defaultValue = "" + DEFAULT_DELAY)
Expand All @@ -48,15 +50,23 @@ protected BatchProcessor.BatchProcessorBuilder<T, String> batchProcessorBuilder(
.labeledItems(getItems())
.delay(delay);
}
protected <P> BatchProcessor.BatchProcessorBuilder<P, String> paramsBatchProcessorBuilder() throws IOException {

protected <P> BatchProcessor.BatchProcessorBuilder<P, String> paramsBatchProcessorBuilder() {
return BatchProcessor.<P, String> builder()
.delay(delay);
}

protected abstract List<Pair<String, T>> getItems() throws IOException;

@Override
public void doCall() {
public void doCall() throws IOException, DataverseException {
}

public BatchProcessor<T, String> batchProcessor(ThrowingFunction<T, String, Exception> action) throws IOException {
return BatchProcessor.<T, String> builder()
.labeledItems(getItems())
.delay(delay)
.action(action)
.build();
}
}
71 changes: 71 additions & 0 deletions src/test/java/nl/knaw/dans/dvcli/AbstractCapturingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2024 DANS - Data Archiving and Networked Services ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nl.knaw.dans.dvcli;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;

public abstract class AbstractCapturingTest {
private final PrintStream originalStdout = System.out;
private final PrintStream originalStderr = System.err;
protected OutputStream stdout;
protected OutputStream stderr;
protected ListAppender<ILoggingEvent> logged;

@AfterEach
public void tearDown() {

System.setOut(originalStdout);
System.setErr(originalStderr);
}

@BeforeEach
public void setUp() {
stdout = captureStdout();
stderr = captureStderr();
logged = captureLog(Level.DEBUG, "nl.knaw.dans");
}

public static ListAppender<ILoggingEvent> captureLog(Level error, String loggerName) {
var logger = (Logger) LoggerFactory.getLogger(loggerName);
ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
listAppender.start();
logger.setLevel(error);
logger.addAppender(listAppender);
return listAppender;
}

public static ByteArrayOutputStream captureStdout() {
var outContent = new ByteArrayOutputStream();
System.setOut(new PrintStream(outContent));
return outContent;
}

public static ByteArrayOutputStream captureStderr() {
var outContent = new ByteArrayOutputStream();
System.setErr(new PrintStream(outContent));
return outContent;
}
}
36 changes: 36 additions & 0 deletions src/test/java/nl/knaw/dans/dvcli/AbstractTestWithTestDir.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package nl.knaw.dans.dvcli;/*
* Copyright (C) 2024 DANS - Data Archiving and Networked Services ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.BeforeEach;

import java.nio.file.Path;

/**
* A test class that creates a test directory for each test method.
*/
public abstract class AbstractTestWithTestDir {
protected final Path testDir = Path.of("target/test")
.resolve(getClass().getSimpleName());

@BeforeEach
public void setUp() throws Exception {
if (testDir.toFile().exists()) {
// github stumbled: https://github.com/DANS-KNAW/dans-layer-store-lib/actions/runs/8705753485/job/23876831089?pr=7#step:4:106
FileUtils.deleteDirectory(testDir.toFile());
}
}
}
Loading

0 comments on commit be134dd

Please sign in to comment.