This is an automated email from the ASF dual-hosted git repository. rec pushed a commit to branch bugfix/231-CAS-not-reset-if-validation-fails-in-managed-CASes in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git
commit 94dc9a19b93878870cd843ceb730579ea9967b96 Author: Richard Eckart de Castilho <r...@apache.org> AuthorDate: Wed Jul 5 12:17:33 2023 +0200 Issue #231: CAS not reset if validation fails in managed CASes - Fix issue that CAS is not reset if validation fails - Added unit tests --- .../apache/uima/fit/testing/junit/ManagedCas.java | 22 +++++++- .../apache/uima/fit/testing/junit/ManagedJCas.java | 22 +++++++- .../uima/fit/testing/junit/ManagedCasTest.java | 66 ++++++++++++++++++++++ .../uima/fit/testing/junit/ManagedJCasTest.java | 66 ++++++++++++++++++++++ 4 files changed, 170 insertions(+), 6 deletions(-) diff --git a/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedCas.java b/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedCas.java index 98b6aac..a1edd91 100644 --- a/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedCas.java +++ b/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedCas.java @@ -26,6 +26,7 @@ import static org.apache.uima.fit.factory.CasFactory.createCas; import static org.apache.uima.fit.validation.ValidationResult.Severity.ERROR; import static org.junit.jupiter.api.Assertions.fail; +import java.lang.invoke.MethodHandles; import java.util.Set; import java.util.WeakHashMap; @@ -41,6 +42,8 @@ import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.platform.commons.logging.Logger; +import org.junit.platform.commons.logging.LoggerFactory; /** * Provides a {@link CAS} object which is automatically reset before the test. The idea of this @@ -53,6 +56,8 @@ import org.junit.jupiter.api.extension.TestWatcher; public final class ManagedCas implements TestWatcher, AfterTestExecutionCallback, AfterAllCallback { private final ThreadLocal<CAS> casHolder; + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final Set<CAS> managedCases = synchronizedSet(newSetFromMap(new WeakHashMap<>())); private Validator defaultValidator = new Validator.Builder().build(); @@ -117,9 +122,20 @@ public final class ManagedCas implements TestWatcher, AfterTestExecutionCallback public void afterTestExecution(ExtensionContext context) throws Exception { try { managedCases.forEach(this::assertValid); - managedCases.forEach(CAS::reset); } finally { - this.validator = null; + reset(); + } + } + + private void reset() { + this.validator = null; + + for (CAS cas : managedCases) { + try { + cas.reset(); + } catch (Exception e) { + LOG.error(e, () -> "Unable to reset managed CAS"); + } } } @@ -165,7 +181,7 @@ public final class ManagedCas implements TestWatcher, AfterTestExecutionCallback return this; } - private Validator getValidator() { + Validator getValidator() { if (validator != null) { return validator; } diff --git a/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedJCas.java b/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedJCas.java index 8ff2a55..99a1c9c 100644 --- a/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedJCas.java +++ b/uimafit-junit/src/main/java/org/apache/uima/fit/testing/junit/ManagedJCas.java @@ -26,6 +26,7 @@ import static org.apache.uima.fit.factory.JCasFactory.createJCas; import static org.apache.uima.fit.validation.ValidationResult.Severity.ERROR; import static org.junit.jupiter.api.Assertions.fail; +import java.lang.invoke.MethodHandles; import java.util.Set; import java.util.WeakHashMap; @@ -41,6 +42,8 @@ import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.AfterTestExecutionCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestWatcher; +import org.junit.platform.commons.logging.Logger; +import org.junit.platform.commons.logging.LoggerFactory; /** * Provides a {@link JCas} object which is automatically reset before the test. The idea of this @@ -54,6 +57,8 @@ public final class ManagedJCas implements TestWatcher, AfterTestExecutionCallback, AfterAllCallback { private final ThreadLocal<JCas> casHolder; + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private final Set<JCas> managedCases = synchronizedSet(newSetFromMap(new WeakHashMap<>())); private Validator defaultValidator = new Validator.Builder().build(); @@ -118,9 +123,20 @@ public final class ManagedJCas public void afterTestExecution(ExtensionContext context) throws Exception { try { managedCases.forEach(this::assertValid); - managedCases.forEach(JCas::reset); } finally { - this.validator = null; + reset(); + } + } + + private void reset() { + this.validator = null; + + for (JCas cas : managedCases) { + try { + cas.reset(); + } catch (Exception e) { + LOG.error(e, () -> "Unable to reset managed CAS"); + } } } @@ -166,7 +182,7 @@ public final class ManagedJCas return this; } - private Validator getValidator() { + Validator getValidator() { if (validator != null) { return validator; } diff --git a/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedCasTest.java b/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedCasTest.java new file mode 100644 index 0000000..56ca059 --- /dev/null +++ b/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedCasTest.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.uima.fit.testing.junit; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import org.apache.uima.cas.CAS; +import org.apache.uima.fit.validation.ValidationResult; +import org.apache.uima.fit.validation.Validator; +import org.junit.jupiter.api.Test; +import org.opentest4j.AssertionFailedError; + +class ManagedCasTest { + + private ManagedCas sut = new ManagedCas(); + + @Test + void thatValidatorIsResetBeforeNextTest() throws Exception { + Validator defaultValidator = sut.getValidator(); + Validator transientValidator = new Validator.Builder().build(); + sut.withValidator(transientValidator); + assertThat(sut.getValidator()).isSameAs(transientValidator); + sut.afterTestExecution(null); + assertThat(sut.getValidator()).isSameAs(defaultValidator); + } + + @Test + void thatCasIsResetBeforeNextTest() throws Exception { + CAS cas = sut.get(); + cas.setDocumentText("test"); + sut.afterTestExecution(null); + assertThat(cas.getDocumentText()).isNull(); + } + + @Test + void thatCasIsResetBeforeNextTestIfValidationFails() throws Exception { + sut.withValidator(new Validator.Builder() + .withCheck(cas -> asList(ValidationResult.error(this, "fail"))).build()); + CAS cas = sut.get(); + cas.setDocumentText("test"); + assertThatExceptionOfType(AssertionFailedError.class) // + .as("Validation should fail") // + .isThrownBy(() -> sut.afterTestExecution(null)); + assertThat(cas.getDocumentText()) // + .as("Despite failed validation, CAS should have been reset") // + .isNull(); + } +} diff --git a/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedJCasTest.java b/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedJCasTest.java new file mode 100644 index 0000000..e07cdd1 --- /dev/null +++ b/uimafit-junit/src/test/java/org/apache/uima/fit/testing/junit/ManagedJCasTest.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.uima.fit.testing.junit; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import org.apache.uima.fit.validation.ValidationResult; +import org.apache.uima.fit.validation.Validator; +import org.apache.uima.jcas.JCas; +import org.junit.jupiter.api.Test; +import org.opentest4j.AssertionFailedError; + +class ManagedJCasTest { + + private ManagedJCas sut = new ManagedJCas(); + + @Test + void thatValidatorIsResetBeforeNextTest() throws Exception { + Validator defaultValidator = sut.getValidator(); + Validator transientValidator = new Validator.Builder().build(); + sut.withValidator(transientValidator); + assertThat(sut.getValidator()).isSameAs(transientValidator); + sut.afterTestExecution(null); + assertThat(sut.getValidator()).isSameAs(defaultValidator); + } + + @Test + void thatCasIsResetBeforeNextTest() throws Exception { + JCas cas = sut.get(); + cas.setDocumentText("test"); + sut.afterTestExecution(null); + assertThat(cas.getDocumentText()).isNull(); + } + + @Test + void thatCasIsResetBeforeNextTestIfValidationFails() throws Exception { + sut.withValidator(new Validator.Builder() + .withCheck(cas -> asList(ValidationResult.error(this, "fail"))).build()); + JCas cas = sut.get(); + cas.setDocumentText("test"); + assertThatExceptionOfType(AssertionFailedError.class) // + .as("Validation should fail") // + .isThrownBy(() -> sut.afterTestExecution(null)); + assertThat(cas.getDocumentText()) // + .as("Despite failed validation, JCAS should have been reset") // + .isNull(); + } +}