remove use of security manager in exit code checker tests, fix tests for MARC field stream, rename filter to all to imply the complexity of the operation

This commit is contained in:
Jörg Prante 2022-11-01 00:44:39 +01:00
parent 4b0d391ad7
commit 4ff083db34
5 changed files with 7 additions and 162 deletions

View file

@ -31,9 +31,6 @@ dependencies {
testImplementation libs.json testImplementation libs.json
testImplementation libs.xalan testImplementation libs.xalan
testImplementation libs.xmlunit testImplementation libs.xmlunit
testImplementation (libs.system.rules) {
exclude module: 'junit'
}
testImplementation(libs.mockito) { testImplementation(libs.mockito) {
exclude group: 'org.hamcrest' exclude group: 'org.hamcrest'
} }

View file

@ -13,7 +13,6 @@ dependencyResolutionManagement {
library('json', 'org.xbib', 'content-json').version('4.0.0') library('json', 'org.xbib', 'content-json').version('4.0.0')
library('xalan', 'xalan', 'xalan').version('2.7.2') library('xalan', 'xalan', 'xalan').version('2.7.2')
library('xmlunit', 'org.xmlunit', 'xmlunit-matchers').version('2.8.4') library('xmlunit', 'org.xmlunit', 'xmlunit-matchers').version('2.8.4')
library('system-rules', 'com.github.stefanbirkner', 'system-rules').version('1.19.0')
library('mockito', 'org.mockito', 'mockito-core').version('3.3.3') library('mockito', 'org.mockito', 'mockito-core').version('3.3.3')
library('marc4j', 'org.marc4j', 'marc4j').version('2.9.2') library('marc4j', 'org.marc4j', 'marc4j').version('2.9.2')
} }

View file

@ -108,7 +108,7 @@ public class MarcRecordTest {
// single 245 field // single 245 field
List<MarcField> list = new ArrayList<>(); List<MarcField> list = new ArrayList<>();
Pattern pattern = Pattern.compile("^245.*"); Pattern pattern = Pattern.compile("^245.*");
marcRecord.filter(field -> pattern.matcher(field.getTag()).matches(), list::add); marcRecord.all(field -> pattern.matcher(field.getTag()).matches(), list::add);
assertEquals(1, list.size()); assertEquals(1, list.size());
} }
} }
@ -232,10 +232,10 @@ public class MarcRecordTest {
.filter(m -> m.getTag().equals("100")).findFirst().get().getFirstSubfieldValue("a")); .filter(m -> m.getTag().equals("100")).findFirst().get().getFirstSubfieldValue("a"));
assertEquals(4, marcRecord.getFields().size()); assertEquals(4, marcRecord.getFields().size());
List<MarcField> list = new LinkedList<>(); List<MarcField> list = new LinkedList<>();
marcRecord.filter(f -> "016".equals(f.getTag()), list::add); marcRecord.all(f -> "016".equals(f.getTag()), list::add);
assertEquals(2, list.size()); assertEquals(2, list.size());
AtomicBoolean match = new AtomicBoolean(); AtomicBoolean match = new AtomicBoolean();
marcRecord.filter(f -> "016".equals(f.getTag()) && "7 ".equals(f.getIndicator()), f -> { marcRecord.all(f -> "016".equals(f.getTag()) && "7 ".equals(f.getIndicator()), f -> {
if ("DE-600".equals(f.getFirstSubfieldValue("2"))) { if ("DE-600".equals(f.getFirstSubfieldValue("2"))) {
match.set("23-1".equals(f.getFirstSubfieldValue("a"))); match.set("23-1".equals(f.getFirstSubfieldValue("a")));
} }
@ -259,7 +259,7 @@ public class MarcRecordTest {
Map<String, Object> map = Map.of("001", "123", Map<String, Object> map = Map.of("001", "123",
"100", Map.of("_", Map.of("a", "Hello World"))); "100", Map.of("_", Map.of("a", "Hello World")));
MarcRecord marcRecord = MarcRecord.from(map); MarcRecord marcRecord = MarcRecord.from(map);
marcRecord.filter("001", field -> assertEquals("123", field.getValue())); marcRecord.all("001", field -> assertEquals("123", field.getValue()));
marcRecord.filter("100", field -> assertEquals("Hello World", field.getFirstSubfieldValue("a"))); marcRecord.all("100", field -> assertEquals("Hello World", field.getFirstSubfieldValue("a")));
} }
} }

View file

@ -1,145 +0,0 @@
/**
* Copyright 2016-2022 Jörg Prante <joergprante@gmail.com>
*
* 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
*
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0</a>
*
* 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 org.xbib.marc.tools;
import org.junit.contrib.java.lang.system.internal.CheckExitCalled;
import org.junit.contrib.java.lang.system.internal.NoExitSecurityManager;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
import org.junit.platform.commons.support.ReflectionSupport;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.System.getSecurityManager;
import static java.lang.System.setSecurityManager;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
/**
* This class is original inspired from project {@code system-rules},
* rewritten to JUnit5. It is a JUnit Jupiter extension that allows
* in-test specification of expected {@code System.exit(...)} calls.
*/
@Target({TYPE, METHOD})
@Retention(RUNTIME)
@ExtendWith(ExpectedSystemExit.Extension.class)
public @interface ExpectedSystemExit {
class Extension implements BeforeEachCallback,
AfterEachCallback,
BeforeAllCallback,
ParameterResolver,
TestExecutionExceptionHandler {
private NoExitSecurityManager noExitSecurityManager;
private SecurityManager originalManager;
@Override
public void beforeAll(ExtensionContext context) {
noExitSecurityManager = new NoExitSecurityManager(getSecurityManager());
}
@Override
public void beforeEach(ExtensionContext context) {
originalManager = getSecurityManager();
setSecurityManager(noExitSecurityManager);
}
@Override
public void afterEach(ExtensionContext context) {
NoExitSecurityManager securityManager = (NoExitSecurityManager) getSecurityManager();
ExitCapture exitCapture = getExitCapture(context);
if (exitCapture.expectExit) {
checkSystemExit(securityManager, exitCapture);
}
setSecurityManager(originalManager);
}
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
boolean isTestMethodLevel = extensionContext.getTestMethod().isPresent();
boolean isOutputCapture = parameterContext.getParameter().getType() == ExitCapture.class;
return isTestMethodLevel && isOutputCapture;
}
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return getExitCapture(extensionContext);
}
@Override
public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
ExitCapture exitCapture = getExitCapture(context);
if (!(throwable instanceof CheckExitCalled) || !exitCapture.expectExit) {
throw throwable;
}
}
private void checkSystemExit(NoExitSecurityManager securityManager, ExitCapture exitCapture) {
if (securityManager.isCheckExitCalled()) {
exitCapture.handleSystemExitWithStatus(securityManager.getStatusOfFirstCheckExitCall());
} else {
exitCapture.handleMissingSystemExit();
}
}
private ExitCapture getExitCapture(ExtensionContext context) {
Store store = context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
return store.getOrComputeIfAbsent(ExitCapture.class, ReflectionSupport::newInstance, ExitCapture.class);
}
}
class ExitCapture {
private boolean expectExit = false;
private Integer expectedStatus = null;
public void expectSystemExit() {
expectExit = true;
}
public void expectSystemExitWithStatus(int status) {
expectSystemExit();
expectedStatus = status;
}
private void handleMissingSystemExit() {
if (expectExit) {
fail("System.exit has not been called.");
}
}
private void handleSystemExitWithStatus(int status) {
if (!expectExit) {
fail("Unexpected call of System.exit(" + status + ").");
} else if (expectedStatus != null) {
assertEquals(expectedStatus, Integer.valueOf(status), "Wrong exit status");
}
}
}
}

View file

@ -15,27 +15,22 @@
*/ */
package org.xbib.marc.tools; package org.xbib.marc.tools;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@Disabled("system exit ends testing?")
public class ToolTest { public class ToolTest {
@Test @Test
@ExpectedSystemExit public void testToolSimple() {
public void testToolSimple(ExpectedSystemExit.ExitCapture exitCapture) {
String[] args = { String[] args = {
"--in", "src/test/resources/org/xbib/marc/chabon.mrc", "--in", "src/test/resources/org/xbib/marc/chabon.mrc",
"--charset", "ANSEL", "--charset", "ANSEL",
"--out", "build/chabon.mrc.xml" "--out", "build/chabon.mrc.xml"
}; };
exitCapture.expectSystemExitWithStatus(0);
MarcTool.main(args); MarcTool.main(args);
} }
@Test @Test
@ExpectedSystemExit public void testToolStylesheet() {
public void testToolStylesheet(ExpectedSystemExit.ExitCapture exitCapture) {
String[] args = { String[] args = {
"--in", "src/test/resources/org/xbib/marc/summerland.mrc", "--in", "src/test/resources/org/xbib/marc/summerland.mrc",
"--out", "build/summerland.mrc.xml", "--out", "build/summerland.mrc.xml",
@ -44,7 +39,6 @@ public class ToolTest {
"--stylesheet", "http://www.loc.gov/standards/mods/v3/MARC21slim2MODS3.xsl", "--stylesheet", "http://www.loc.gov/standards/mods/v3/MARC21slim2MODS3.xsl",
"--result", "build/summerland.mods" "--result", "build/summerland.mods"
}; };
exitCapture.expectSystemExitWithStatus(0);
MarcTool.main(args); MarcTool.main(args);
} }
} }