You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2021/02/22 20:50:05 UTC
[jena] branch main updated: JENA-2031: More tests for IRIx
This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 5b918b4 JENA-2031: More tests for IRIx
new ccd3904 Merge pull request #931 from afs/irix-tests
5b918b4 is described below
commit 5b918b4d87a99ab11d4eb3039d0c23df83339cf6
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Mon Feb 22 13:09:00 2021 +0000
JENA-2031: More tests for IRIx
---
.../java/org/apache/jena/irix/IRIProviderJDK.java | 18 ++
.../org/apache/jena/irix/IRIProviderJenaIRI.java | 83 +++++--
.../src/main/java/org/apache/jena/irix/IRIx.java | 7 +
.../org/apache/jena/irix/AbstractTestIRIx.java | 83 +++++++
.../test/java/org/apache/jena/irix/JenaIRI.java | 79 ++++++
.../test/java/org/apache/jena/irix/TS_IRIx.java | 43 ++++
.../test/java/org/apache/jena/irix/TestIRIx.java | 72 +-----
.../java/org/apache/jena/irix/TestNormalize.java | 120 +++++++++
.../java/org/apache/jena/irix/TestRFC3986.java | 272 +++++++++++++++++++++
.../java/org/apache/jena/irix/TestRelative.java | 79 ++++++
.../java/org/apache/jena/irix/TestResolve.java | 206 ++++++++++++++++
.../java/org/apache/jena/test/TestPackage.java | 2 +-
.../java/org/apache/jena/iri/ViolationCodes.java | 2 +-
13 files changed, 976 insertions(+), 90 deletions(-)
diff --git a/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJDK.java b/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJDK.java
index 2013409..48ab041 100644
--- a/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJDK.java
+++ b/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJDK.java
@@ -20,6 +20,7 @@ package org.apache.jena.irix;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.Objects;
import java.util.function.Supplier;
/**
@@ -118,6 +119,23 @@ public class IRIProviderJDK implements IRIProvider {
return new IRIxJDK(iri2.toString(), iri2);
});
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(javaURI);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ IRIxJDK other = (IRIxJDK)obj;
+ return Objects.equals(javaURI, other.javaURI);
+ }
}
@Override
diff --git a/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJenaIRI.java b/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJenaIRI.java
index 060706d..78debe5 100644
--- a/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJenaIRI.java
+++ b/jena-core/src/main/java/org/apache/jena/irix/IRIProviderJenaIRI.java
@@ -20,6 +20,8 @@ package org.apache.jena.irix;
import java.io.PrintStream;
import java.util.Iterator;
+import java.util.Objects;
+import java.util.regex.Pattern;
import org.apache.jena.iri.*;
import org.apache.jena.iri.impl.PatternCompiler;
@@ -96,6 +98,9 @@ public class IRIProviderJenaIRI implements IRIProvider {
static private int relFlags = IRIRelativize.SAMEDOCUMENT | IRIRelativize.CHILD ;
@Override
public IRIx relativize(IRIx other) {
+ // Align of IRI3986 algorithm.
+ if (jenaIRI.getRawQuery() != null )
+ return null;
IRIxJena iriOther = (IRIxJena)other;
IRI iri2 = jenaIRI.relativize(iriOther.jenaIRI, relFlags);
if ( iri2.equals(iriOther.jenaIRI))
@@ -103,6 +108,23 @@ public class IRIProviderJenaIRI implements IRIProvider {
IRIProviderJenaIRI.exceptions(iri2);
return new IRIxJena(iri2.toString(), iri2);
}
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(jenaIRI);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj )
+ return true;
+ if ( obj == null )
+ return false;
+ if ( getClass() != obj.getClass() )
+ return false;
+ IRIxJena other = (IRIxJena)obj;
+ return Objects.equals(jenaIRI, other.jenaIRI);
+ }
}
@Override
@@ -110,6 +132,12 @@ public class IRIProviderJenaIRI implements IRIProvider {
// "create" - does not throw exceptions
IRI iriObj = iriFactory().create(iriStr);
// errors and warnings.
+ if ( STRICT_FILE && isFILE(iriObj) ) {
+ if ( iriStr.startsWith("file://" ) && ! iriStr.startsWith("file:///") )
+ throw new IRIException("file: URLs should start file:///");
+ }
+ if ( isUUID(iriObj) )
+ checkUUID(iriObj, iriStr);
exceptions(iriObj);
return new IRIProviderJenaIRI.IRIxJena(iriStr, iriObj);
}
@@ -161,21 +189,8 @@ public class IRIProviderJenaIRI implements IRIProvider {
Violation v = vIter.next();
int code = v.getViolationCode() ;
// Filter codes.
- if ( code == Violation.PERCENT_ENCODING_SHOULD_BE_UPPERCASE)
- continue;
-
- if ( code == Violation.SCHEME_PATTERN_MATCH_FAILED && isURN(iri) && ! STRICT_URN )
- continue;
-
- if ( code == Violation.REQUIRED_COMPONENT_MISSING && isFILE(iri) )
- // jena-iri implements the earlier RFCs, not RFC8089 which adds "file:local"
- continue;
- //break to retain errors
+ // Global settings below; this section is for conditional filtering.
switch(code) {
- //case Violation.LOWERCASE_PREFERRED:
- case Violation.PERCENT_ENCODING_SHOULD_BE_UPPERCASE:
- continue;
-
case Violation.SCHEME_PATTERN_MATCH_FAILED:
if ( isURN(iri) && ! STRICT_URN )
continue;
@@ -183,11 +198,12 @@ public class IRIProviderJenaIRI implements IRIProvider {
continue;
break;
case Violation.REQUIRED_COMPONENT_MISSING:
- if ( isFILE(iri) && ! STRICT_FILE )
+ // jena-iri handling of file: URIs is only for (an interpretation of) RFC 1738.
+ // RFC8089 allows relative file URIs and a wider use of characters.
+ if ( isFILE(iri) )
continue;
- default:
}
- String msg = iri.violations(false).next().getShortMessage();
+ String msg = v.getShortMessage();
throw new IRIException(msg);
}
return iri;
@@ -196,7 +212,27 @@ public class IRIProviderJenaIRI implements IRIProvider {
private static boolean isURN(IRI iri) { return "urn".equalsIgnoreCase(iri.getScheme()); }
private static boolean isFILE(IRI iri) { return "file".equalsIgnoreCase(iri.getScheme()); }
- private static final boolean ShowResolverSetup = false;
+ // Checks trailing part of URI.
+ // Works on "urn:" and "urn:uuid:".
+ private static Pattern UUID_PATTERN = Pattern.compile(":[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
+
+ private boolean isUUID(IRI iri) {
+ if ( "uuid".equalsIgnoreCase(iri.getScheme()) )
+ return true;
+ return iri.getRawPath().startsWith("uuid:");
+ }
+
+ private void checkUUID(IRI iriObj, String original) {
+ if ( iriObj.getRawFragment() != null )
+ throw new IRIException("Fragment used with UUID");
+ if ( iriObj.getRawQuery() != null )
+ throw new IRIException("Query used with UUID");
+ boolean matches = UUID_PATTERN.matcher(original).matches();
+ if ( !matches )
+ throw new IRIException("Not a valid UUID string: "+original);
+ }
+
+ private static final boolean ShowResolverSetup = false;
private static final IRIFactory iriFactoryInst = new IRIFactory();
static {
@@ -216,14 +252,17 @@ public class IRIProviderJenaIRI implements IRIProvider {
// Accept any scheme.
setErrorWarning(iriFactoryInst, ViolationCodes.UNREGISTERED_IANA_SCHEME, false, false);
- setErrorWarning(iriFactoryInst, ViolationCodes.NON_INITIAL_DOT_SEGMENT, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.UNREGISTERED_NONIETF_SCHEME_TREE, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.NON_INITIAL_DOT_SEGMENT, false, false);
setErrorWarning(iriFactoryInst, ViolationCodes.LOWERCASE_PREFERRED, false, true);
setErrorWarning(iriFactoryInst, ViolationCodes.REQUIRED_COMPONENT_MISSING, true, true);
- // Choices: setting here does not seem to have any effect. See CheckerIRI and IRIProviderJena for filtering.
-// //setErrorWarning(iriFactoryInst, ViolationCodes.PERCENT_ENCODING_SHOULD_BE_UPPERCASE, false, true);
-// //setErrorWarning(iriFactoryInst, ViolationCodes.SCHEME_PATTERN_MATCH_FAILED, false, true);
+ setErrorWarning(iriFactoryInst, ViolationCodes.PERCENT_ENCODING_SHOULD_BE_UPPERCASE, false, false);
+
+ // jena-iri has not been updated for percent in DNS name (RFC 3986)
+ setErrorWarning(iriFactoryInst, ViolationCodes.NOT_DNS_NAME, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.USE_PUNYCODE_NOT_PERCENTS, false, false);
// NFC tests are not well understood by general developers and these cause confusion.
// See JENA-864
diff --git a/jena-core/src/main/java/org/apache/jena/irix/IRIx.java b/jena-core/src/main/java/org/apache/jena/irix/IRIx.java
index ccae1b2..aa37a20 100644
--- a/jena-core/src/main/java/org/apache/jena/irix/IRIx.java
+++ b/jena-core/src/main/java/org/apache/jena/irix/IRIx.java
@@ -186,6 +186,13 @@ public abstract class IRIx {
return iriString;
}
+ // Provide value-based equality.
+ @Override
+ public abstract int hashCode();
+
+ @Override
+ public abstract boolean equals(Object other);
+
/**
* User readable form. Not guaranteed to be usable as a string
* in other API calls.
diff --git a/jena-core/src/test/java/org/apache/jena/irix/AbstractTestIRIx.java b/jena-core/src/test/java/org/apache/jena/irix/AbstractTestIRIx.java
new file mode 100644
index 0000000..b4135a0
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/AbstractTestIRIx.java
@@ -0,0 +1,83 @@
+/*
+ * 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.jena.irix;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.runners.Parameterized.Parameters;
+
+/** Test suite driver for IRIx */
+public class AbstractTestIRIx {
+
+ @Parameters(name = "{index}: {0}")
+ public static Iterable<Object[]> data() {
+ SystemIRIx.init();
+ List<Object[]> data = new ArrayList<>();
+ //data.add(new Object[]{"IRI3986", new IRIProvider3986()});
+ data.add(new Object[]{"JenaIRI", new IRIProviderJenaIRI()});
+ // Does not pass the test suite.
+ //data.add(new Object[]{"JDK.URI", new IRIProviderJDK()});
+ return data;
+ }
+
+ protected static void setProvider(IRIProvider provider) {
+ provider.strictMode("urn", true);
+ provider.strictMode("file", true);
+ SystemIRIx.setProvider(provider);
+ }
+
+ protected static IRIProvider getProvider() {
+ return SystemIRIx.getProvider();
+ }
+
+ protected void notStrict(String scheme, Runnable action) {
+ provider.strictMode(scheme, false);
+ try { action.run(); }
+ finally { provider.strictMode(scheme, true); }
+ }
+
+ private final IRIProvider provider;
+ private static IRIProvider systemProvider;
+
+ @BeforeClass static public void beforeClass() {
+ systemProvider = getProvider();
+ }
+
+ @AfterClass static public void afterClass() {
+ setProvider(systemProvider);
+ }
+
+ @Before public void beforeTest() {
+ systemProvider = getProvider();
+ setProvider(provider);
+ }
+
+ @After public void afterTest() {
+ setProvider(systemProvider);
+ }
+
+ protected AbstractTestIRIx(String name, IRIProvider provider) {
+ this.provider = provider;
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/irix/JenaIRI.java b/jena-core/src/test/java/org/apache/jena/irix/JenaIRI.java
new file mode 100644
index 0000000..d15dd29
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/JenaIRI.java
@@ -0,0 +1,79 @@
+/*
+ * 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.jena.irix;
+
+import org.apache.jena.iri.IRIFactory;
+import org.apache.jena.iri.ViolationCodes;
+
+// The Jena IRI settings using in ARQ/RIOT.
+class JenaIRI {
+
+ public static IRIFactory iriFactory() {
+ return iriFactoryInst;
+ }
+
+ private static final IRIFactory iriFactoryInst = new IRIFactory();
+ static {
+ iriFactoryInst.useSpecificationIRI(true);
+ iriFactoryInst.useSchemeSpecificRules("*", true);
+
+ // Allow relative references for file: URLs.
+ iriFactoryInst.setSameSchemeRelativeReferences("file");
+
+ // Convert "SHOULD" to warning (default is "error").
+ // iriFactory.shouldViolation(false,true);
+
+ // Accept any scheme.
+ setErrorWarning(iriFactoryInst, ViolationCodes.UNREGISTERED_IANA_SCHEME, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.UNREGISTERED_NONIETF_SCHEME_TREE, false, false);
+
+ setErrorWarning(iriFactoryInst, ViolationCodes.NON_INITIAL_DOT_SEGMENT, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.LOWERCASE_PREFERRED, false, true);
+ setErrorWarning(iriFactoryInst, ViolationCodes.REQUIRED_COMPONENT_MISSING, true, true);
+
+ setErrorWarning(iriFactoryInst, ViolationCodes.PERCENT_ENCODING_SHOULD_BE_UPPERCASE, false, false);
+
+ // jena-iri has not been updated for percent in DNS name (RFC 3986)
+ setErrorWarning(iriFactoryInst, ViolationCodes.NOT_DNS_NAME, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.USE_PUNYCODE_NOT_PERCENTS, false, false);
+
+ // NFC tests are not well understood by general developers and these cause confusion.
+ // See JENA-864
+ // NFC is in RDF 1.1 so do test for that.
+ // https://www.w3.org/TR/rdf11-concepts/#section-IRIs
+ // Leave switched on as a warning.
+ //setErrorWarning(iriFactoryInst, ViolationCodes.NOT_NFC, false, false);
+
+ // NFKC is not mentioned in RDF 1.1. Switch off.
+ setErrorWarning(iriFactoryInst, ViolationCodes.NOT_NFKC, false, false);
+
+ // ** Applies to various unicode blocks.
+ // The set of legal characters depends on the Java version.
+ // If not set, this causes test failures in Turtle and Trig eval tests.
+ // "Any" unicode codepoint.
+ setErrorWarning(iriFactoryInst, ViolationCodes.COMPATIBILITY_CHARACTER, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.UNDEFINED_UNICODE_CHARACTER, false, false);
+ setErrorWarning(iriFactoryInst, ViolationCodes.UNASSIGNED_UNICODE_CHARACTER, false, false);
+ }
+
+ private static void setErrorWarning(IRIFactory factory, int code, boolean isError, boolean isWarning) {
+ factory.setIsError(code, isError);
+ factory.setIsWarning(code, isWarning);
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TS_IRIx.java b/jena-core/src/test/java/org/apache/jena/irix/TS_IRIx.java
new file mode 100644
index 0000000..affa067
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/TS_IRIx.java
@@ -0,0 +1,43 @@
+/*
+ * 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.jena.irix;
+
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.TestSuite;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses( {
+ // IRIx tests with matrix of providers.
+ TestIRIx.class,
+ TestRFC3986.class,
+ TestResolve.class,
+ TestNormalize.class,
+ TestRelative.class,
+} )
+
+public class TS_IRIx {
+ public static TestSuite suite() {
+ TestSuite ts = new TestSuite();
+ ts.setName("IRIx");
+ ts.addTest(new JUnit4TestAdapter(TS_IRIx.class));
+ return ts;
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TestIRIx.java b/jena-core/src/test/java/org/apache/jena/irix/TestIRIx.java
index 347cba7..fae9c44 100644
--- a/jena-core/src/test/java/org/apache/jena/irix/TestIRIx.java
+++ b/jena-core/src/test/java/org/apache/jena/irix/TestIRIx.java
@@ -18,74 +18,18 @@
package org.apache.jena.irix;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.JUnit4TestAdapter;
-import junit.framework.TestSuite;
-import org.junit.*;
+import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public class TestIRIx {
-
- public static TestSuite suite() {
- TestSuite ts = new TestSuite();
- ts.setName("IRIx");
- ts.addTest(new JUnit4TestAdapter(TestIRIx.class));
- return ts;
- }
-
- // These are not complete tests for IRIs.
- // They cover corner cases and the expected functionality of IRI
- // providers and assume that RFC3986 parsing is (mostly) correct.
- // (by taking the tests from iri4ld they could be made complete).
-
- @Parameters(name = "{index}: {0}")
- public static Iterable<Object[]> data() {
- List<Object[]> data = new ArrayList<>();
- data.add(new Object[]{"JenaIRI", new IRIProviderJenaIRI()});
- // Future
- // data.add(new Object[]{"IRI3986", new IRIProvider3986()});
- // For completeness: see javadoc for reasons not to use this.
- // data.add(new Object[]{"JDK.URI", new IRIProviderJDK()});
- return data;
- }
-
- private void notStrict(String scheme, Runnable action) {
- provider.strictMode(scheme, false);
- try { action.run(); }
- finally { provider.strictMode(scheme, true); }
- }
-
- private final IRIProvider provider;
- private static IRIProvider systemProvider;
-
- @BeforeClass static public void beforeClass() {
- systemProvider = SystemIRIx.getProvider();
- }
-
- @AfterClass static public void afterClass() {
- SystemIRIx.setProvider(systemProvider);
- }
-
- @Before public void beforeTest() {
- systemProvider = SystemIRIx.getProvider();
- provider.strictMode("urn", true);
- provider.strictMode("file", true);
- SystemIRIx.setProvider(provider);
- }
-
- @After public void afterTest() {
- SystemIRIx.setProvider(systemProvider);
- }
+public class TestIRIx extends AbstractTestIRIx {
public TestIRIx(String name, IRIProvider provider) {
- this.provider = provider;
+ super(name, provider);
}
// ---- RFC 3986 Grammar
@@ -124,7 +68,7 @@ public class TestIRIx {
// [] not in IPv6 address
public void http_07() { parse("http://h/ab[]"); }
- public void http_08() { parse("http://example/~jena/file"); }
+ @Test public void http_08() { parse("http://example/~jena/file"); }
// -- Compliance with URN scheme: https://tools.ietf.org/html/rfc8141
@@ -226,10 +170,6 @@ public class TestIRIx {
@Test public void misc_01() { reference("wm:/abc", true); }
- @Test(expected=IRIException.class)
- // Bad hex code: Breaks RFC 3986 grammar.
- public void misc_02() { parse("http://h/ab%XXcd"); }
-
private void relative(String baseUriStr, String otherStr, String expected) {
IRIx base = IRIx.create(baseUriStr);
IRIx relInput = IRIx.create(otherStr);
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TestNormalize.java b/jena-core/src/test/java/org/apache/jena/irix/TestNormalize.java
new file mode 100644
index 0000000..212f0a9
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/TestNormalize.java
@@ -0,0 +1,120 @@
+/*
+ * 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.jena.irix;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeFalse;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class TestNormalize extends AbstractTestIRIx {
+
+ public TestNormalize(String name, IRIProvider provider) {
+ super(name, provider);
+ }
+
+ @Test
+ public void normalize_01() {
+ testNormalize("http://host/a/b/c?q=1#2", "http://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_02() {
+ testNormalize("HtTp://host/a/b/c?q=1#2", "http://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_03() {
+ testNormalize("HTTP://HOST/a/b/c?q=1#2", "http://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_04() {
+ testNormalize("HTTP://HOST:/a/b/c?q=1#2", "http://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_05() {
+ testNormalize("HTTP://HOST:80/a/b/c?q=1#2", "http://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_06() {
+ testNormalize("HTTPs://HOST:443/a/b/c?q=1#2", "https://host/a/b/c?q=1#2");
+ }
+
+ @Test
+ public void normalize_07() {
+ testNormalize("http://host", "http://host/");
+ }
+
+ @Test
+ public void normalize_08() {
+ testNormalize("http://host#frag", "http://host/#frag");
+ }
+
+ @Test
+ public void normalize_09() {
+ testNormalize("http://host?q=s", "http://host/?q=s");
+ }
+
+ @Test
+ public void normalize_10() {
+ testNormalize("http://host/?q=s", "http://host/?q=s");
+ }
+
+ @Test
+ public void normalize_11() {
+ testNormalize("http://host%20/?q=s", "http://host%20/?q=s");
+ }
+
+ @Test
+ public void normalize_12() {
+ testNormalize("http://hOSt%20/?q=s", "http://host%20/?q=s");
+ }
+
+ @Test
+ public void normalize_13() {
+ testNormalize("http://hOSt%20/foo%62ar?q=s", "http://host%20/foobar?q=s");
+ }
+
+ @Test
+ public void normalize_14() {
+ testNormalize("http://host/foobar?q=s%74", "http://host/foobar?q=st");
+ }
+
+ @Test
+ public void normalize_15() {
+ testNormalize("http://host/foobar#%7E", "http://host/foobar#~");
+ }
+
+ private void testNormalize(String input, String expected) {
+ // jena-iri does not implement normalization.
+ assumeFalse("jena-iri does not implement normalization", SystemIRIx.getProvider() instanceof IRIProviderJenaIRI );
+// if ( SystemIRIx.getProvider() instanceof IRIProviderJenaIRI )
+// return;
+ IRIx iri = IRIx.create(input);
+ IRIx iri2 = iri.normalize();
+ String s = iri2.toString();
+ assertEquals(expected, s);
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TestRFC3986.java b/jena-core/src/test/java/org/apache/jena/irix/TestRFC3986.java
new file mode 100644
index 0000000..14c9c2c
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/TestRFC3986.java
@@ -0,0 +1,272 @@
+/*
+ * 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.jena.irix;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import org.apache.jena.iri.IRI;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)
+public class TestRFC3986 extends AbstractTestIRIx {
+ public TestRFC3986(String name, IRIProvider provider) {
+ super(name, provider);
+ }
+
+ // Assumes full authority parsing and not scheme-specific checks.
+
+ @Test public void parse_00() { good("http://host"); }
+
+ @Test public void parse_01() { good("http://host:8081/abc/def?qs=ghi#jkl"); }
+
+ @Test public void parse_02() { good("http://[::1]:8080/abc/def?qs=ghi#jkl"); }
+
+ // jena-iri does not allow %XX in the authority. It originated pre-3986 and does not seem to have updated completely.
+ // %XX in host added at RFC 3986.
+ @Test public void parse_03() { goodNoIRICheck("http://ab%AAdef/xyzβ/abc"); }
+
+ @Test public void parse_04() { good("/abcdef"); }
+
+ @Test public void parse_05() { good("/ab%FFdef"); }
+
+ // jena-iri mandates upper case. The RFC 3986 grammar only has upper case but the normalization section discusses lower case.
+ // Unclear status.
+ @Test public void parse_06() { goodNoIRICheck("/ab%ffdef"); }
+
+ @Test public void parse_07() { good("http://host/abcdef?qs=foo#frag"); }
+
+ @Test public void parse_08() { good(""); }
+
+ @Test public void parse_09() { good("."); }
+
+ @Test public void parse_10() { good(".."); }
+
+ @Test public void parse_11() { good("//host:8081/abc/def?qs=ghi#jkl"); }
+
+ @Test public void parse_12() { goodNoIRICheck("a+.-9://h/"); }
+
+ // No path.
+
+ @Test public void parse_13() { good("http://host"); }
+
+ @Test public void parse_14() { good("http://host#frag"); }
+
+ @Test public void parse_15() { good("http://host?query"); }
+
+ // : in first segment in path.
+ @Test public void parse_16() { good("http://host/a:b/"); }
+
+ @Test public void parse_17() { good("/a:b/"); }
+
+ @Test public void parse_18() { good("/z/a:b"); }
+
+ @Test public void equality_01() {
+ String s = "https://jena.apache.org/";
+ IRIx iri1 = IRIx.create(s);
+ IRIx iri2 = IRIx.create(s);
+ assertEquals(iri1, iri2);
+ assertEquals(iri1.hashCode(), iri2.hashCode());
+ }
+
+ // HTTP scheme specific rules.
+ @Test public void parse_http_01() { badSpecific("http:///file/name.txt"); }
+
+ // HTTP scheme specific rules.
+ @Test public void parse_http_02() { badSpecific("HTTP:///file/name.txt"); }
+
+ // This is treated as legal with path and no authority.
+ //@Test public void parse_http_02a() { badSpecific("http:/file/name.txt"); }
+
+ @Test public void parse_http_03() { badSpecific("http://users@host/file/name.txt"); }
+
+ @Test public void parse_http_04() { good("nothttp://users@host/file/name.txt"); }
+
+ @Test public void parse_http_05() { good("nothttp://users@/file/name.txt"); }
+
+ @Test public void parse_file_01() { good("file:///file/name.txt"); }
+
+ // We reject "file://host/" forms.
+ @Test public void parse_file_02() { badSpecific("file://host/file/name.txt"); }
+
+ // This is legal by RFC 8089 (jena-iri, based on the original RFC 1738, fails this with missing authority).
+ @Test public void parse_file_03() { goodNoIRICheck("file:/file/name.txt"); }
+
+ @Test public void parse_urn_01() { good("urn:x-local:abc/def"); }
+
+ // rq-components = [ "?+" r-component ]
+ // [ "?=" q-component ]
+
+ @Test public void parse_urn_02() { good("urn:x-local:abc/def?+more"); }
+
+ @Test public void parse_urn_03() { good("urn:x-local:abc/def?=123"); }
+
+ @Test public void parse_urn_04() { good("urn:x-local:abc/def?+resolve?=123#frag"); }
+
+ @Test public void parse_urn_05() { good("urn:abc0:def"); }
+
+ @Test public void parse_ftp_01() { good("ftp://user@host:3333/abc/def?qs=ghi#jkl"); }
+
+ @Test public void parse_ftp_02() { good("ftp://[::1]/abc/def?qs=ghi#jkl"); }
+
+ // ---- bad
+
+ // Leading ':'
+ @Test public void bad_scheme_1() { bad(":segment"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_2() { bad("://host/xyz"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_3() { bad("1://host/xyz"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_4() { bad("a~b://host/xyz"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_5() { bad("aβ://host/xyz"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_6() { bad("_:xyz"); }
+
+ // Bad scheme
+ @Test public void bad_scheme_7() { bad("a_b:xyz"); }
+
+ // Space!
+ @Test public void bad_chars_1() { bad("http://abcdef:80/xyz /abc"); }
+
+ // colons
+ @Test public void bad_host_1() { bad("http://abcdef:80:/xyz"); }
+
+ // Bad IPv6
+ @Test public void bad_ipv6_1() { bad("http://[::80/xyz"); }
+
+ // Bad IPv6
+ @Test public void bad_ipv6_2() { bad("http://host]/xyz"); }
+
+ // Bad IPv6
+ @Test public void bad_ipv6_3() { bad("http://[]/xyz"); }
+
+ // Multiple @
+ @Test public void bad_authority_1() { bad("ftp://abc@def@host/abc"); }
+
+ // Multiple colon in authority
+ @Test public void bad_authority_2() { bad("http://abc:def:80/abc"); }
+
+ // Bad %-encoding.
+ @Test public void bad_percent_1() { bad("http://example/abc%ZZdef"); }
+
+ @Test public void bad_percent_2() { bad("http://abc%ZZdef/"); }
+
+ // Bad %-encoded
+ @Test public void bad_percent_3() { bad("http://example/xyz%"); }
+
+ // Bad %-encoded
+ @Test public void bad_percent_4() { bad("http://example/xyz%A"); }
+
+ // Bad %-encoded
+ @Test public void bad_percent_5() { bad("http://example/xyz%A?"); }
+
+ // [] not allowed.
+ @Test public void bad_frag_1() { bad("http://eg.com/test.txt#xpointer(/unit[5])"); }
+
+ // ---- bad by scheme.
+ @Test public void parse_http_bad_01() { badSpecific("http://user@host:8081/abc/def?qs=ghi#jkl"); }
+
+ // urn:2char:1char
+ // urn:NID:NSS where NID is at least 2 alphas, and at most 32 long
+ @Test public void parse_urn_bad_01() { badSpecific("urn:"); }
+ @Test public void parse_urn_bad_02() { badSpecific("urn:x:abc"); }
+
+ @Test public void parse_urn_bad_03() { badSpecific("urn:abc:"); }
+ // 33 chars
+ @Test public void parse_urn_bad_04() { badSpecific("urn:abcdefghij-123456789-123456789-yz:a"); }
+
+ // Bad by URN specific rule for the query components.
+ @Test public void parse_urn_bad_05() { badSpecific("urn:local:abc/def?query=foo"); }
+
+ @Test public void parse_urn_uuid_bad_01() {
+ badSpecific("urn:uuid:06e775ac-2c38-11b2-801c-8086f2cc00c9?query=foo");
+ }
+
+ @Test public void parse_urn_uuid_bad_02() {
+ badSpecific("urn:uuid:06e775ac-2c38-11b2-801c-8086f2cc00c9#frag");
+ }
+
+ @Test public void parse_urn_uuid_bad_03() {
+ // Bad length
+ badSpecific("urn:uuid:06e775ac");
+ }
+
+ @Test public void parse_urn_uuid_bad_04() {
+ // Bad character
+ badSpecific("urn:uuid:06e775ac-ZZZZ-11b2-801c-8086f2cc00c9");
+ }
+
+ @Test public void parse_uuid_bad_01() {
+ badSpecific("uuid:06e775ac-2c38-11b2-801c-8086f2cc00c9?query=foo");
+ }
+
+ @Test public void parse_uuid_bad_02() {
+ badSpecific("uuid:06e775ac-2c38-11b2-801c-8086f2cc00c9#frag");
+ }
+
+ @Test public void parse_uuid_bad_03() {
+ badSpecific("uuid:06e775ac-2c38-11b2");
+ }
+
+ private void good(String string) {
+ IRIx iri = IRIx.create(string);
+ assertNotNull(iri);
+ if ( true ) {
+ IRI iri1 = JenaIRI.iriFactory().create(string);
+ if ( iri1.hasViolation(true) ) {
+ iri1.violations(true).forEachRemaining(v-> System.err.println("IRI = "+string + " :: "+v.getLongMessage()));
+ fail("Violations "+string);
+ }
+ }
+ java.net.URI javaURI = java.net.URI.create(string);
+ assertNotNull(javaURI);
+ }
+
+ private void goodNoIRICheck(String string) {
+ IRIx iri = IRIx.create(string);
+ java.net.URI javaURI = java.net.URI.create(string);
+ }
+
+ // Expect an IRIParseException
+ private void bad(String string) {
+ try {
+ IRIs.checkEx(string);
+ IRIs.reference(string);
+ //RFC3986.check(string);
+ fail("Did not fail: "+string);
+ } catch (IRIException ex) {}
+ }
+
+ private void badSpecific(String string) {
+ bad(string);
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TestRelative.java b/jena-core/src/test/java/org/apache/jena/irix/TestRelative.java
new file mode 100644
index 0000000..3c7ed87
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/TestRelative.java
@@ -0,0 +1,79 @@
+/*
+ * 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.jena.irix;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class TestRelative extends AbstractTestIRIx {
+
+ public TestRelative(String name, IRIProvider provider) {
+ super(name, provider);
+ }
+
+ @Test
+ public void relative_01() { testRelative("http://host/dir/", "http://host/dir/file", "file"); }
+
+ @Test
+ public void relative_02() { testRelative("http://host/dir/", "http://elsewhere/dir/file", null); }
+
+ @Test
+ public void relative_03() { testRelative("https://host/dir/", "http://host/dir/file", null); }
+
+ @Test
+ public void relative_04() { testRelative("http://host:1234/dir/", "http://host:1234/dir/file", "file"); }
+
+ @Test
+ public void relative_05() { testRelative("https://host:1234/dir/", "http://host:5678/dir/file", null); }
+
+ @Test
+ public void relative_06() { testRelative("http://ex/path/?query", "http://ex/path/file", null); }
+
+ @Test
+ public void relative_07() { testRelative("http://ex/path/#frag", "http://ex/path/file", "file"); }
+
+ @Test
+ public void relative_08() { testRelative("http://ex/path/", "http://ex/path/file?q=x", "file?q=x"); }
+
+ @Test
+ public void relative_09() { testRelative("http://ex/path/", "http://ex/path/file#frag", "file#frag"); }
+ @Test
+ public void relative_10() { testRelative("http://example/ns#", "http://example/x", "x") ; }
+
+ @Test
+ public void relative_11() { testRelative("http://example/ns#", "http://example/ns#x", "#x") ; }
+
+ private void testRelative(String baseStr, String pathStr, String expected) {
+ IRIx base = IRIx.create(baseStr);
+ IRIx path = IRIx.create(pathStr);
+ IRIx rel = base.relativize(path);
+ String result = (rel==null)?null:rel.str();
+ assertEquals(expected, result);
+ if ( expected != null ) {
+ IRIx path2 = base.resolve(rel);
+ assertEquals(path, path2);
+ assertEquals(path.str(), path2.str());
+ }
+ }
+}
+
diff --git a/jena-core/src/test/java/org/apache/jena/irix/TestResolve.java b/jena-core/src/test/java/org/apache/jena/irix/TestResolve.java
new file mode 100644
index 0000000..63625d6
--- /dev/null
+++ b/jena-core/src/test/java/org/apache/jena/irix/TestResolve.java
@@ -0,0 +1,206 @@
+/*
+ * 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.jena.irix;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class TestResolve extends AbstractTestIRIx {
+
+ public TestResolve(String name, IRIProvider provider) {
+ super(name, provider);
+ }
+
+ @Test
+ public void resolve_01() {
+ testResolve("http://example/dir/", "", "http://example/dir/");
+ }
+
+ @Test
+ public void resolve_02() {
+ testResolve("http://example/dir/", "A", "http://example/dir/A");
+ }
+
+ @Test
+ public void resolve_03() {
+ testResolve("http://example/dir", "A", "http://example/A");
+ }
+
+ @Test
+ public void resolve_04() {
+ testResolve("http://example/dir", "A/", "http://example/A/");
+ }
+
+ @Test
+ public void resolve_05() {
+ testResolve("http://example/dir1/dir2/dir3/dir4", "..", "http://example/dir1/dir2/");
+ }
+
+ @Test
+ public void resolve_06() {
+ testResolve("http://example/dir1/dir2/", "..", "http://example/dir1/");
+ }
+
+ @Test
+ public void resolve_07() {
+ testResolve("http://example/dir1/dir2", "..", "http://example/");
+ }
+
+ @Test
+ public void resolve_08() {
+ testResolve("http://example/dir1/dir2/f3", "..", "http://example/dir1/");
+ }
+
+ @Test
+ public void resolve_09() {
+ testResolve("http://example/dir1/dir2/", "../a", "http://example/dir1/a");
+ }
+
+ @Test
+ public void resolve_10() {
+ testResolve("http://example/dir1/dir2/f3", "../a", "http://example/dir1/a");
+ }
+
+ @Test
+ public void resolve_11() {
+ testResolve("http://example/dir1/f2", "../a", "http://example/a");
+ }
+
+ @Test
+ public void resolve_12() {
+ testResolve("http://example/dir1/dir2/", "..", "http://example/dir1/");
+ }
+
+ @Test
+ public void resolve_13() {
+ testResolve("http://example/dir/", "..", "http://example/");
+ }
+
+ @Test
+ public void resolve_14() {
+ testResolve("http://example/dir", "..", "http://example/");
+ }
+
+ @Test
+ public void resolve_15() {
+ testResolve("http://example/", "..", "http://example/");
+ }
+
+ @Test
+ public void resolve_16() {
+ testResolve("http://example", "..", "http://example/");
+ }
+
+ @Test
+ public void resolve_17() {
+ testResolve("http://example/path?query#frag", "http://host", "http://host");
+ }
+
+ @Test
+ public void resolve_18() {
+ testResolve("http://example/", "abc", "http://example/abc");
+ }
+
+ @Test
+ public void resolve_19() {
+ testResolve("http://example", "abc", "http://example/abc");
+ }
+
+ @Test
+ public void resolve_20() {
+ testResolve("http://example/dir/file", ".", "http://example/dir/");
+ }
+
+ @Test
+ public void resolve_21() {
+ testResolve("http://example/dir/", ".", "http://example/dir/");
+ }
+
+ @Test
+ public void resolve_22() {
+ testResolve("http://example/dir1/dir2/", ".", "http://example/dir1/dir2/");
+ }
+
+ @Test
+ public void resolve_23() {
+ testResolve("http://example/", ".", "http://example/");
+ }
+
+ @Test
+ public void resolve_24() {
+ testResolve("http://example/#fragment", "path?q=arg", "http://example/path?q=arg");
+ }
+
+ @Test
+ public void resolve_25() {
+ testResolve("http://example/", "../path?q=arg", "http://example/path?q=arg");
+ }
+
+ @Test
+ public void resolve_26() {
+ testResolve("http://example/?query", "../path?q=arg", "http://example/path?q=arg");
+ }
+
+ @Test
+ public void resolve_27() {
+ testResolve("http://example/?query", "../path?q=arg", "http://example/path?q=arg");
+ }
+
+ @Test
+ public void resolve_28() {
+ testResolve("http://example/path", "?query", "http://example/path?query");
+ }
+
+ @Test
+ public void resolve_29() {
+ testResolve("http://example/path", "#frag", "http://example/path#frag");
+ }
+
+ @Test
+ public void resolve_30() {
+ testResolve("http://example/path", "..#frag", "http://example/#frag");
+ }
+
+ @Test
+ public void resolve_31() {
+ testResolve("http://example/path#fragment", "..#frag", "http://example/#frag");
+ }
+
+ @Test
+ public void resolve_32() {
+ testResolve("http://example/dir1/dir2/", "/OtherPath", "http://example/OtherPath");
+ }
+
+ @Test
+ public void resolve_33() {
+ testResolve("http://example/dir1/dir2/", "//EX/OtherPath", "http://EX/OtherPath");
+ }
+
+ private void testResolve(String base, String rel, String expected) {
+ IRIx baseIRI = IRIx.create(base);
+ IRIx relIRI = IRIx.create(rel);
+ IRIx iri2 = baseIRI.resolve(relIRI);
+ String s1 = iri2.str();
+ assertEquals(expected, s1);
+ }
+}
diff --git a/jena-core/src/test/java/org/apache/jena/test/TestPackage.java b/jena-core/src/test/java/org/apache/jena/test/TestPackage.java
index ada5d77..e397a97 100644
--- a/jena-core/src/test/java/org/apache/jena/test/TestPackage.java
+++ b/jena-core/src/test/java/org/apache/jena/test/TestPackage.java
@@ -34,7 +34,7 @@ public class TestPackage extends TestCase {
TestSuite ts = new TestSuite() ;
ts.setName("Jena") ;
addTest(ts, "System setup", TestSystemSetup.suite());
- addTest(ts, "IRI", org.apache.jena.irix.TestIRIx.suite());
+ addTest(ts, "IRI", org.apache.jena.irix.TS_IRIx.suite());
addTest(ts, "Enhanced", org.apache.jena.enhanced.test.TestPackage.suite());
addTest(ts, "Datatypes", org.apache.jena.datatypes.TestPackage.suite()) ;
addTest(ts, "Graph", org.apache.jena.graph.test.TestPackage.suite());
diff --git a/jena-iri/src/main/java/org/apache/jena/iri/ViolationCodes.java b/jena-iri/src/main/java/org/apache/jena/iri/ViolationCodes.java
index d2ebe54..105f272 100644
--- a/jena-iri/src/main/java/org/apache/jena/iri/ViolationCodes.java
+++ b/jena-iri/src/main/java/org/apache/jena/iri/ViolationCodes.java
@@ -2472,7 +2472,7 @@ This class is not part of the API.
// RFC 2141 -
//"(?![uU][rR][nN]:)[a-zA-Z0-9][-a-zA-Z0-9]{1,31}:[^/~]+"
// RFC 8141 revision of 2141 - JENA-1647
- "(?![uU][rR][nN]:)[a-zA-Z0-9][-a-zA-Z0-9]{1,31}:.+"
+ "(?![uU][rR][nN]:)[a-zA-Z0-9][-a-zA-Z0-9]{0,30}[a-zA-Z0-9]:.+"
);
spec.setReserved(PATH,"/~");