This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch 
feature/205-Managed-CASes-in-tests-should-consider-validators
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git

commit f4f1d3cf7a8ba296eda9524587eae6b329cef811
Author: Richard Eckart de Castilho <[email protected]>
AuthorDate: Thu Nov 10 12:03:50 2022 +0100

    Issue #205: Managed CASes in tests should consider validators
    
    - Validate managed (J)CASes by default
---
 .../org/apache/uima/fit/validation/Validator.java  | 24 +++++----
 .../apache/uima/fit/testing/junit/ManagedCas.java  | 62 +++++++++++++++++++---
 .../apache/uima/fit/testing/junit/ManagedJCas.java | 60 ++++++++++++++++++---
 3 files changed, 120 insertions(+), 26 deletions(-)

diff --git 
a/uimafit-core/src/main/java/org/apache/uima/fit/validation/Validator.java 
b/uimafit-core/src/main/java/org/apache/uima/fit/validation/Validator.java
index d8ccf30..f9d8fe0 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/validation/Validator.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/validation/Validator.java
@@ -6,9 +6,9 @@
  * 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
@@ -47,6 +47,7 @@ public class Validator {
 
     for (ValidationCheck check : checks) {
       try {
+        summary.add(ValidationResult.trace(check, "Trying check..."));
         if (check instanceof CasValidationCheck) {
           summary.addAll(((CasValidationCheck) 
check).validate(aJCas.getCas()));
         } else if (check instanceof JCasValidationCheck) {
@@ -56,7 +57,7 @@ public class Validator {
                   "Unknown ValidationCheck type: [" + 
check.getClass().getName() + "]");
         }
       } catch (ValidationCheckSkippedException e) {
-        summary.add(ValidationResult.info(check, "Skipped: %s", 
e.getMessage()));
+        summary.add(ValidationResult.info(check, "Skipped check: %s", 
e.getMessage()));
       } catch (ValidationCheckException e) {
         summary.add(ValidationResult.error(check, "%s", e.getMessage()));
       }
@@ -70,6 +71,7 @@ public class Validator {
 
     for (ValidationCheck check : checks) {
       try {
+        summary.add(ValidationResult.trace(check, "Trying check..."));
         if (check instanceof CasValidationCheck) {
           summary.addAll(((CasValidationCheck) check).validate(cas));
         } else if (check instanceof JCasValidationCheck) {
@@ -83,7 +85,7 @@ public class Validator {
                   "Unknown ValidationCheck type: [" + 
check.getClass().getName() + "]");
         }
       } catch (ValidationCheckSkippedException e) {
-        summary.add(ValidationResult.info(check, "Skipped: %s", 
e.getMessage()));
+        summary.add(ValidationResult.info(check, "Skipped check: %s", 
e.getMessage()));
       } catch (ValidationCheckException e) {
         summary.add(ValidationResult.error(check, "%s", e.getMessage()));
       }
@@ -111,7 +113,7 @@ public class Validator {
      * (assuming that the resulting validator is not shared between threads).
      * <p>
      * <b>Note:</b> Includes/excludes do also apply do checks added via this 
method.
-     * 
+     *
      * @param check
      *          a check instance to use.
      */
@@ -140,7 +142,7 @@ public class Validator {
      * Skip any checks with the given names. Subtypes of the given classes are 
not skipped.
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param className
      *          names of check classes to be excluded.
      */
@@ -153,7 +155,7 @@ public class Validator {
      * Skip any checks with names matching the given regular expressions.
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param patterns
      *          regular expressions matching check class names to be excluded.
      */
@@ -167,7 +169,7 @@ public class Validator {
      * of the given types).
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param types
      *          check type names to be excluded.
      */
@@ -180,7 +182,7 @@ public class Validator {
      * Retain only checks with the given names. Subtypes of the given classes 
are not retained.
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param className
      *          names of check classes to be included.
      */
@@ -193,7 +195,7 @@ public class Validator {
      * Retain any checks with names matching the given regular expressions.
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param patterns
      *          regular expressions matching check class names to be included.
      */
@@ -207,7 +209,7 @@ public class Validator {
      * of the given types).
      * <p>
      * <b>Note:</b> Excludes are applied after includes.
-     * 
+     *
      * @param types
      *          check type names to be included.
      */
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 2bf3e88..5031171 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
@@ -18,17 +18,26 @@
  */
 package org.apache.uima.fit.testing.junit;
 
+import static java.lang.String.format;
 import static java.util.Collections.newSetFromMap;
 import static java.util.Collections.synchronizedSet;
+import static java.util.stream.Collectors.joining;
 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.util.Set;
 import java.util.WeakHashMap;
 
 import org.apache.uima.UIMAException;
 import org.apache.uima.cas.CAS;
+import org.apache.uima.fit.validation.ValidationException;
+import org.apache.uima.fit.validation.ValidationSummary;
+import org.apache.uima.fit.validation.Validator;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
 import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.api.extension.TestWatcher;
@@ -41,11 +50,13 @@ import org.junit.jupiter.api.extension.TestWatcher;
  * handed out to any thread are reset (except any CASes which may meanwhile 
have been garbage
  * collected).
  */
-public final class ManagedCas
-        implements TestWatcher, BeforeTestExecutionCallback, AfterAllCallback {
+public final class ManagedCas implements TestWatcher, 
BeforeTestExecutionCallback,
+        AfterTestExecutionCallback, AfterAllCallback {
   private final ThreadLocal<CAS> casHolder;
 
-  private final static Set<CAS> managedCases = 
synchronizedSet(newSetFromMap(new WeakHashMap<>()));
+  private final Set<CAS> managedCases = synchronizedSet(newSetFromMap(new 
WeakHashMap<>()));
+
+  private Validator validator = new Validator.Builder().build();
 
   /**
    * Provides a CAS with an auto-detected type system.
@@ -57,7 +68,7 @@ public final class ManagedCas
         managedCases.add(cas);
         return cas;
       } catch (UIMAException e) {
-        throw new RuntimeException(e);
+        return fail("Unable to initialize managed CAS", e);
       }
     });
   }
@@ -75,7 +86,7 @@ public final class ManagedCas
         managedCases.add(cas);
         return cas;
       } catch (UIMAException e) {
-        throw new RuntimeException(e);
+        return fail("Unable to initialize managed CAS", e);
       }
     });
   }
@@ -87,13 +98,48 @@ public final class ManagedCas
     return casHolder.get();
   }
 
+  @Override
+  public void afterAll(ExtensionContext aContext) throws Exception {
+    casHolder.remove();
+  }
+
   @Override
   public void beforeTestExecution(ExtensionContext aContext) throws Exception {
-    managedCases.forEach(cas -> cas.reset());
+    managedCases.forEach(CAS::reset);
   }
 
   @Override
-  public void afterAll(ExtensionContext aContext) throws Exception {
-    casHolder.set(null);
+  public void afterTestExecution(ExtensionContext context) throws Exception {
+    managedCases.forEach(this::assertValid);
+  }
+
+  public ManagedCas skipValidation() {
+    validator = null;
+    return this;
+  }
+
+  public ManagedCas withValidator(Validator aValidator) {
+    this.validator = aValidator;
+    return this;
+  }
+
+  private void assertValid(CAS aJCas) {
+    if (validator == null) {
+      return;
+    }
+
+    try {
+      ValidationSummary summary = validator.check(aJCas);
+
+      String messageBuffer = summary.getResults().stream()
+              .filter(r -> r.getSeverity().isEquallyOrMoreSevereThan(ERROR))
+              .map(r -> format("[%s] %s", r.getSource(), 
r.getMessage())).collect(joining("\n"));
+
+      if (messageBuffer.length() > 0) {
+        Assertions.fail(messageBuffer);
+      }
+    } catch (ValidationException e) {
+      Assertions.fail("Unable to validate CAS", e);
+    }
   }
 }
\ No newline at end of file
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 7879453..759c1f7 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
@@ -18,17 +18,26 @@
  */
 package org.apache.uima.fit.testing.junit;
 
+import static java.lang.String.format;
 import static java.util.Collections.newSetFromMap;
 import static java.util.Collections.synchronizedSet;
+import static java.util.stream.Collectors.joining;
 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.util.Set;
 import java.util.WeakHashMap;
 
 import org.apache.uima.UIMAException;
+import org.apache.uima.fit.validation.ValidationException;
+import org.apache.uima.fit.validation.ValidationSummary;
+import org.apache.uima.fit.validation.Validator;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
 import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.api.extension.TestWatcher;
@@ -41,11 +50,13 @@ import org.junit.jupiter.api.extension.TestWatcher;
  * handed out to any thread are reset (except any JCases which may meanwhile 
have been garbage
  * collected).
  */
-public final class ManagedJCas
-        implements TestWatcher, BeforeTestExecutionCallback, AfterAllCallback {
+public final class ManagedJCas implements TestWatcher, 
BeforeTestExecutionCallback,
+        AfterTestExecutionCallback, AfterAllCallback {
   private final ThreadLocal<JCas> casHolder;
 
-  private final static Set<JCas> managedCases = 
synchronizedSet(newSetFromMap(new WeakHashMap<>()));
+  private final Set<JCas> managedCases = synchronizedSet(newSetFromMap(new 
WeakHashMap<>()));
+
+  private Validator validator = new Validator.Builder().build();
 
   /**
    * Provides a JCas with an auto-detected type system.
@@ -57,7 +68,7 @@ public final class ManagedJCas
         managedCases.add(cas);
         return cas;
       } catch (UIMAException e) {
-        throw new RuntimeException(e);
+        return fail("Unable to initialize managed JCas", e);
       }
     });
   }
@@ -75,7 +86,7 @@ public final class ManagedJCas
         managedCases.add(cas);
         return cas;
       } catch (UIMAException e) {
-        throw new RuntimeException(e);
+        return fail("Unable to initialize managed JCas", e);
       }
     });
   }
@@ -89,11 +100,46 @@ public final class ManagedJCas
 
   @Override
   public void afterAll(ExtensionContext aContext) throws Exception {
-    casHolder.set(null);
+    casHolder.remove();
   }
 
   @Override
   public void beforeTestExecution(ExtensionContext aContext) throws Exception {
-    managedCases.forEach(cas -> cas.reset());
+    managedCases.forEach(JCas::reset);
+  }
+
+  @Override
+  public void afterTestExecution(ExtensionContext context) throws Exception {
+    managedCases.forEach(this::assertValid);
+  }
+
+  public ManagedJCas skipValidation() {
+    validator = null;
+    return this;
+  }
+
+  public ManagedJCas withValidator(Validator aValidator) {
+    this.validator = aValidator;
+    return this;
+  }
+
+  private void assertValid(JCas aJCas) {
+    if (validator == null) {
+      return;
+    }
+
+    try {
+      ValidationSummary summary = validator.check(aJCas);
+
+      String messageBuffer = summary.getResults().stream()
+              .filter(r -> r.getSeverity().isEquallyOrMoreSevereThan(ERROR))
+              .map(r -> format("[%s] %s", r.getSource(), 
r.getMessage())).collect(joining("\n"));
+
+      if (messageBuffer.length() > 0) {
+        Assertions.fail(messageBuffer);
+      }
+    } catch (ValidationException e) {
+      Assertions.fail("Unable to validate CAS", e);
+    }
   }
 }
\ No newline at end of file

Reply via email to