Repository: w3c/epubcheck
Pull request #1585 (2024-12-23 10:22:45)

fix: re[prt the container creation date
Also enable test cases for the XML report.


Patch:
diff --git a/pom.xml b/pom.xml
index 99910d02..16d3671a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -170,12 +170,6 @@
             <artifactId>json-path-assert</artifactId>
             <version>2.8.0</version>
         </dependency>
-        <dependency>
-            <groupId>xmlunit</groupId>
-            <artifactId>xmlunit</artifactId>
-            <version>1.3</version>
-            <scope>test</scope>
-        </dependency>
         <dependency>
     	        <groupId>io.cucumber</groupId>
     	        <artifactId>cucumber-java</artifactId>
diff --git a/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java b/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java
index 1461b3f8..cb2a3ada 100755
--- a/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java
+++ b/src/main/java/com/adobe/epubcheck/ocf/OCFChecker.java
@@ -250,16 +250,6 @@ public final class OCFChecker extends AbstractChecker
       }
       return false;
     }
-    // FIXME 2022 - report container info
-    // long l = container.getTimeEntry(OCFData.containerEntry);
-    // if (l > 0)
-    // {
-    // Date d = new Date(l);
-    // String formattedDate = new
-    // SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(d);
-    // report.info(OCFData.containerEntry, FeatureEnum.CREATION_DATE,
-    // formattedDate);
-    // }
 
     ValidationContext containerFileContext = state.context()
         .url(OCFMetaFile.CONTAINER.asURL(container)).mimetype("application/xml").build();
@@ -559,9 +549,14 @@ public final class OCFChecker extends AbstractChecker
   {
     for (FeatureEnum feature : resource.getProperties().keySet())
     {
-      // report.info(context.path, feature,
-      // resource.getProperties().get(feature));
-      report.info(resource.getPath(), feature, resource.getProperties().get(feature));
+      if (feature == FeatureEnum.CREATION_DATE
+          && !OCFMetaFile.CONTAINER.asPath().equals(resource.getPath()))
+      {
+        // we only report the creation date once
+        continue;
+      }
+      report.info(resource.getPath(), feature,
+          resource.getProperties().get(feature));
     }
   }
 
diff --git a/src/main/java/com/adobe/epubcheck/ocf/OCFZipResources.java b/src/main/java/com/adobe/epubcheck/ocf/OCFZipResources.java
index 6ee1bf75..170c170f 100644
--- a/src/main/java/com/adobe/epubcheck/ocf/OCFZipResources.java
+++ b/src/main/java/com/adobe/epubcheck/ocf/OCFZipResources.java
@@ -5,6 +5,8 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.Map;
@@ -48,11 +50,14 @@ public class OCFZipResources implements Iterable<OCFResource>
         throws NoSuchElementException
       {
         final ZipEntry entry = entries.nextElement();
+
         final Map<FeatureEnum, String> properties = ImmutableMap.<FeatureEnum, String> builder()
             .put(FeatureEnum.SIZE, String.valueOf(entry.getSize()))
             .put(FeatureEnum.COMPRESSED_SIZE, String.valueOf(entry.getCompressedSize()))
             .put(FeatureEnum.COMPRESSION_METHOD, getCompressionMethod(entry))
             .put(FeatureEnum.SHA_256, getSHAHash(entry, zip))
+            .put(FeatureEnum.CREATION_DATE,
+                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(new Date(entry.getTime())))
             .build();
 
         return new OCFResource()
@@ -87,7 +92,7 @@ public class OCFZipResources implements Iterable<OCFResource>
           {
             return entry.getName();
           }
-          
+
           @Override
           public String toString()
           {


Test patch:
diff --git a/src/test/java/org/w3c/epubcheck/test/JSONReportAssertionSteps.java b/src/test/java/org/w3c/epubcheck/test/JSONReportAssertionSteps.java
index b69fa4ff..9411843e 100644
--- a/src/test/java/org/w3c/epubcheck/test/JSONReportAssertionSteps.java
+++ b/src/test/java/org/w3c/epubcheck/test/JSONReportAssertionSteps.java
@@ -19,7 +19,7 @@ import io.cucumber.java.en.Then;
 public class JSONReportAssertionSteps
 {
 
-  private TestReport report;
+  final private TestReport report;
 
   public JSONReportAssertionSteps(TestConfiguration configuration)
   {
diff --git a/src/test/java/org/w3c/epubcheck/test/XMLReportAssertionSteps.java b/src/test/java/org/w3c/epubcheck/test/XMLReportAssertionSteps.java
new file mode 100644
index 00000000..dbcffe9f
--- /dev/null
+++ b/src/test/java/org/w3c/epubcheck/test/XMLReportAssertionSteps.java
@@ -0,0 +1,115 @@
+package org.w3c.epubcheck.test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.emptyIterable;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.StringReader;
+import java.util.function.Supplier;
+
+import javax.xml.transform.stream.StreamSource;
+
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import net.sf.saxon.s9api.DocumentBuilder;
+import net.sf.saxon.s9api.Processor;
+import net.sf.saxon.s9api.SaxonApiException;
+import net.sf.saxon.s9api.XPathCompiler;
+import net.sf.saxon.s9api.XPathSelector;
+import net.sf.saxon.s9api.XdmNode;
+
+public class XMLReportAssertionSteps
+{
+
+  private final TestReport report;
+  private final Processor processor;
+  private final XPathCompiler xpathCompiler;
+  Supplier<XdmNode> xml = new Supplier<XdmNode>()
+  {
+    XdmNode xml = null;
+
+    @Override
+    public XdmNode get()
+    {
+      if (xml == null)
+      {
+
+        // Parse the XML report
+        DocumentBuilder docBuilder = processor.newDocumentBuilder();
+        try
+        {
+          xml = docBuilder.build(new StreamSource(new StringReader(report.getOutput())));
+        } catch (SaxonApiException e)
+        {
+          assertThat(e.getMessage(), false);
+        }
+      }
+      return xml;
+    }
+  };
+
+  public XMLReportAssertionSteps(TestConfiguration configuration)
+  {
+    this.report = configuration.getReport();
+
+    // Configure Saxon
+    this.processor = new Processor(false);
+    processor.getUnderlyingConfiguration()
+        .setStandardErrorOutput(new PrintStream(new OutputStream()
+        {
+          // TODO when upgrading to Java 11, replace by
+          // OutputStream#nullOutputStream()
+          @Override
+          public void write(int b)
+            throws IOException
+          {
+          }
+        }));
+    xpathCompiler = processor.newXPathCompiler();
+  }
+
+  @Given("the default namespace is {string}")
+  public void setDefaultNamespace(String namespace)
+  {
+    xpathCompiler.declareNamespace("", namespace);
+  }
+
+  @Then("the XML report is well-formed")
+  public void xmlIsWellFormed()
+  {
+    // Parsing errors would be raised in the constructor already
+  }
+
+  @Then("(the )XPath (value of ){string} is true")
+  public void xpathIsTrue(String xpath)
+    throws SaxonApiException
+  {
+    assertThat(eval(xpath).effectiveBooleanValue(), is(true));
+  }
+
+  @Then("(the )XPath {string} exists")
+  public void xpathExists(String xpath)
+    throws SaxonApiException
+  {
+    assertThat(eval(xpath), is(not(emptyIterable())));
+
+  }
+
+  private XPathSelector eval(String xpath)
+  {
+    try
+    {
+      XPathSelector result = xpathCompiler.compile(xpath).load();
+      result.setContextItem(xml.get());
+      return result;
+    } catch (SaxonApiException e)
+    {
+      throw new IllegalArgumentException(e);
+    }
+  }
+
+}
diff --git a/src/test/resources/reporting/xml-report.feature b/src/test/resources/reporting/xml-report.feature
new file mode 100644
index 00000000..7606676d
--- /dev/null
+++ b/src/test/resources/reporting/xml-report.feature
@@ -0,0 +1,21 @@
+ Feature: EPUBCheck - XML Report tests
+  
+  Checks the XML (JHove) report format
+
+
+  Background: 
+    Given EPUB test files located at '/reporting/files/'
+    And the reporting format is set to XML
+    And EPUBCheck with default settings
+    Given the default namespace is 'http://schema.openpreservation.org/ois/xml/ns/jhove'
+
+  Scenario: Basic well-formedness checks
+    When checking EPUB 'minimal'
+    Then the XML report is well-formed
+    And XPath '//repInfo' exists
+
+  Scenario: Creation date is set
+    When checking EPUB 'minimal'
+    And XPath '//repInfo/created' exists
+
+