From daf5a1bb9b0be132bd2a838e36a77a0ac0616e1f Mon Sep 17 00:00:00 2001 From: David Thompson Date: Fri, 16 Sep 2022 17:03:28 -0400 Subject: [PATCH] WIP add unit tests Signed-off-by: David Thompson --- .../participants/RNGErrorCode.java | 4 + .../rng/RNGURIResolverExtension.java | 9 +- .../xmlmodel/XMLModelRelaxNGValidator.java | 2 +- .../validation/RelaxNGValidationTest.java | 119 ++++++++++++++++ .../extensions/rng/RNGUriResolverTest.java | 130 ++++++++++++++++++ .../src/test/resources/rng/broken.rng | 1 + .../src/test/resources/rng/dressSize.rng | 27 ++++ 7 files changed, 287 insertions(+), 5 deletions(-) create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java create mode 100644 org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java create mode 100644 org.eclipse.lemminx/src/test/resources/rng/broken.rng create mode 100644 org.eclipse.lemminx/src/test/resources/rng/dressSize.rng diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java index 77fd5a966..0d55d68ad 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/contentmodel/participants/RNGErrorCode.java @@ -34,6 +34,7 @@ public enum RNGErrorCode implements IXMLErrorCode { IncompleteContentModel, BadTagName, BadAttribute, + BadText, MissingAttribute, InvalidRelaxNG; @@ -84,6 +85,9 @@ public static Range toLSPRange(XMLLocator location, RNGErrorCode code, String me String attrName = m.group(1); return XMLPositionUtility.selectAttributeNameFromGivenNameAt(attrName, offset, document); } + case BadText: { + return XMLPositionUtility.selectContent(offset, document); + } case InvalidRelaxNG: { for (XMLModel xmlModel : document.getXMLModels()) { if (message.contains(xmlModel.getHref())) { diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java index 6399ef105..9dd320b4e 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/rng/RNGURIResolverExtension.java @@ -30,9 +30,11 @@ */ public class RNGURIResolverExtension implements URIResolverExtension, IExternalGrammarLocationProvider { - private static final ResourceToDeploy RNG_RNG = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", + private static final ResourceToDeploy RNG_XSD = new ResourceToDeploy("http://relaxng.org/relaxng.xsd", "schemas/rng/relaxng.xsd"); + // private static final String RELAXNG_NAMESPACE = "http://relaxng.org/ns/structure/1.0"; + public RNGURIResolverExtension(IXMLDocumentProvider documentProvider) { } @@ -62,9 +64,8 @@ public String resolve(String baseLocation, String publicId, String systemId) { private String resolve(String uri) { if (DOMUtils.isRNG(uri)) { try { - // XXX: I think this triggers the download, but confirm if this is needed - CacheResourcesManager.getResourceCachePath(RNG_RNG); - return RNG_RNG.getDeployedPath().toFile().toURI().toString(); + CacheResourcesManager.getResourceCachePath(RNG_XSD); + return RNG_XSD.getDeployedPath().toFile().toURI().toString(); } catch (IOException e) { // do nothing } diff --git a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java index 2428c3aa8..14cbe346d 100644 --- a/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java +++ b/org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/xerces/xmlmodel/XMLModelRelaxNGValidator.java @@ -247,7 +247,7 @@ public void setDocumentHandler(XMLDocumentHandler handler) { @Override public XMLDocumentHandler getDocumentHandler() { - return this; // TODO: ?? + return this; } @Override diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java new file mode 100644 index 000000000..8322a34ba --- /dev/null +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/contentmodel/validation/RelaxNGValidationTest.java @@ -0,0 +1,119 @@ +/******************************************************************************* +* Copyright (c) 2022 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.contentmodel.validation; + +import org.eclipse.lemminx.extensions.contentmodel.participants.RNGErrorCode; +import org.junit.jupiter.api.Test; +import static org.eclipse.lemminx.XMLAssert.d; +import static org.eclipse.lemminx.XMLAssert.testDiagnosticsFor; + +/** + * Test validating XML files against RelaxNG schemas + * + * @author datho7561 + */ +public class RelaxNGValidationTest { + + @Test + public void relaxNGWithBrokenRNG() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(1, 17, 52, RNGErrorCode.InvalidRelaxNG)); + } + + @Test + public void relaxNGWithMissingAttributeValue() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), + d(2, 23, 23, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithBadAttributeValue() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 7, 11, RNGErrorCode.BadAttribute), + d(2, 31, 31, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithUndefinedAttribute() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 20, 24, RNGErrorCode.BadAttribute), + d(2, 36, 36, RNGErrorCode.IncompleteContentModel)); + } + + @Test + public void relaxNGWithUndefinedElement() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml, d(2, 21,25, RNGErrorCode.BadTagName)); + } + + @Test + public void relaxNGWithInvalidElementContent() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "pant"; + testDiagnosticsFor(xml, d(2, 20,24, RNGErrorCode.BadText)); + } + + @Test + public void relaxNGElementTextContentDoesntMatchType() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "pant"; + // FIXME: only the innermost error should be reported + testDiagnosticsFor(xml, d(2, 13,17, RNGErrorCode.BadText), + d(2, 7, 24, RNGErrorCode.BadText)); + } + + @Test + public void relaxNGWithValidContent1() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent2() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + ""; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent3() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "medium"; + testDiagnosticsFor(xml); + } + + @Test + public void relaxNGWithValidContent4() throws Exception { + String xml = " \r\n" + // + "\r\n" + // + "9000000"; + testDiagnosticsFor(xml); + } + +} diff --git a/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java new file mode 100644 index 000000000..38aa85498 --- /dev/null +++ b/org.eclipse.lemminx/src/test/java/org/eclipse/lemminx/extensions/rng/RNGUriResolverTest.java @@ -0,0 +1,130 @@ +/******************************************************************************* +* Copyright (c) 2022 Red Hat Inc. and others. +* All rights reserved. This program and the accompanying materials +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v20.html +* +* Contributors: +* Red Hat Inc. - initial API and implementation +*******************************************************************************/ +package org.eclipse.lemminx.extensions.rng; + +import static org.eclipse.lemminx.XMLAssert.pd; +import static org.eclipse.lemminx.XMLAssert.r; + +import org.eclipse.lemminx.AbstractCacheBasedTest; +import org.eclipse.lemminx.XMLAssert; +import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager; +import org.eclipse.lemminx.extensions.contentmodel.participants.XMLSchemaErrorCode; +import org.eclipse.lemminx.extensions.contentmodel.settings.XMLValidationRootSettings; +import org.eclipse.lemminx.services.XMLLanguageService; +import org.eclipse.lsp4j.Diagnostic; +import org.eclipse.lsp4j.DiagnosticSeverity; +import org.junit.jupiter.api.Test; + +/** + * Tests to make sure that *.rng associates with relaxng.xsd properly + * + * @author datho7561 + */ +public class RNGUriResolverTest extends AbstractCacheBasedTest { + + @Test + public void testValidatesRNGWithBadElement() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + Diagnostic d = new Diagnostic(r(0, 1, 0, 5), "cvc-elt.1.a: Cannot find the declaration of element 'asdf'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode()); + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI, d)); + } + + @Test + public void testValidatesRNGWithMissingNamespace() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + Diagnostic d1 = new Diagnostic(r(0, 1, 0, 8), + "TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of 'http://relaxng.org/ns/structure/1.0'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.TargetNamespace_2.getCode()); + + Diagnostic d2 = new Diagnostic(r(0, 1, 0, 8), "cvc-elt.1.a: Cannot find the declaration of element 'grammar'.", + DiagnosticSeverity.Error, "xml", XMLSchemaErrorCode.cvc_elt_1_a.getCode()); + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI, d1, d2)); + } + + @Test + public void testValidatesRNGThatsValid() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + String xsd = ""; + + String fileURI = "test.rng"; + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI)); + } + + @Test + public void testValidatesRNGThatsValidWithNamespaceInPrefix() throws Exception { + + XMLValidationRootSettings validation = new XMLValidationRootSettings(); + validation.setResolveExternalEntities(true); + + XMLLanguageService ls = new XMLLanguageService(); + ls.initializeIfNeeded(); + // Disable download + ContentModelManager contentModelManager = ls.getComponent(ContentModelManager.class); + contentModelManager.setDownloadExternalResources(false); + + // FIXME: namespace is not handled correctly + + // https://relaxng.org/tutorial-20011203.html + String xsd = "\n" + // + "" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n" + // + "\n"; + + String fileURI = "test.rng"; + + XMLAssert.testPublishDiagnosticsFor(xsd, fileURI, validation, ls, pd(fileURI)); + } + +} diff --git a/org.eclipse.lemminx/src/test/resources/rng/broken.rng b/org.eclipse.lemminx/src/test/resources/rng/broken.rng new file mode 100644 index 000000000..b2ed3ad6a --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/rng/broken.rng @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng b/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng new file mode 100644 index 000000000..0977e93ec --- /dev/null +++ b/org.eclipse.lemminx/src/test/resources/rng/dressSize.rng @@ -0,0 +1,27 @@ + + + + + + small + medium + large + x-large + + + + + + + + + + + + + + + + \ No newline at end of file