tdf#136822: Add VeraPDF as a PDF validator
For now, only validate those tests that are conformant with the validator verapdf-cli-1.29.0.jar has been generated using https://github.com/veraPDF/veraPDF-apps/pull/415 and running 'mvn clean install' Change-Id: Ic172100a120dc0f43f6de526660961d34dc6b415 Change-Id: Icacc8ccbd938f779b506fb5e1820f10a539ab77b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198556 Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org> Tested-by: Jenkins
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
/bin/bffvalidator.sh
|
||||
/bin/odfvalidator.sh
|
||||
/bin/officeotron.sh
|
||||
/bin/verapdf.sh
|
||||
/hardened_runtime.xcent
|
||||
/lo.xcent
|
||||
/vs-code.code-workspace.template
|
||||
|
||||
@@ -252,6 +252,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
|
||||
$(call fetch_Optional,OPENSYMBOL,OPENSYMBOL_TTF) \
|
||||
$(call fetch_Optional,ODFVALIDATOR,ODFVALIDATOR_JAR) \
|
||||
$(call fetch_Optional,OFFICEOTRON,OFFICEOTRON_JAR) \
|
||||
$(call fetch_Optional,VERAPDF,VERAPDF_JAR) \
|
||||
,$(call fetch_Download_item,https://dev-www.libreoffice.org/extern,$(item)))
|
||||
-@mkdir -p $(TARFILE_LOCATION)/cargo
|
||||
$(if $(call fetch_Optional,YRS,1),\
|
||||
|
||||
@@ -226,6 +226,7 @@ distclean : clean compilerplugins-clean mac-app-store-package.clean
|
||||
$(BUILDDIR)/bin/bffvalidator.sh \
|
||||
$(BUILDDIR)/bin/odfvalidator.sh \
|
||||
$(BUILDDIR)/bin/officeotron.sh \
|
||||
$(BUILDDIR)/bin/verapdf.sh \
|
||||
$(BUILDDIR)/config.Build.log \
|
||||
$(BUILDDIR)/config.Build.warn \
|
||||
$(BUILDDIR)/config.log \
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
java -jar @TARFILE_LOCATION_NATIVE@/@VERAPDF_JAR@ --nonpdfext "$@"
|
||||
@@ -766,6 +766,7 @@ export VCL_PLUGIN_INFO=@VCL_PLUGIN_INFO@
|
||||
export VCTOOLSET=@VCTOOLSET@
|
||||
export VCVER=@VCVER@
|
||||
export DEVENV=@DEVENV@
|
||||
export VERAPDF=@VERAPDF@
|
||||
export VISIO_CFLAGS=$(gb_SPACE)@VISIO_CFLAGS@
|
||||
export VISIO_LIBS=$(gb_SPACE)@VISIO_LIBS@
|
||||
export WGET=@WGET@
|
||||
|
||||
@@ -6197,6 +6197,7 @@ if test "$cross_compiling" = "yes"; then
|
||||
bin/bffvalidator.sh.in \
|
||||
bin/odfvalidator.sh.in \
|
||||
bin/officeotron.sh.in \
|
||||
bin/verapdf.sh.in \
|
||||
instsetoo_native/util/openoffice.lst.in \
|
||||
config_host/*.in \
|
||||
sysui/desktop/macosx/Info.plist.in \
|
||||
@@ -9653,6 +9654,31 @@ if test "$with_export_validation" != "no"; then
|
||||
else
|
||||
OFFICEOTRON="sh $OFFICEOTRON"
|
||||
fi
|
||||
|
||||
AC_PATH_PROGS(VERAPDF, verapdf)
|
||||
if test -z "$VERAPDF"; then
|
||||
# remember to download the verapdf with validator later
|
||||
AC_MSG_NOTICE([no verapdf found, will download it])
|
||||
BUILD_TYPE="$BUILD_TYPE VERAPDF"
|
||||
VERAPDF="$BUILDDIR/bin/verapdf.sh"
|
||||
|
||||
# and fetch name of verapdf jar name from download.lst
|
||||
VERAPDF_JAR=`$SED -n -e "s/^VERAPDF_JAR *:= *\(.*\) */\1/p" $SRC_ROOT/download.lst`
|
||||
AC_SUBST(VERAPDF_JAR)
|
||||
|
||||
if test -z "$VERAPDF_JAR"; then
|
||||
AC_MSG_ERROR([cannot determine verapdf jar location (--with-export-validation)])
|
||||
fi
|
||||
fi
|
||||
if test "$build_os" = "cygwin"; then
|
||||
# In case of Cygwin it will be executed from Windows,
|
||||
# so we need to run bash and absolute path to validator
|
||||
# so instead of "odfvalidator" it will be
|
||||
# something like "bash.exe C:\cygwin\opt\lo\bin\odfvalidator"
|
||||
VERAPDF="bash.exe `cygpath -m "$VERAPDF"`"
|
||||
else
|
||||
VERAPDF="sh $VERAPDF"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(OFFICEOTRON)
|
||||
else
|
||||
@@ -16274,6 +16300,7 @@ AC_CONFIG_FILES([
|
||||
bin/bffvalidator.sh
|
||||
bin/odfvalidator.sh
|
||||
bin/officeotron.sh
|
||||
bin/verapdf.sh
|
||||
instsetoo_native/util/openoffice.lst
|
||||
sysui/desktop/macosx/Info.plist
|
||||
sysui/desktop/macosx/LaunchConstraint.plist
|
||||
|
||||
@@ -539,6 +539,11 @@ OFFICEOTRON_JAR := officeotron-0.8.8.jar
|
||||
# three static lines
|
||||
# so that git cherry-pick
|
||||
# will not run into conflicts
|
||||
VERAPDF_SHA256SUM := bdeef807f7e883fe3ff4e0a4712dc216064ca670d5c857fbc94408266719f0f4
|
||||
VERAPDF_JAR := verapdf-cli-1.29.0.jar
|
||||
# three static lines
|
||||
# so that git cherry-pick
|
||||
# will not run into conflicts
|
||||
ONLINEUPDATE_SHA256SUM := 37206cf981e8409d048b59ac5839621ea107ff49af72beb9d7769a2f41da8d90
|
||||
ONLINEUPDATE_TARBALL := onlineupdate-c003be8b9727672e7d30972983b375f4c200233f-2.tar.xz
|
||||
# three static lines
|
||||
|
||||
@@ -28,7 +28,8 @@ enum ValidationFormat
|
||||
{
|
||||
OOXML,
|
||||
ODF,
|
||||
MSBINARY
|
||||
MSBINARY,
|
||||
PDF
|
||||
};
|
||||
|
||||
enum class TestFilter
|
||||
@@ -188,9 +189,9 @@ protected:
|
||||
|
||||
rtl::Reference<TestInteractionHandler> xInteractionHandler;
|
||||
|
||||
private:
|
||||
void validate(const OUString& rURL, TestFilter eFilter) const;
|
||||
void validate(TestFilter eFilter);
|
||||
|
||||
private:
|
||||
bool mbSkipValidation;
|
||||
OUString m_aBaseString;
|
||||
|
||||
|
||||
+54
-33
@@ -100,7 +100,7 @@ constexpr std::u16string_view grand_total = u"Grand total of errors in submitted
|
||||
}
|
||||
#endif
|
||||
|
||||
void UnoApiTest::validate(const OUString& rPath, TestFilter eFilter) const
|
||||
void UnoApiTest::validate(TestFilter eFilter)
|
||||
{
|
||||
ValidationFormat eFormat = ValidationFormat::ODF;
|
||||
if (eFilter == TestFilter::XLSX)
|
||||
@@ -123,6 +123,8 @@ void UnoApiTest::validate(const OUString& rPath, TestFilter eFilter) const
|
||||
eFormat = ValidationFormat::MSBINARY;
|
||||
else if (eFilter == TestFilter::PPT)
|
||||
eFormat = ValidationFormat::MSBINARY;
|
||||
else if (eFilter == TestFilter::PDF_WRITER)
|
||||
eFormat = ValidationFormat::PDF;
|
||||
else
|
||||
{
|
||||
SAL_INFO("test", "UnoApiTest::validate: unknown filter");
|
||||
@@ -139,6 +141,10 @@ void UnoApiTest::validate(const OUString& rPath, TestFilter eFilter) const
|
||||
{
|
||||
var = "ODFVALIDATOR";
|
||||
}
|
||||
else if (eFormat == ValidationFormat::PDF)
|
||||
{
|
||||
var = "VERAPDF";
|
||||
}
|
||||
else if (eFormat == ValidationFormat::MSBINARY)
|
||||
{
|
||||
#if HAVE_BFFVALIDATOR
|
||||
@@ -175,7 +181,7 @@ void UnoApiTest::validate(const OUString& rPath, TestFilter eFilter) const
|
||||
utl::TempFileNamed aOutput;
|
||||
aOutput.EnableKillingFile();
|
||||
OUString aOutputFile = aOutput.GetFileName();
|
||||
OUString aCommand = aValidator + " " + rPath + " > " + aOutputFile + " 2>&1";
|
||||
OUString aCommand = aValidator + " " + maTempFile.GetFileName() + " > " + aOutputFile + " 2>&1";
|
||||
|
||||
#if !defined _WIN32
|
||||
// For now, this is only needed by some Linux ASan builds, so keep it simply and disable it on
|
||||
@@ -199,45 +205,59 @@ void UnoApiTest::validate(const OUString& rPath, TestFilter eFilter) const
|
||||
SAL_INFO("test", "UnoApiTest::validate: executing '" << aCommand << "'");
|
||||
int returnValue = system(OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8).getStr());
|
||||
|
||||
OString aContentString = loadFile(aOutput.GetURL());
|
||||
OUString aContentOUString = OStringToOUString(aContentString, RTL_TEXTENCODING_UTF8);
|
||||
|
||||
if (eFormat == ValidationFormat::OOXML && !aContentOUString.isEmpty())
|
||||
if (eFormat == ValidationFormat::PDF)
|
||||
{
|
||||
// check for validation errors here
|
||||
sal_Int32 nIndex = aContentOUString.lastIndexOf(grand_total);
|
||||
if (nIndex == -1)
|
||||
SvMemoryStream aStream;
|
||||
SvFileStream aFileStream(aOutput.GetURL(), StreamMode::READ);
|
||||
aStream.WriteStream(aFileStream);
|
||||
aStream.Seek(0);
|
||||
xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
|
||||
// Make sure the output is well-formed.
|
||||
CPPUNIT_ASSERT(pXmlDoc);
|
||||
assertXPath(pXmlDoc, "/report/jobs/job/validationReport", "isCompliant", u"true");
|
||||
}
|
||||
else
|
||||
{
|
||||
OString aContentString = loadFile(aOutput.GetURL());
|
||||
OUString aContentOUString = OStringToOUString(aContentString, RTL_TEXTENCODING_UTF8);
|
||||
|
||||
if (eFormat == ValidationFormat::OOXML && !aContentOUString.isEmpty())
|
||||
{
|
||||
SAL_WARN("test", "no summary line");
|
||||
// check for validation errors here
|
||||
sal_Int32 nIndex = aContentOUString.lastIndexOf(grand_total);
|
||||
if (nIndex == -1)
|
||||
{
|
||||
SAL_WARN("test", "no summary line");
|
||||
}
|
||||
else
|
||||
{
|
||||
sal_Int32 nStartOfNumber = nIndex + grand_total.size();
|
||||
std::u16string_view aNumber = aContentOUString.subView(nStartOfNumber);
|
||||
sal_Int32 nErrors = o3tl::toInt32(aNumber);
|
||||
OString aMsg
|
||||
= "validation error in OOXML export: Errors: " + OString::number(nErrors);
|
||||
if (nErrors)
|
||||
{
|
||||
SAL_WARN("test", aContentOUString);
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_Int32(0), nErrors);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (eFormat == ValidationFormat::ODF && !aContentOUString.isEmpty())
|
||||
{
|
||||
sal_Int32 nStartOfNumber = nIndex + grand_total.size();
|
||||
std::u16string_view aNumber = aContentOUString.subView(nStartOfNumber);
|
||||
sal_Int32 nErrors = o3tl::toInt32(aNumber);
|
||||
OString aMsg = "validation error in OOXML export: Errors: " + OString::number(nErrors);
|
||||
if (nErrors)
|
||||
if (aContentOUString.indexOf("Error") != -1 || aContentOUString.indexOf("Fatal") != -1)
|
||||
{
|
||||
SAL_WARN("test", aContentOUString);
|
||||
CPPUNIT_FAIL(aContentString.getStr());
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(aMsg.getStr(), sal_Int32(0), nErrors);
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
OString("failed to execute: " + OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8)
|
||||
+ "\n" + OUStringToOString(aContentOUString, RTL_TEXTENCODING_UTF8))
|
||||
.getStr(),
|
||||
0, returnValue);
|
||||
}
|
||||
else if (eFormat == ValidationFormat::ODF && !aContentOUString.isEmpty())
|
||||
{
|
||||
if (aContentOUString.indexOf("Error") != -1 || aContentOUString.indexOf("Fatal") != -1)
|
||||
{
|
||||
SAL_WARN("test", aContentOUString);
|
||||
CPPUNIT_FAIL(aContentString.getStr());
|
||||
}
|
||||
}
|
||||
CPPUNIT_ASSERT_EQUAL_MESSAGE(
|
||||
OString("failed to execute: " + OUStringToOString(aCommand, RTL_TEXTENCODING_UTF8) + "\n"
|
||||
+ OUStringToOString(aContentOUString, RTL_TEXTENCODING_UTF8))
|
||||
.getStr(),
|
||||
0, returnValue);
|
||||
#else
|
||||
(void)rPath;
|
||||
(void)eFormat;
|
||||
#endif
|
||||
}
|
||||
@@ -347,8 +367,9 @@ void UnoApiTest::save(TestFilter eFilter, const uno::Sequence<beans::PropertyVal
|
||||
css::uno::Reference<frame::XStorable> xStorable(mxComponent, css::uno::UNO_QUERY_THROW);
|
||||
xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
|
||||
|
||||
if (!mbSkipValidation)
|
||||
validate(maTempFile.GetFileName(), eFilter);
|
||||
// FIXME: Don't validate pdf files by default for now
|
||||
if (!mbSkipValidation && eFilter != TestFilter::PDF_WRITER)
|
||||
validate(eFilter);
|
||||
}
|
||||
|
||||
void UnoApiTest::saveAndReload(TestFilter eFilter,
|
||||
|
||||
@@ -2385,6 +2385,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"tdf157816.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -2787,6 +2788,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"LinkWithFly.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3178,6 +3180,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142806)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"LinkPages.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
|
||||
@@ -1473,6 +1473,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf139736)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"tdf139736-1.odt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -1779,6 +1780,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf149140)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -1839,6 +1841,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testNestedSection)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"nestedsection.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -2976,6 +2979,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf154982)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"tdf154982.odt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3386,6 +3390,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf135192)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"tdf135192-1.fodp");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3518,6 +3523,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf154955)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"grouped-shape.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3653,6 +3659,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf155190)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"tdf155190.odt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3743,6 +3750,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testMediaShapeAnnot)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"vid.odt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -3883,6 +3891,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFlyFrameHyperlinkAnnot)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"image-hyperlink-alttext.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
@@ -4019,6 +4028,7 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFormControlAnnot)
|
||||
vcl::filter::PDFDocument aDocument;
|
||||
loadFromFile(u"formcontrol.fodt");
|
||||
save(TestFilter::PDF_WRITER, aMediaDescriptor.getAsConstPropertyValueList());
|
||||
validate(TestFilter::PDF_WRITER);
|
||||
|
||||
// Parse the export result.
|
||||
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
|
||||
|
||||
Reference in New Issue
Block a user