diff --git a/src/main/java/org/eclipse/uprotocol/transport/validate/UAttributesValidator.java b/src/main/java/org/eclipse/uprotocol/transport/validate/UAttributesValidator.java
index 7e0d6462..f6ca727b 100644
--- a/src/main/java/org/eclipse/uprotocol/transport/validate/UAttributesValidator.java
+++ b/src/main/java/org/eclipse/uprotocol/transport/validate/UAttributesValidator.java
@@ -443,7 +443,7 @@ public void validateSink(UAttributes attributes) {
if (!attributes.hasSink() || attributes.getSink() == UUri.getDefaultInstance()) {
throw new ValidationException("Missing Sink");
}
- if (!UriValidator.isDefaultResourceId(attributes.getSink())) {
+ if (!UriValidator.isNotificationDestination(attributes.getSink())) {
throw new ValidationException("Invalid Sink Uri");
}
}
diff --git a/src/main/java/org/eclipse/uprotocol/uri/factory/UriFactory.java b/src/main/java/org/eclipse/uprotocol/uri/factory/UriFactory.java
index 7b80c587..8d50e110 100644
--- a/src/main/java/org/eclipse/uprotocol/uri/factory/UriFactory.java
+++ b/src/main/java/org/eclipse/uprotocol/uri/factory/UriFactory.java
@@ -12,7 +12,12 @@
*/
package org.eclipse.uprotocol.uri.factory;
+
+import java.util.Objects;
+import java.util.Optional;
+
import org.eclipse.uprotocol.Uoptions;
+import org.eclipse.uprotocol.uri.validator.UriValidator;
import org.eclipse.uprotocol.v1.UUri;
import com.google.protobuf.DescriptorProtos.ServiceOptions;
@@ -24,7 +29,9 @@
public final class UriFactory {
public static final String WILDCARD_AUTHORITY = "*";
- public static final int WILDCARD_ENTITY_ID = 0xFFFF;
+ public static final int WILDCARD_ENTITY_TYPE_ID = 0x0000_FFFF;
+ public static final int WILDCARD_ENTITY_INSTANCE_ID = 0xFFFF_0000;
+ public static final int WILDCARD_ENTITY_ID = WILDCARD_ENTITY_TYPE_ID | WILDCARD_ENTITY_INSTANCE_ID;
public static final int WILDCARD_ENTITY_VERSION = 0xFF;
public static final int WILDCARD_RESOURCE_ID = 0xFFFF;
@@ -42,39 +49,52 @@ private UriFactory() {
}
/**
- * Builds a UEntity for an protobuf generated code Service Descriptor.
- *
- * @param descriptor The protobuf generated code Service Descriptor.
- * @param resourceId The resource id.
- * @return Returns a UEntity for an protobuf generated code Service Descriptor.
+ * Creates a uProtocol URI for a resource defined by a protobuf service descriptor.
+ *
+ * The descriptor is expected to contain {@link Uoptions#serviceId service ID}
+ * and {@link Uoptions#serviceVersionMajor major version} options.
+ *
+ * @param descriptor The service descriptor to create the URI for.
+ * @param resourceId The resource ID to create the URI for.
+ * @return The URI.
+ * @throws NullPointerException if the descriptor is {@code null}.
+ * @throws IllegalArgumentException if the descriptor does not contain the required options
+ * or if the options can not be used to create a valid uProtocol URI.
*/
public static UUri fromProto(ServiceDescriptor descriptor, int resourceId) {
return fromProto(descriptor, resourceId, null);
}
/**
- * Builds a UEntity for an protobuf generated code Service Descriptor.
+ * Creates a uProtocol URI for a resource defined by a protobuf service descriptor.
+ *
+ * The descriptor is expected to contain {@link Uoptions#serviceId service ID}
+ * and {@link Uoptions#serviceVersionMajor major version} options.
*
- * @param descriptor The protobuf generated code Service Descriptor.
- * @param resourceId The resource id.
- * @param authorityName The authority name.
- * @return Returns a UEntity for an protobuf generated code Service Descriptor.
+ * @param descriptor The service descriptor to create the URI for.
+ * @param resourceId The resource ID to create the URI for.
+ * @param authorityName The URI's authority name or {@code null} to create a local URI.
+ * @return The URI.
+ * @throws NullPointerException if the descriptor is {@code null}.
+ * @throws IllegalArgumentException if the descriptor does not contain the required options
+ * or if the options can not be used to create a valid uProtocol URI.
*/
public static UUri fromProto(ServiceDescriptor descriptor, int resourceId, String authorityName) {
- if (descriptor == null) {
- return UUri.getDefaultInstance();
- }
-
+ Objects.requireNonNull(descriptor);
final ServiceOptions options = descriptor.getOptions();
+ if (!options.hasExtension(Uoptions.serviceId) || !options.hasExtension(Uoptions.serviceVersionMajor)) {
+ throw new IllegalArgumentException(
+ "The provided descriptor does not contain the required uProtocol options.");
+ }
UUri.Builder builder = UUri.newBuilder()
.setUeId(options.getExtension(Uoptions.serviceId))
.setUeVersionMajor(options.getExtension(Uoptions.serviceVersionMajor))
.setResourceId(resourceId);
- if (authorityName != null && !authorityName.isEmpty()) {
- builder.setAuthorityName(authorityName);
- }
- return builder.build();
+ Optional.ofNullable(authorityName).ifPresent(builder::setAuthorityName);
+ final var uuri = builder.build();
+ UriValidator.validate(uuri);
+ return uuri;
}
}
diff --git a/src/main/java/org/eclipse/uprotocol/uri/serializer/UriSerializer.java b/src/main/java/org/eclipse/uprotocol/uri/serializer/UriSerializer.java
index 08ea6299..c9525ad3 100644
--- a/src/main/java/org/eclipse/uprotocol/uri/serializer/UriSerializer.java
+++ b/src/main/java/org/eclipse/uprotocol/uri/serializer/UriSerializer.java
@@ -12,114 +12,140 @@
*/
package org.eclipse.uprotocol.uri.serializer;
-import org.eclipse.uprotocol.uri.factory.UriFactory;
+import java.net.URI;
+import java.util.Objects;
+import java.util.Optional;
+
import org.eclipse.uprotocol.uri.validator.UriValidator;
import org.eclipse.uprotocol.v1.UUri;
/**
- * UUri Serializer that serializes a UUri to a long format string per
- * https://github.com/eclipse-uprotocol/uprotocol-spec/blob/main/basics/uri.adoc.
+ * Provides functionality for serializing and deserializing {@link UUri}s to/from their
+ * corresponding URI representation as defined by the uProtocol specification.
+ *
+ * @see
+ * uProtocol URI Specification
*/
public interface UriSerializer {
-
+ String SCHEME_UP = "up";
/**
- * Support for serializing {@link UUri} objects into their String format.
+ * Serializes a {@link UUri} into its URI representation.
*
- * @param uri {@link UUri} object to be serialized to the String format.
- * @return Returns the String format of the supplied {@link UUri} that can be
- * used as a sink or a source in a uProtocol publish communication.
+ * @param uuri The UUri to be serialized.
+ * @return The URI.
+ * @throws NullPointerException if the UUri is null.
+ * @throws IllegalArgumentException if the UUri does not comply with the UUri specification.
*/
- static String serialize(UUri uri) {
- if (uri == null || UriValidator.isEmpty(uri)) {
- return "";
- }
-
+ // [impl->dsn~uri-authority-mapping~1]
+ // [impl->dsn~uri-path-mapping~1]
+ // [impl->req~uri-serialization~1]
+ static String serialize(UUri uuri) {
+ Objects.requireNonNull(uuri);
+ UriValidator.validate(uuri);
StringBuilder sb = new StringBuilder();
- if (!uri.getAuthorityName().isBlank()) {
+ if (!uuri.getAuthorityName().isBlank()) {
sb.append("//");
- sb.append(uri.getAuthorityName());
+ sb.append(uuri.getAuthorityName());
}
sb.append("/");
final var pathSegments = String.format("%X/%X/%X",
- uri.getUeId(),
- uri.getUeVersionMajor(),
- uri.getResourceId());
+ uuri.getUeId(),
+ uuri.getUeVersionMajor(),
+ uuri.getResourceId());
sb.append(pathSegments);
return sb.toString();
}
/**
- * Deserialize a String into a UUri object.
+ * Deserializes a URI into a UUri.
*
- * @param uProtocolUri A long format uProtocol URI.
- * @return Returns an UUri data object.
+ * @param uProtocolUri The URI to deserialize.
+ * @return The UUri.
+ * @throws NullPointerException if the URI is null.
+ * @throws IllegalArgumentException if the URI is invalid.
*/
+ // [impl->dsn~uri-authority-name-length~1]
+ // [impl->dsn~uri-scheme~1]
+ // [impl->dsn~uri-host-only~2]
+ // [impl->dsn~uri-authority-mapping~1]
+ // [impl->dsn~uri-path-mapping~1]
+ // [impl->req~uri-serialization~1]
static UUri deserialize(String uProtocolUri) {
- if (uProtocolUri == null) {
- return UUri.getDefaultInstance();
- }
+ Objects.requireNonNull(uProtocolUri);
+ final var parsedUri = URI.create(uProtocolUri);
+ return deserialize(parsedUri);
+ }
- String uri = uProtocolUri.contains(":") ? uProtocolUri.substring(uProtocolUri.indexOf(":") + 1)
- : uProtocolUri
- .replace('\\', '/');
+ /**
+ * Deserializes a URI into a UUri.
+ *
+ * @param uProtocolUri The URI to deserialize.
+ * @return The UUri.
+ * @throws NullPointerException if the URI is null.
+ * @throws IllegalArgumentException if the URI is invalid.
+ */
+ // [impl->dsn~uri-authority-name-length~1]
+ // [impl->dsn~uri-scheme~1]
+ // [impl->dsn~uri-host-only~2]
+ // [impl->dsn~uri-authority-mapping~1]
+ // [impl->dsn~uri-path-mapping~1]
+ // [impl->req~uri-serialization~1]
+ static UUri deserialize(URI uProtocolUri) {
+ Objects.requireNonNull(uProtocolUri);
+
+ if (uProtocolUri.getScheme() != null && !SCHEME_UP.equals(uProtocolUri.getScheme())) {
+ throw new IllegalArgumentException("uProtocol URI must use '%s' scheme".formatted(SCHEME_UP));
+ }
+ if (uProtocolUri.getQuery() != null) {
+ throw new IllegalArgumentException("uProtocol URI must not contain query");
+ }
+ if (uProtocolUri.getFragment() != null) {
+ throw new IllegalArgumentException("uProtocol URI must not contain fragment");
+ }
+ UriValidator.validateParsedAuthority(uProtocolUri);
- boolean isLocal = !uri.startsWith("//");
+ final var pathSegments = uProtocolUri.getPath().split("/");
+ if (pathSegments.length != 4) {
+ throw new IllegalArgumentException("uProtocol URI must have exactly 3 path segments");
+ }
- final String[] uriParts = uri.split("/");
- final int numberOfPartsInUri = uriParts.length;
+ final var builder = UUri.newBuilder();
+ Optional.ofNullable(uProtocolUri.getAuthority()).ifPresent(builder::setAuthorityName);
- if (numberOfPartsInUri == 0 || numberOfPartsInUri == 1) {
- return UUri.getDefaultInstance();
+ if (pathSegments[1].isEmpty()) {
+ throw new IllegalArgumentException("URI must contain non-empty entity ID");
}
-
- UUri.Builder builder = UUri.newBuilder();
try {
- if (isLocal) {
- builder.setUeId(Integer.parseUnsignedInt(uriParts[1], 16));
- if (numberOfPartsInUri > 2) {
- builder.setUeVersionMajor(Integer.parseUnsignedInt(uriParts[2], 16));
-
- if (numberOfPartsInUri > 3) {
- builder.setResourceId(Integer.parseUnsignedInt(uriParts[3], 16));
- }
- }
- } else {
- // If authority is blank, it is an error
- if (uriParts[2].isBlank()) {
- return UUri.getDefaultInstance();
- }
- builder.setAuthorityName(uriParts[2]);
-
- if (uriParts.length > 3) {
- builder.setUeId(Integer.parseUnsignedInt(uriParts[3], 16));
- if (numberOfPartsInUri > 4) {
- builder.setUeVersionMajor(Integer.parseUnsignedInt(uriParts[4], 16));
-
- if (numberOfPartsInUri > 5) {
- builder.setResourceId(Integer.parseUnsignedInt(uriParts[5], 16));
- }
-
- }
- }
- }
+ builder.setUeId(Integer.parseUnsignedInt(pathSegments[1], 16));
} catch (NumberFormatException e) {
- return UUri.getDefaultInstance();
+ throw new IllegalArgumentException("URI must contain 32 bit hex-encoded entity ID", e);
}
- // Ensure the major version is less than the wildcard
- if (builder.getUeVersionMajor() > UriFactory.WILDCARD_ENTITY_VERSION) {
- return UUri.getDefaultInstance();
+ if (pathSegments[2].isEmpty()) {
+ throw new IllegalArgumentException("URI must contain non-empty entity version");
}
-
- // Ensure the resource id is less than the wildcard
- if (builder.getResourceId() > UriFactory.WILDCARD_ENTITY_ID) {
- return UUri.getDefaultInstance();
+ try {
+ int versionMajor = Integer.parseUnsignedInt(pathSegments[2], 16);
+ UriValidator.validateVersionMajor(versionMajor);
+ builder.setUeVersionMajor(versionMajor);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("URI must contain 8 bit hex-encoded entity version", e);
}
+ // the fourth path segment can not be empty because the String.split() method excludes
+ // trailing empty strings from the resulting array
+ // it is therefore safe to simply parse it as an unsigned integer
+ try {
+ int resourceId = Integer.parseUnsignedInt(pathSegments[3], 16);
+ UriValidator.validateResourceId(resourceId);
+ builder.setResourceId(resourceId);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("URI must contain 16 bit hex-encoded resource ID", e);
+ }
return builder.build();
}
}
diff --git a/src/main/java/org/eclipse/uprotocol/uri/validator/UriValidator.java b/src/main/java/org/eclipse/uprotocol/uri/validator/UriValidator.java
index e62da205..4a117cde 100644
--- a/src/main/java/org/eclipse/uprotocol/uri/validator/UriValidator.java
+++ b/src/main/java/org/eclipse/uprotocol/uri/validator/UriValidator.java
@@ -12,230 +12,226 @@
*/
package org.eclipse.uprotocol.uri.validator;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Objects;
+import java.util.Optional;
+
import org.eclipse.uprotocol.uri.factory.UriFactory;
import org.eclipse.uprotocol.v1.UUri;
/**
- * class for validating Uris.
+ * A helper for validating uProtocol URIs.
*/
-public interface UriValidator {
+public final class UriValidator {
+
+ private UriValidator() {
+ // prevent instantiation
+ }
/**
* The minimum publish/notification topic id for a URI.
*/
- int MIN_TOPIC_ID = 0x8000;
+ public static final int MIN_TOPIC_ID = 0x8000;
/**
* The Default resource id.
*/
- int DEFAULT_RESOURCE_ID = 0;
+ public static final int DEFAULT_RESOURCE_ID = 0x0000;
/**
* Validates a UUri against the uProtocol specification.
*
* @param uuri The UUri to validate.
- * @throws NullPointerException if the UUri is null.
- * @throws IllegalArgumentException if the UUri does not comply with the UUri specification.
- */
- static void validate(UUri uuri) {
- if (uuri == null) {
- throw new NullPointerException("URI cannot be null");
- }
-
- if (uuri.getAuthorityName().length() > 128) {
- throw new IllegalArgumentException("Authority name exceeds maximum length of 128 characters");
- }
+ * @throws NullPointerException if uuri is {@code null}.
+ * @throws IllegalArgumentException if uuri does not comply with the UUri specification.
+ */
+ public static void validate(UUri uuri) {
+ Objects.requireNonNull(uuri, "URI must not be null");
+
+ Optional.ofNullable(uuri.getAuthorityName())
+ .filter(s -> !s.isEmpty())
+ .ifPresent(name -> {
+ try {
+ var uri = new URI(null, name, null, null, null);
+ validateParsedAuthority(uri);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Invalid authority name", e);
+ }
+ });
// no need to check uEntity ID which is of Java primitive type (signed) int but actually represents
// an unsigned 32 bit integer, thus any value is valid
- if ((uuri.getUeVersionMajor() & 0xFFFF_FF00) != 0) {
- throw new IllegalArgumentException("uEntity version major must be in range [0, 0x%X]"
+ validateVersionMajor(uuri.getUeVersionMajor());
+ validateResourceId(uuri.getResourceId());
+ }
+
+ public static void validateVersionMajor(int versionMajor) {
+ if ((versionMajor & 0xFFFF_FF00) != 0) {
+ throw new IllegalArgumentException("uEntity version major must be in range [0x00, 0x%X]"
.formatted(UriFactory.WILDCARD_ENTITY_VERSION));
}
+ }
- if ((uuri.getResourceId() & 0xFFFF_0000) != 0) {
- throw new IllegalArgumentException("uEntity resource ID must be in range [0, 0x%X]"
+ public static void validateResourceId(int resourceId) {
+ if ((resourceId & 0xFFFF_0000) != 0) {
+ throw new IllegalArgumentException("uEntity resource ID must be in range [0x0000, 0x%X]"
.formatted(UriFactory.WILDCARD_RESOURCE_ID));
}
}
- /**
- * Indicates that this URI is an empty as it does not contain authority, entity,
- * and resource.
- *
- * @param uri {@link UUri} to check if it is empty
- * @return Returns true if this URI is an empty container and has no valuable
- * information in building uProtocol sinks or sources.
- */
- static boolean isEmpty(UUri uri) {
- return uri == null || uri.equals(UUri.getDefaultInstance());
+ public static void validateParsedAuthority(URI uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+
+ if (uri.getPort() != -1) {
+ throw new IllegalArgumentException("uProtocol URI must not contain port");
+ }
+ if (uri.getUserInfo() != null) {
+ throw new IllegalArgumentException("uProtocol URI must not contain user info");
+ }
+ Optional.ofNullable(uri.getAuthority()).ifPresent(authority -> {
+ if (authority.length() > 128) {
+ throw new IllegalArgumentException("Authority name exceeds maximum length of 128 characters");
+ }
+ });
+ // TODO: make sure that authority name only consists of allowed characters
}
/**
- * Returns true if URI is of type RPC. A UUri is of type RPC if its
- * resource ID is less than MIN_TOPIC_ID and greater than RESOURCE_ID_RESPONSE.
+ * Checks if a uProtocol URI represents an RPC method address.
*
- * @param uri {@link UUri} to check if it is of type RPC method
- * @return Returns true if URI is of type RPC.
- */
- static boolean isRpcMethod(UUri uri) {
- return !isEmpty(uri) &&
- uri.getResourceId() > DEFAULT_RESOURCE_ID &&
+ * @param uri The URI to check.
+ * @return {@code true} if the URI's resource ID is > {@value #DEFAULT_RESOURCE_ID}
+ * and < {@value #MIN_TOPIC_ID}.
+ * @throws NullPointerException if uri is {@code null}.
+ */
+ public static boolean isRpcMethod(UUri uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+ return uri.getResourceId() > DEFAULT_RESOURCE_ID &&
uri.getResourceId() < MIN_TOPIC_ID;
}
/**
- * Returns true if URI is of type RPC response.
+ * Checks if a uProtocol URI represents an RPC response address.
*
- * @param uri {@link UUri} to check response
- * @return Returns true if URI is of type RPC response.
+ * @param uri The URI to check.
+ * @return {@code true} if the URI's resource ID is {@value #DEFAULT_RESOURCE_ID}.
+ * @throws NullPointerException if uri is {@code null}.
*/
- static boolean isRpcResponse(UUri uri) {
- return isDefaultResourceId(uri);
+ public static boolean isRpcResponse(UUri uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+ return isNotificationDestination(uri);
}
/**
- * Returns true if URI has the resource id of 0.
+ * Checks if a uProtocol URI represents a destination for a notification.
*
- * @param uri {@link UUri} to check request
- * @return Returns true if URI has a resource id of 0.
+ * @param uri The URI to check.
+ * @return {@code true} if the URI's resource ID is {@value #DEFAULT_RESOURCE_ID}.
+ * @throws NullPointerException if uri is {@code null}.
*/
- static boolean isDefaultResourceId(UUri uri) {
- return !isEmpty(uri) && uri.getResourceId() == DEFAULT_RESOURCE_ID;
+ public static boolean isNotificationDestination(UUri uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+ return uri.getResourceId() == DEFAULT_RESOURCE_ID;
}
/**
- * Returns true if URI is of type Topic used for publish and notifications.
+ * Checks if a uProtocol URI can be used as the source of an event or notification.
*
- * @param uri {@link UUri} to check if it is of type Topic
- * @return Returns true if URI is of type Topic.
- */
- static boolean isTopic(UUri uri) {
- return !isEmpty(uri) && uri.getResourceId() >= MIN_TOPIC_ID;
+ * @param uri The URI to check.
+ * @return {@code true} if the URI's resource ID is >= {@value #MIN_TOPIC_ID}
+ * and < {@value UriFactory#WILDCARD_RESOURCE_ID}.
+ * @throws NullPointerException if uri is {@code null}.
+ */
+ public static boolean isTopic(UUri uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+ return uri.getResourceId() >= MIN_TOPIC_ID &&
+ uri.getResourceId() < UriFactory.WILDCARD_RESOURCE_ID;
}
- /**
- * Checks if the authority of the uriToMatch matches the candidateUri.
- * A match occurs if the authority name in uriToMatch is a wildcard
- * or if both URIs have the same authority name.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the authority names match, False otherwise.
- */
- static boolean matchesAuthority(UUri uriToMatch, UUri candidateUri) {
- return UriFactory.WILDCARD_AUTHORITY.equals(uriToMatch.getAuthorityName()) ||
- uriToMatch.getAuthorityName().equals(candidateUri.getAuthorityName());
+ static boolean matchesAuthority(UUri pattern, UUri candidateUri) {
+ return hasWildcardAuthority(pattern) ||
+ pattern.getAuthorityName().equals(candidateUri.getAuthorityName());
}
- /**
- * Checks if the entity ID of the uriToMatch matches the candidateUri.
- * A match occurs if the entity ID in uriToMatch is a wildcard (0xFFFF)
- * or if the masked entity IDs of both URIs are equal.
- * The entity ID masking is performed using a bitwise AND operation with
- * 0xFFFF. If the result of the bitwise AND operation between the
- * uriToMatch's entity ID and 0xFFFF is 0xFFFF, it indicates that the
- * uriToMatch's entity ID is a wildcard and can match any entity ID.
- * Otherwise, the function checks if the masked entity IDs of both URIs
- * are equal, meaning that the relevant parts of their entity IDs match.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the entity IDs match, False otherwise.
- */
- static boolean matchesEntityId(UUri uriToMatch, UUri candidateUri) {
- return (uriToMatch.getUeId() & UriFactory.WILDCARD_ENTITY_ID) == UriFactory.WILDCARD_ENTITY_ID ||
- (uriToMatch.getUeId() & UriFactory.WILDCARD_ENTITY_ID) ==
- (candidateUri.getUeId() & UriFactory.WILDCARD_ENTITY_ID);
+ static boolean matchesEntityTypeId(UUri pattern, UUri candidateUri) {
+ final var entityTypeIdToMatch = pattern.getUeId() & UriFactory.WILDCARD_ENTITY_TYPE_ID;
+ return entityTypeIdToMatch == UriFactory.WILDCARD_ENTITY_TYPE_ID ||
+ entityTypeIdToMatch == (candidateUri.getUeId() & UriFactory.WILDCARD_ENTITY_TYPE_ID);
}
- /**
- * Checks if the entity instance of the uriToMatch matches the candidateUri.
- * A match occurs if the upper 16 bits of the entity ID in uriToMatch are zero
- * or if the upper 16 bits of the entity IDs of both URIs are equal.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the entity instances match, False otherwise.
- */
- static boolean matchesEntityInstance(UUri uriToMatch, UUri candidateUri) {
- return (uriToMatch.getUeId() & 0xFFFF0000) == 0x00000000 ||
- (uriToMatch.getUeId() & 0xFFFF0000) == (candidateUri.getUeId() & 0xFFFF0000);
+ static boolean matchesEntityInstance(UUri pattern, UUri candidateUri) {
+ final var instanceIdToMatch = pattern.getUeId() & UriFactory.WILDCARD_ENTITY_INSTANCE_ID;
+ return instanceIdToMatch == UriFactory.WILDCARD_ENTITY_INSTANCE_ID ||
+ instanceIdToMatch == (candidateUri.getUeId() & UriFactory.WILDCARD_ENTITY_INSTANCE_ID);
}
- /**
- * Checks if the entity version of the uriToMatch matches the candidateUri.
- * A match occurs if the entity version in uriToMatch is a wildcard
- * or if both URIs have the same entity version.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the entity versions match, False otherwise.
- */
- static boolean matchesEntityVersion(UUri uriToMatch, UUri candidateUri) {
- return UriFactory.WILDCARD_ENTITY_VERSION == uriToMatch.getUeVersionMajor() ||
- uriToMatch.getUeVersionMajor() == candidateUri.getUeVersionMajor();
+ static boolean matchesEntityVersion(UUri pattern, UUri candidateUri) {
+ return hasWildcardEntityVersion(pattern) ||
+ pattern.getUeVersionMajor() == candidateUri.getUeVersionMajor();
}
- /**
- * Checks if the entity of the uriToMatch matches the candidateUri.
- * A match occurs if the entity ID, entity instance, and entity version
- * of both URIs match according to their respective rules.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the entities match, False otherwise.
- */
- static boolean matchesEntity(UUri uriToMatch, UUri candidateUri) {
- return matchesEntityId(uriToMatch, candidateUri) &&
- matchesEntityInstance(uriToMatch, candidateUri) &&
- matchesEntityVersion(uriToMatch, candidateUri);
+ static boolean matchesEntity(UUri pattern, UUri candidateUri) {
+ return matchesEntityTypeId(pattern, candidateUri) &&
+ matchesEntityInstance(pattern, candidateUri) &&
+ matchesEntityVersion(pattern, candidateUri);
}
- /**
- * Checks if the resource of the uriToMatch matches the candidateUri.
- * A match occurs if the resource ID in uriToMatch is a wildcard
- * or if both URIs have the same resource ID.
- *
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the resource IDs match, False otherwise.
- */
- static boolean matchesResource(UUri uriToMatch, UUri candidateUri) {
- return UriFactory.WILDCARD_RESOURCE_ID == uriToMatch.getResourceId() ||
- uriToMatch.getResourceId() == candidateUri.getResourceId();
+ static boolean matchesResource(UUri pattern, UUri candidateUri) {
+ return hasWildcardResourceId(pattern) ||
+ pattern.getResourceId() == candidateUri.getResourceId();
}
/**
- * Checks if the entire URI (authority, entity, and resource) of the uriToMatch
- * matches the candidateUri. A match occurs if the authority, entity, and resource
- * of both URIs match according to their respective rules.
+ * Checks if a given candidate URI matches a pattern.
*
- * @param uriToMatch The URI to match.
- * @param candidateUri The candidate URI to match against.
- * @return True if the entire URIs match, False otherwise.
- */
- static boolean matches(UUri uriToMatch, UUri candidateUri) {
- return matchesAuthority(uriToMatch, candidateUri) &&
- matchesEntity(uriToMatch, candidateUri) &&
- matchesResource(uriToMatch, candidateUri);
+ * @param pattern The pattern to match.
+ * @param candidateUri The candidate URI to match against the pattern.
+ * @return {@code true} if the candidate matches the pattern.
+ * @throws NullPointerException if any of the arguments are {@code null}.
+ */
+ public static boolean matches(UUri pattern, UUri candidateUri) {
+ Objects.requireNonNull(pattern, "Pattern must not be null");
+ Objects.requireNonNull(candidateUri, "Candidate URI must not be null");
+ return matchesAuthority(pattern, candidateUri) &&
+ matchesEntity(pattern, candidateUri) &&
+ matchesResource(pattern, candidateUri);
}
+ static boolean hasWildcardAuthority(UUri uri) {
+ return UriFactory.WILDCARD_AUTHORITY.equals(uri.getAuthorityName());
+ }
+
+ static boolean hasWildcardEntityTypeId(UUri uri) {
+ return (uri.getUeId() & UriFactory.WILDCARD_ENTITY_TYPE_ID) == UriFactory.WILDCARD_ENTITY_TYPE_ID;
+ }
+
+ static boolean hasWildcardEntityInstanceId(UUri uri) {
+ return (uri.getUeId() & UriFactory.WILDCARD_ENTITY_INSTANCE_ID) == UriFactory.WILDCARD_ENTITY_INSTANCE_ID;
+ }
+
+ static boolean hasWildcardEntityVersion(UUri uri) {
+ return uri.getUeVersionMajor() == UriFactory.WILDCARD_ENTITY_VERSION;
+ }
+
+ static boolean hasWildcardResourceId(UUri uri) {
+ return uri.getResourceId() == UriFactory.WILDCARD_RESOURCE_ID;
+ }
/**
- * Checks if the URI has a wildcard in any of its fields.
+ * Checks if a uProtocol URI contains any wildcard values.
*
- * @param uri The URI to check for wildcards.
- * @return True if the URI has a wildcard, False otherwise.
- */
- static boolean hasWildcard(UUri uri) {
- return !isEmpty(uri) &&
- (uri.getAuthorityName().equals(UriFactory.WILDCARD_AUTHORITY) ||
- (uri.getUeId() & UriFactory.WILDCARD_ENTITY_ID) == UriFactory.WILDCARD_ENTITY_ID ||
- uri.getUeVersionMajor() == UriFactory.WILDCARD_ENTITY_VERSION ||
- uri.getResourceId() == UriFactory.WILDCARD_RESOURCE_ID);
+ * @param uri The URI to check.
+ * @return {@code true} if at least one of the URI's fields contains a wildcard value.
+ * @throws NullPointerException if uri is {@code null}.
+ */
+ public static boolean hasWildcard(UUri uri) {
+ Objects.requireNonNull(uri, "URI must not be null");
+ return hasWildcardAuthority(uri) ||
+ hasWildcardEntityTypeId(uri) ||
+ hasWildcardEntityInstanceId(uri) ||
+ hasWildcardEntityVersion(uri) ||
+ hasWildcardResourceId(uri);
}
}
-
-
diff --git a/src/test/java/org/eclipse/uprotocol/uri/UUriExamples.java b/src/test/java/org/eclipse/uprotocol/uri/UUriExamples.java
deleted file mode 100644
index f1430f47..00000000
--- a/src/test/java/org/eclipse/uprotocol/uri/UUriExamples.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.eclipse.uprotocol.uri;
-
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.eclipse.uprotocol.core.usubscription.v3.USubscriptionProto;
-import org.eclipse.uprotocol.uri.factory.UriFactory;
-import org.eclipse.uprotocol.uri.serializer.UriSerializer;
-import org.eclipse.uprotocol.uri.validator.UriValidator;
-import org.eclipse.uprotocol.v1.UUri;
-import org.junit.jupiter.api.Test;
-
-public class UUriExamples {
-
- @Test
- public void exampleUrifactoryFromproto() {
- // Fetch the notification topic Uri from the USubscriptionProto generated code
- final UUri uri = UriFactory.fromProto(
- USubscriptionProto.getDescriptor().getServices().get(0), 0);
-
- assertEquals(uri.getUeId(), 0);
- assertEquals(uri.getUeVersionMajor(), 3);
- assertEquals(uri.getResourceId(), 0);
- }
-
- @Test
- public void exampleSerializerDeserializer() {
- final UUri uri = UUri.newBuilder()
- .setUeId(1).setUeVersionMajor(2).setResourceId(3).build();
- final String strUri = UriSerializer.serialize(uri);
- assertEquals("/1/2/3", strUri);
- assertEquals(uri, UriSerializer.deserialize(strUri));
- }
-
- @Test
- public void exampleUrivalidator() {
- final UUri uri = UUri.newBuilder()
- .setUeId(1).setUeVersionMajor(2).setResourceId(3).build();
- assertFalse(UriValidator.isEmpty(uri));
- assertFalse(UriValidator.isDefaultResourceId(uri));
- assertTrue(UriValidator.isRpcMethod(uri));
- assertFalse(UriValidator.isRpcResponse(uri));
- assertFalse(UriValidator.isTopic(uri));
- }
-}
diff --git a/src/test/java/org/eclipse/uprotocol/uri/factory/UriFactoryTest.java b/src/test/java/org/eclipse/uprotocol/uri/factory/UriFactoryTest.java
index 6f409a8d..45259a7a 100644
--- a/src/test/java/org/eclipse/uprotocol/uri/factory/UriFactoryTest.java
+++ b/src/test/java/org/eclipse/uprotocol/uri/factory/UriFactoryTest.java
@@ -1,70 +1,106 @@
package org.eclipse.uprotocol.uri.factory;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.stream.Stream;
+import org.eclipse.uprotocol.Uoptions;
import org.eclipse.uprotocol.core.usubscription.v3.USubscriptionProto;
import org.eclipse.uprotocol.v1.UUri;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
-public class UriFactoryTest {
-
- @Test
- @DisplayName("Test fromProto")
- public void testFromProto() {
- final UUri uri = UriFactory.fromProto(
- USubscriptionProto.getDescriptor().getServices().get(0), 0);
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto;
+import com.google.protobuf.DescriptorProtos.ServiceOptions;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.ServiceDescriptor;
- assertEquals(uri.getAuthorityName(), "");
- assertEquals(uri.getUeId(), 0);
- assertEquals(uri.getUeVersionMajor(), 3);
- assertEquals(uri.getResourceId(), 0);
- }
+class UriFactoryTest {
@Test
@DisplayName("Test ANY")
- public void testAny() {
+ void testAny() {
final UUri uri = UriFactory.ANY;
- assertEquals(uri.getAuthorityName(), "*");
- assertEquals(uri.getUeId(), 65535);
- assertEquals(uri.getUeVersionMajor(), 255);
- assertEquals(uri.getResourceId(), 65535);
+ assertEquals("*", uri.getAuthorityName());
+ assertEquals(0xFFFF_FFFF, uri.getUeId());
+ assertEquals(0xFF, uri.getUeVersionMajor());
+ assertEquals(0xFFFF, uri.getResourceId());
}
- @Test
- @DisplayName("Test fromProto with null descriptor")
- public void testFromProtoWithNullDescriptor() {
- final UUri uri = UriFactory.fromProto(null, 0);
-
- assertEquals(uri.getAuthorityName(), "");
- assertEquals(uri.getUeId(), 0);
- assertEquals(uri.getUeVersionMajor(), 0);
- assertEquals(uri.getResourceId(), 0);
- }
+ static ServiceDescriptor createServiceDescriptor(OptionalInt serviceId, OptionalInt majorVersion) {
+ var optionsBuilder = ServiceOptions.newBuilder();
+ serviceId.ifPresent(id -> optionsBuilder.setExtension(Uoptions.serviceId, id));
+ majorVersion.ifPresent(version -> optionsBuilder.setExtension(Uoptions.serviceVersionMajor, version));
+ ServiceDescriptorProto serviceProto = ServiceDescriptorProto.newBuilder()
+ .setName("TestService")
+ .setOptions(optionsBuilder)
+ .build();
- @Test
- @DisplayName("Test fromProto with authority name")
- public void testFromProtoWithAuthorityName() {
- final UUri uri = UriFactory.fromProto(
- USubscriptionProto.getDescriptor().getServices().get(0), 0, "hartley");
+ FileDescriptorProto fileProto = FileDescriptorProto.newBuilder()
+ .setName("test.proto")
+ .setPackage("test")
+ .addService(serviceProto)
+ .build();
- assertEquals(uri.getAuthorityName(), "hartley");
- assertEquals(uri.getUeId(), 0);
- assertEquals(uri.getUeVersionMajor(), 3);
- assertEquals(uri.getResourceId(), 0);
+ try {
+ var fileDescriptor = FileDescriptor.buildFrom(fileProto, new FileDescriptor[0]);
+ return fileDescriptor.getServices().get(0);
+ } catch (DescriptorValidationException e) {
+ throw new IllegalArgumentException("cannot create ServiceDescriptor for arguments", e);
+ }
}
- @Test
- @DisplayName("Test fromProto with empty authority name string")
- public void testFromProtoWithEmptyAuthorityName() {
- final UUri uri = UriFactory.fromProto(
- USubscriptionProto.getDescriptor().getServices().get(0), 0, "");
+ static Stream fromProtoProvider() {
+ var uSubscriptionDesc = USubscriptionProto.getDescriptor().getServices().get(0);
+ return Stream.of(
+ Arguments.of(uSubscriptionDesc, 0, "*", null),
+ Arguments.of(uSubscriptionDesc, 1, "hartley", null),
+ Arguments.of(uSubscriptionDesc, 2, null, null),
+ Arguments.of(uSubscriptionDesc, -1, null, IllegalArgumentException.class),
+ Arguments.of(
+ createServiceDescriptor(OptionalInt.empty(), OptionalInt.empty()),
+ 1,
+ "localhost",
+ IllegalArgumentException.class),
+ Arguments.of(
+ createServiceDescriptor(OptionalInt.of(0x0010_a1bf), OptionalInt.empty()),
+ 1,
+ "localhost",
+ IllegalArgumentException.class),
+ Arguments.of(
+ createServiceDescriptor(OptionalInt.empty(), OptionalInt.of(0x02)),
+ 1,
+ "localhost",
+ IllegalArgumentException.class)
+ );
+ }
- assertEquals(uri.getAuthorityName(), "");
- assertEquals(uri.getUeId(), 0);
- assertEquals(uri.getUeVersionMajor(), 3);
- assertEquals(uri.getResourceId(), 0);
+ @ParameterizedTest(name = "Test fromProto: {index} - {arguments}")
+ @MethodSource("fromProtoProvider")
+ public void testFromProtoWithParameters(
+ ServiceDescriptor descriptor,
+ int resourceId,
+ String authorityName,
+ Class expectedOutcome) {
+ if (expectedOutcome != null) {
+ assertThrows(
+ expectedOutcome,
+ () -> UriFactory.fromProto(descriptor, resourceId, authorityName));
+ } else {
+ final UUri uri = UriFactory.fromProto(descriptor, resourceId, authorityName);
+ assertEquals(Optional.ofNullable(authorityName).orElse(""), uri.getAuthorityName());
+ assertEquals(0, uri.getUeId());
+ assertEquals(3, uri.getUeVersionMajor());
+ assertEquals(resourceId, uri.getResourceId());
+ }
}
}
diff --git a/src/test/java/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.java b/src/test/java/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.java
index 6cdd166e..efbb5ba3 100644
--- a/src/test/java/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.java
+++ b/src/test/java/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.java
@@ -12,321 +12,145 @@
*/
package org.eclipse.uprotocol.uri.serializer;
-import org.eclipse.uprotocol.uri.validator.UriValidator;
import org.eclipse.uprotocol.v1.UUri;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
-
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*;
-
-public class UriSerializerTest {
-
-
- @Test
- @DisplayName("Test using the serializers")
- public void testUsingTheSerializers() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(1)
- .setUeVersionMajor(2)
- .setResourceId(3)
- .build();
-
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/1/2/3", serializedUri);
- }
-
- @Test
- @DisplayName("Test deserializing a null UUri")
- public void testDeserializingANullUuri() {
- UUri uri = UriSerializer.deserialize(null);
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing an empty UUri")
- public void testDeserializingAnEmptyUuri() {
- UUri uri = UriSerializer.deserialize("");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
-
- @Test
- @DisplayName("Test deserializing a blank UUri")
- public void testDeserializingABlankUuri() {
- UUri uri = UriSerializer.deserialize(" ");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing with a valid URI that has scheme")
- public void testDeserializingWithAValidUriThatHasScheme() {
- UUri uri = UriSerializer.deserialize("up://myAuthority/1/2/3");
- assertEquals("myAuthority", uri.getAuthorityName());
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(3, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing with a valid URI that has scheme but nothing else")
- public void testDeserializingWithAValidUriThatHasSchemeButNothingElse() {
- UUri uri = UriSerializer.deserialize("up://");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a valid UUri with all fields")
- public void testDeserializingAValidUuriWithAllFields() {
- UUri uri = UriSerializer.deserialize("//myAuthority/1/2/3");
- assertEquals("myAuthority", uri.getAuthorityName());
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(3, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing a valid UUri with only authority")
- public void testDeserializingAValidUuriWithOnlyAuthority() {
- UUri uri = UriSerializer.deserialize("//myAuthority");
- assertEquals("myAuthority", uri.getAuthorityName());
- assertEquals(0, uri.getUeId());
- assertEquals(0, uri.getUeVersionMajor());
- assertEquals(0, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing a valid UUri with only authority and ueId")
- public void testDeserializingAValidUuriWithOnlyAuthorityAndUeid() {
- UUri uri = UriSerializer.deserialize("//myAuthority/1");
- assertEquals("myAuthority", uri.getAuthorityName());
- assertEquals(1, uri.getUeId());
- assertEquals(0, uri.getUeVersionMajor());
- assertEquals(0, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing a valid UUri with only authority, ueId and ueVersionMajor")
- public void testDeserializingAValidUuriWithOnlyAuthorityUeidAndUeversionmajor() {
- UUri uri = UriSerializer.deserialize("//myAuthority/1/2");
- assertEquals("myAuthority", uri.getAuthorityName());
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(0, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing a string with invalid characters at the beginning")
- public void testDeserializingAStringWithInvalidCharacters() {
- UUri uri = UriSerializer.deserialize("$$");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with names instead of ids for UeId")
- public void testDeserializingAStringWithNamesInsteadOfIdsForUeid() {
- UUri uri = UriSerializer.deserialize("//myAuthority/myUeId/2/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with names instead of ids for UeVersionMajor")
- public void testDeserializingAStringWithNamesInsteadOfIdsForUeversionmajor() {
- UUri uri = UriSerializer.deserialize("//myAuthority/1/myUeVersionMajor/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with names instead of ids for ResourceId")
- public void testDeserializingAStringWithNamesInsteadOfIdsForResourceid() {
- UUri uri = UriSerializer.deserialize("//myAuthority/1/2/myResourceId");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string without authority")
- public void testDeserializingAStringWithoutAuthority() {
- UUri uri = UriSerializer.deserialize("/1/2/3");
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(3, uri.getResourceId());
- assertTrue(uri.getAuthorityName().isBlank());
- }
-
- @Test
- @DisplayName("Test deserializing a string without authority and ResourceId")
- public void testDeserializingAStringWithoutAuthorityAndResourceid() {
- UUri uri = UriSerializer.deserialize("/1/2");
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(0, uri.getResourceId());
- assertTrue(uri.getAuthorityName().isBlank());
- }
-
- @Test
- @DisplayName("Test deserializing a string without authority, ResourceId and UeVersionMajor")
- public void testDeserializingAStringWithoutAuthorityResourceidAndUeversionmajor() {
- UUri uri = UriSerializer.deserialize("/1");
- assertEquals(1, uri.getUeId());
- assertEquals(0, uri.getUeVersionMajor());
- assertEquals(0, uri.getResourceId());
- assertTrue(uri.getAuthorityName().isBlank());
- }
-
- @Test
- @DisplayName("Test deserializing a string with blank authority")
- public void testDeserializingAStringWithBlankAuthority() {
- UUri uri = UriSerializer.deserialize("///2");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with all the items are the wildcard values")
- public void testDeserializingAStringWithAllTheItemsAreTheWildcardValues() {
- UUri uri = UriSerializer.deserialize("//*/FFFF/ff/ffff");
- assertEquals("*", uri.getAuthorityName());
- assertEquals(0xFFFF, uri.getUeId());
- assertEquals(0xFF, uri.getUeVersionMajor());
- assertEquals(0xFFFF, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test deserializing a string with uEId() out of range")
- public void testDeserializingAStringWithUeidOutOfRange() {
- UUri uri = UriSerializer.deserialize("/fffffffff/2/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with uEVersionMajor out of range")
- public void testDeserializingAStringWithUeversionmajorOutOfRange() {
- UUri uri = UriSerializer.deserialize("/1/256/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with resourceId out of range")
- public void testDeserializingAStringWithResourceidOutOfRange() {
- UUri uri = UriSerializer.deserialize("/1/2/65536");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with negative uEId")
- public void testDeserializingAStringWithNegativeUeid() {
- UUri uri = UriSerializer.deserialize("/-1/2/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with negative uEVersionMajor")
- public void testDeserializingAStringWithNegativeUeversionmajor() {
- UUri uri = UriSerializer.deserialize("/1/-2/3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with negative resourceId")
- public void testDeserializingAStringWithNegativeResourceid() {
- UUri uri = UriSerializer.deserialize("/1/2/-3");
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test deserializing a string with wildcard ResourceId")
- public void testDeserializingAStringWithWildcardResourceid() {
- UUri uri = UriSerializer.deserialize("/1/2/ffff");
- assertEquals(1, uri.getUeId());
- assertEquals(2, uri.getUeVersionMajor());
- assertEquals(0xFFFF, uri.getResourceId());
- }
-
- @Test
- @DisplayName("Test serializing an Empty UUri")
- public void testSerializingAnEmptyUuri() {
- UUri uri = UUri.getDefaultInstance();
- String serializedUri = UriSerializer.serialize(uri);
- assertTrue(serializedUri.isBlank());
- }
-
- @Test
- @DisplayName("Test serializing a null UUri")
- public void testSerializingANullUuri() {
- String serializedUri = UriSerializer.serialize(null);
- assertTrue(serializedUri.isBlank());
- }
-
- @Test
- @DisplayName("Test serializing a full UUri")
- public void testSerializingAFullUuri() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(1)
- .setUeVersionMajor(2)
- .setResourceId(3)
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/1/2/3", serializedUri);
- }
-
- @Test
- @DisplayName("Test serializing a UUri with only authority")
- public void testSerializingAUuriWithOnlyAuthority() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/0/0/0", serializedUri);
- }
-
- @Test
- @DisplayName("Test serializing a UUri with only authority and ueId")
- public void testSerializingAUuriWithOnlyAuthorityAndUeid() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(1)
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/1/0/0", serializedUri);
- }
-
- @Test
- @DisplayName("Test serializing a UUri with only authority, ueId and ueVersionMajor")
- public void testSerializingAUuriWithOnlyAuthorityUeidAndUeversionmajor() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(1)
- .setUeVersionMajor(2)
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/1/2/0", serializedUri);
- }
-
- @Test
- @DisplayName("Test serializing a UUri with only authority, ueId, ueVersionMajor and resourceId")
- public void testSerializingAUuriWithOnlyAuthorityUeidUeversionmajorAndResourceid() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(1)
- .setUeVersionMajor(2)
- .setResourceId(3)
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("//myAuthority/1/2/3", serializedUri);
- }
-
- @Test
- @DisplayName("Test serializing a UUri that has a blank authority")
- public void testSerializingAUuriThatHasABlankAuthority() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("")
- .setUeId(1)
- .setUeVersionMajor(2)
- .setResourceId(3)
- .build();
- String serializedUri = UriSerializer.serialize(uri);
- assertEquals("/1/2/3", serializedUri);
+import java.net.URI;
+import java.util.Optional;
+
+
+class UriSerializerTest {
+
+ @ParameterizedTest(name = "Test serializing a valid UUri succeeds [{index}] {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ authority, ueId, ueVersion, resourceId, expectedUri
+ , , , , /0/0/0
+ myAuthority, , , , //myAuthority/0/0/0
+ myAuthority, 0x0000_abcd, , , //myAuthority/ABCD/0/0
+ myAuthority, 0x0000_abcd, 0x02, , //myAuthority/ABCD/2/0
+ myAuthority, 0x001f_abcd, 0x02, 0x3d4b, //myAuthority/1FABCD/2/3D4B
+ *, 0xb1a, 0x01, 0x8aa1, //*/B1A/1/8AA1
+ myAuthority, 0x0000_ffff, 0x01, 0x8aa1, //myAuthority/FFFF/1/8AA1
+ # using -62694 to represent 0xffff_0b1a which fails to be parsed by CsvSource
+ # because CsvSource does not support parsing hex strings as unsigned integers
+ myAuthority, -62694, 0x01, 0x8aa1, //myAuthority/FFFF0B1A/1/8AA1
+ myAuthority, 0xb1a, 0xff, 0x8aa1, //myAuthority/B1A/FF/8AA1
+ myAuthority, 0xb1a, 0x01, 0xffff, //myAuthority/B1A/1/FFFF
+ # using -1 (2s complement) to represent 0xffff_ffff which fails to be parsed by CsvSource
+ # because CsvSource does not support parsing hex strings as unsigned integers
+ *, -1, 0xff, 0xffff, //*/FFFFFFFF/FF/FFFF
+ """)
+ void testSerializingValidUUriSucceeds(
+ String authority,
+ Integer ueId,
+ Integer ueVersion,
+ Integer resourceId,
+ String expectedUri) {
+ final var builder = UUri.newBuilder();
+ Optional.ofNullable(authority).ifPresent(builder::setAuthorityName);
+ Optional.ofNullable(ueId).ifPresent(builder::setUeId);
+ Optional.ofNullable(ueVersion).ifPresent(builder::setUeVersionMajor);
+ Optional.ofNullable(resourceId).ifPresent(builder::setResourceId);
+ UUri originalUuri = builder.build();
+
+ String correspondingUri = UriSerializer.serialize(originalUuri);
+ assertEquals(expectedUri, correspondingUri);
+ assertEquals(originalUuri, UriSerializer.deserialize(correspondingUri));
+ }
+
+ @Test
+ @DisplayName("Test serializing a null UUri fails")
+ void testSerializingANullUuri() {
+ assertThrows(NullPointerException.class, () -> {
+ UriSerializer.serialize(null);
+ });
+ }
+
+ //
+ // tests for deserializing URIs
+ //
+
+ @ParameterizedTest(name = "Test deserializing a valid Uri succeeds [{index}] {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ URI, expectedAuthority, expectedUeId, expectedVersion, expectedResourceId
+ /0/0/0, , 0x0000_0000, 0x00, 0x0000
+ up:/0/0/0, , 0x0000_0000, 0x00, 0x0000
+ //auth.dev/0/0/0, auth.dev, 0x0000_0000, 0x00, 0x0000
+ //192.168.1.0/ABCD/0/0, 192.168.1.0, 0x0000_abcd, 0x00, 0x0000
+ //auth/ABCD/2/0, auth, 0x0000_abcd, 0x02, 0x0000
+ up://auth/ABCD/2/3D4B, auth, 0x0000_abcd, 0x02, 0x3d4b
+ /1234/1/5678, , 0x0000_1234, 0x01, 0x5678
+ //*/1234/1/5678, *, 0x0000_1234, 0x01, 0x5678
+ //auth/FFFF/1/5678, auth, 0x0000_ffff, 0x01, 0x5678
+ # using -62694 to represent 0xffff_0b1a which fails to be parsed by CsvSource
+ # because CsvSource does not support parsing hex strings as unsigned integers
+ //auth/FFFF0B1A/1/5678, auth, -62694, 0x01, 0x5678
+ //auth/1234/FF/5678, auth, 0x0000_1234, 0xff, 0x5678
+ //auth/1234/1/FFFF, auth, 0x0000_1234, 0x01, 0xffff
+ # using -1 to represent 0xffff_ffff which fails to be parsed by CsvSource
+ # because CsvSource does not support parsing hex strings as unsigned integers
+ //*/FFFFFFFF/FF/FFFF, *, -1, 0xff, 0xffff
+ """)
+ void testDeserializeValidUriSucceeds(
+ String uri,
+ String expectedAuthority,
+ Integer expectedUeId,
+ Integer expectedVersion,
+ Integer expectedResourceId) {
+
+ final var uuri = UriSerializer.deserialize(uri);
+ Optional.ofNullable(expectedAuthority).ifPresent(s -> assertEquals(s, uuri.getAuthorityName()));
+ Optional.ofNullable(expectedUeId).ifPresent(s -> assertEquals(s, uuri.getUeId()));
+ Optional.ofNullable(expectedVersion).ifPresent(s -> assertEquals(s, uuri.getUeVersionMajor()));
+ Optional.ofNullable(expectedResourceId).ifPresent(s -> assertEquals(s, uuri.getResourceId()));
+ }
+
+ @Test
+ @DisplayName("Test deserializing a null UUri fails")
+ public void testDeserializingANullUuriFails() {
+ assertThrows(NullPointerException.class, () -> {
+ UriSerializer.deserialize((String) null);
+ });
+ assertThrows(NullPointerException.class, () -> {
+ UriSerializer.deserialize((URI) null);
+ });
+ }
+
+ @ParameterizedTest(name = "Test deserializing an invalid URI fails [{index}] {arguments}")
+ @ValueSource(strings = {
+ " ",
+ "$$",
+ "up://",
+ "up://just_an_authority",
+ "/ABC",
+ "/ABC/1",
+ "//myhost/ABC",
+ "//myhost/ABC/1",
+ "//myhost//1/A000",
+ "//myhost/ABC//A000",
+ "//myhost/ABC/1//",
+ "//myhost/not-hex/1/2341",
+ "//myhost/1/not-hex/2341",
+ "//myhost/1/1/not-hex",
+ "//myhost/-1/1/2341",
+ "invalidscheme://myhost/A000/1/2341",
+ "up://myhost/A000/1/2341#invalid",
+ "up://myhost/A000/1/2341?param=invalid",
+ "up://myhost/100000000/1/2341",
+ "//myhost/A1B/-1/2341",
+ "//myhost/A1B/100/2341",
+ "up://myhost/A1B/1/-1",
+ "//myhost/A1B/1/10000"
+ })
+ void testDeserializeInvalidUriFails(String uri) {
+ assertThrows(IllegalArgumentException.class, () -> {
+ UriSerializer.deserialize(uri);
+ });
}
}
diff --git a/src/test/java/org/eclipse/uprotocol/uri/validator/UriValidatorTest.java b/src/test/java/org/eclipse/uprotocol/uri/validator/UriValidatorTest.java
index 23bff87a..100e315e 100644
--- a/src/test/java/org/eclipse/uprotocol/uri/validator/UriValidatorTest.java
+++ b/src/test/java/org/eclipse/uprotocol/uri/validator/UriValidatorTest.java
@@ -15,323 +15,184 @@
import org.eclipse.uprotocol.uri.serializer.UriSerializer;
import org.eclipse.uprotocol.v1.UUri;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-class UriValidatorTest {
-
- @Test
- @DisplayName("Test isEmpty with null UUri")
- public void testIsemptyWithNullUuri() {
- assertTrue(UriValidator.isEmpty(null));
- }
-
- @Test
- @DisplayName("Test isEmpty with default UUri")
- public void testIsemptyWithDefaultUuri() {
- assertTrue(UriValidator.isEmpty(UUri.getDefaultInstance()));
- }
-
- @Test
- @DisplayName("Test isEmpty for non empty UUri")
- public void testIsemptyForNonEmptyUuri() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("myAuthority")
- .setUeId(0)
- .setUeVersionMajor(1)
- .setResourceId(1).build();
- assertTrue(!UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test isEmpty UUri for empty built UUri")
- public void testIsemptyUuriForEmptyBuiltUuri() {
- UUri uri = UUri.newBuilder().build();
- assertTrue(UriValidator.isEmpty(uri));
- }
-
- @Test
- @DisplayName("Test isRpcMethod with null UUri")
- public void testIsrpcmethodWithNullUuri() {
- assertTrue(!UriValidator.isRpcMethod(null));
- }
-
- @Test
- @DisplayName("Test isRpcMethod with default UUri")
- public void testIsrpcmethodWithDefaultUuri() {
- assertFalse(UriValidator.isRpcMethod(UUri.getDefaultInstance()));
- }
-
- @Test
- @DisplayName("Test isRpcMethod with UUri having resourceId less than MIN_TOPIC_ID")
- public void testIsrpcmethodWithUuriHavingResourceidLessThanMinTopicId() {
- UUri uri = UUri.newBuilder()
- .setResourceId(0x7FFF).build();
- assertTrue(UriValidator.isRpcMethod(uri));
- }
-
- @Test
- @DisplayName("Test isRpcMethod with UUri having resourceId greater than MIN_TOPIC_ID")
- public void testIsrpcmethodWithUuriHavingResourceidGreaterThanMinTopicId() {
- UUri uri = UUri.newBuilder()
- .setResourceId(0x8000).build();
- assertTrue(!UriValidator.isRpcMethod(uri));
- }
-
- @Test
- @DisplayName("Test isRpcMethod with UUri having resourceId equal to MIN_TOPIC_ID")
- public void testIsrpcmethodWithUuriHavingResourceidEqualToMinTopicId() {
- UUri uri = UUri.newBuilder()
- .setResourceId(0x8000).build();
- assertTrue(!UriValidator.isRpcMethod(uri));
- }
-
- @Test
- @DisplayName("Test isRpcResponse with null UUri")
- public void testIsrpcresponseWithNullUuri() {
- assertTrue(!UriValidator.isRpcResponse(null));
- }
+import java.util.Arrays;
- @Test
- @DisplayName("Test isRpcResponse with default UUri")
- public void testIsrpcresponseWithDefaultUuri() {
- assertTrue(!UriValidator.isRpcResponse(UUri.getDefaultInstance()));
- }
-
- @Test
- @DisplayName("Test isRpcResponse with UUri having resourceId equal to 0")
- public void testIsrpcresponseWithUuriHavingResourceidEqualTo0() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("hartley")
- .setUeId(1)
- .setUeVersionMajor(1)
- .setResourceId(0).build();
- assertTrue(UriValidator.isRpcResponse(uri));
- }
-
- @Test
- @DisplayName("Test isRpcResponse with UUri having resourceId not equal to 0")
- public void testIsrpcresponseWithUuriHavingResourceidNotEqualTo0() {
- UUri uri = UUri.newBuilder()
- .setAuthorityName("hartley")
- .setUeId(1)
- .setUeVersionMajor(1)
- .setResourceId(1).build();
- assertTrue(!UriValidator.isRpcResponse(uri));
- }
-
- @Test
- @DisplayName("Test isRpcResponse with UUri having resourceId less than 0")
- public void testIsrpcresponseWithUuriHavingResourceidLessThan0() {
- UUri uri = UUri.newBuilder()
- .setResourceId(-1).build();
- assertTrue(!UriValidator.isRpcResponse(uri));
- }
-
- @Test
- @DisplayName("Test isTopic with null UUri")
- public void testIstopicWithNullUuri() {
- assertFalse(UriValidator.isTopic(null));
- }
-
- @Test
- @DisplayName("Test isTopic with default UUri")
- public void testIstopicWithDefaultUuri() {
- assertFalse(UriValidator.isTopic(UUri.getDefaultInstance()));
- }
-
- @Test
- @DisplayName("Test isTopic with UUri having resourceId greater than 0")
- public void testIstopicWithUuriHavingResourceidGreaterThan0() {
- UUri uri = UUri.newBuilder()
- .setResourceId(1).build();
- assertFalse(UriValidator.isTopic(uri));
- }
-
- @Test
- @DisplayName("Test isTopic with UUri having resourceId greater than 0x8000")
- public void testIstopicWithUuriHavingResourceidGreaterThan0x8000() {
- UUri uri = UUri.newBuilder()
- .setResourceId(0x8001).build();
- assertTrue(UriValidator.isTopic(uri));
- }
-
- @Test
- @DisplayName("Test isRpcMethod should be false when resourceId is 0")
- public void testIsrpcmethodShouldBeFalseWhenResourceidIs0() {
- UUri uri = UUri.newBuilder()
- .setUeId(1)
- .setResourceId(0).build();
- assertFalse(UriValidator.isRpcMethod(uri));
- }
-
- @Test
- @DisplayName("Matches succeeds for identical URIs")
- public void testMatchesSucceedsForIdenticalUris() {
- UUri patternUri = UriSerializer.deserialize("//authority/A410/3/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with wildcard authority")
- public void testMatchesSucceedsForPatternWithWildcardAuthority() {
- UUri patternUri = UriSerializer.deserialize("//*/A410/3/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with wildcard authority and local candidate URI")
- public void testMatchesSucceedsForPatternWithWildcardAuthorityAndLocalCandidateUri() {
- UUri patternUri = UriSerializer.deserialize("//*/A410/3/1003");
- UUri candidateUri = UriSerializer.deserialize("/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with wildcard entity ID")
- public void testMatchesSucceedsForPatternWithWildcardEntityId() {
- UUri patternUri = UriSerializer.deserialize("//authority/FFFF/3/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with similar entity instance")
- public void testMatchesSucceedsForPatternWithSimilarEntityInstance() {
- UUri patternUri = UriSerializer.deserialize("//authority/A410/3/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/2A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with identical entity instance")
- public void testMatchesSucceedsForPatternWithIdenticalEntityInstance() {
- UUri patternUri = UriSerializer.deserialize("//authority/2A410/3/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/2A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with wildcard entity version")
- public void testMatchesSucceedsForPatternWithWildcardEntityVersion() {
- UUri patternUri = UriSerializer.deserialize("//authority/A410/FF/1003");
- UUri candidateUri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches succeeds for pattern with wildcard resource")
- public void testMatchesSucceedsForPatternWithWildcardResource() {
- UUri patternUri = UriSerializer.deserialize("//authority/A410/3/FFFF");
- UUri candidateUri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertTrue(UriValidator.matches(patternUri, candidateUri));
- }
-
- @Test
- @DisplayName("Matches fails for upper case authority")
- public void testMatchesFailForUpperCaseAuthority() {
- UUri pattern = UriSerializer.deserialize("//Authority/A410/3/1003");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for local pattern with authority")
- public void testMatchesFailForLocalPatternWithAuthority() {
- UUri pattern = UriSerializer.deserialize("/A410/3/1003");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for different authority")
- public void testMatchesFailForDifferentAuthority() {
- UUri pattern = UriSerializer.deserialize("//other/A410/3/1003");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for different entity ID")
- public void testMatchesFailForDifferentEntityId() {
- UUri pattern = UriSerializer.deserialize("//authority/45/3/1003");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for different entity instance")
- public void testMatchesFailForDifferentEntityInstance() {
- UUri pattern = UriSerializer.deserialize("//authority/30A410/3/1003");
- UUri candidate = UriSerializer.deserialize("//authority/2A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for different entity version")
- public void testMatchesFailForDifferentEntityVersion() {
- UUri pattern = UriSerializer.deserialize("//authority/A410/1/1003");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("Matches fails for different resource")
- public void testMatchesFailForDifferentResource() {
- UUri pattern = UriSerializer.deserialize("//authority/A410/3/ABCD");
- UUri candidate = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.matches(pattern, candidate));
- }
-
- @Test
- @DisplayName("hasWildcard() for an null UUri")
- void testHaswildcardForNullUuri() {
- assertFalse(UriValidator.hasWildcard(null));
- }
-
- @Test
- @DisplayName("hasWildcard() for a UUri with empty URI")
- void testHaswildcardForEmptyUuri() {
- assertFalse(UriValidator.hasWildcard(UUri.getDefaultInstance()));
- }
-
- @Test
- @DisplayName("hasWildcard() for a UUri with wildcard authority")
- void testHaswildcardForUuriWithWildcardAuthority() {
- UUri uri = UriSerializer.deserialize("//*/A410/3/1003");
- assertTrue(UriValidator.hasWildcard(uri));
- }
-
- @Test
- @DisplayName("hasWildcard() for a UUri with wildcard entity ID")
- void testHaswildcardForUuriWithWildcardEntityId() {
- UUri uri = UriSerializer.deserialize("//authority/FFFF/3/1003");
- assertTrue(UriValidator.hasWildcard(uri));
- }
-
- @Test
- @DisplayName("hasWildcard() for a UUri with wildcard entity version")
- void testHaswildcardForUuriWithWildcardEntityInstance() {
- UUri uri = UriSerializer.deserialize("//authority/A410/FF/1003");
- assertTrue(UriValidator.hasWildcard(uri));
- }
-
- @Test
- @DisplayName("hasWildcard() for a UUri with wildcard resource")
- void testHaswildcardForUuriWithWildcardResource() {
- UUri uri = UriSerializer.deserialize("//authority/A410/3/FFFF");
- assertTrue(UriValidator.hasWildcard(uri));
- }
+class UriValidatorTest {
- @Test
- @DisplayName("hasWildcard() for a UUri with no wildcards")
- void testHaswildcardForUuriWithNoWildcards() {
- UUri uri = UriSerializer.deserialize("//authority/A410/3/1003");
- assertFalse(UriValidator.hasWildcard(uri));
+ @ParameterizedTest(name = "Test validate URI: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ authorityName, ueId, version, resourceId, should succeed
+ *, -1, 0xFF, 0xFFFF, true
+ myhost, 0x0000_0A1B, 0x01, 0x2341, true
+ invalid<<[], 0x0000_0A1B, 0x01, 0x2341, false
+ myhost:5555, 0x0000_0A1B, 0x01, 0x2341, false
+ user:passwd@myhost, 0x0000_0A1B, 0x01, 0x2341, false
+ myhost, 0x0000_0A1B, -1, 0x2341, false
+ myhost, 0x0000_0A1B, 0x100, 0x2341, false
+ myhost, 0x0000_0A1B, 0x01, -1, false
+ myhost, 0x0000_0A1B, 0x01, 0x10000, false
+ """
+ )
+ void testValidate(
+ String authorityName,
+ int ueId,
+ int ueVersionMajor,
+ int resourceId,
+ boolean shouldSucceed) {
+ UUri uuri = UUri.newBuilder()
+ .setAuthorityName(authorityName)
+ .setUeId(ueId)
+ .setUeVersionMajor(ueVersionMajor)
+ .setResourceId(resourceId)
+ .build();
+ if (shouldSucceed) {
+ assertDoesNotThrow(() -> UriValidator.validate(uuri));
+ } else {
+ assertThrows(IllegalArgumentException.class, () -> {
+ UriValidator.validate(uuri);
+ });
+ }
+ }
+
+ @ParameterizedTest(name = "Test validate checks maximum length of authority name: {index} - {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ authorityNameLength, should succeed
+ 128, true
+ 129, false
+ """)
+ void testValidateFailsForAuthorityExceedingMaxLength(int authorityNameLength, boolean shouldSucceed) {
+ var authorityName = new char[authorityNameLength];
+ Arrays.fill(authorityName, 'A');
+ var uri = UUri.newBuilder()
+ .setAuthorityName(new String(authorityName))
+ .setUeId(0x1234)
+ .setUeVersionMajor(0x01)
+ .setResourceId(0x0001)
+ .build();
+ if (shouldSucceed) {
+ assertDoesNotThrow(() -> UriValidator.validate(uri));
+ } else {
+ assertThrows(IllegalArgumentException.class, () -> UriValidator.validate(uri));
+ }
+ }
+
+ @ParameterizedTest(name = "Test isRpcMethod: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ uri, should succeed
+ //myhost/A1B/1/0, false
+ //myhost/A1B/1/1, true
+ //myhost/A1B/1/2341, true
+ //myhost/A1B/1/7FFF, true
+ //myhost/A1B/1/8000, false
+ //myhost/A1B/1/FFFF, false
+ """
+ )
+ void testIsRpcMethod(String uri, boolean shouldSucceed) {
+ UUri uuri = UriSerializer.deserialize(uri);
+ if (shouldSucceed) {
+ assertTrue(UriValidator.isRpcMethod(uuri));
+ } else {
+ assertFalse(UriValidator.isRpcMethod(uuri));
+ }
+ }
+
+ @ParameterizedTest(name = "Test isRpcResponse: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ uri, should succeed
+ //myhost/A1B/1/0, true
+ //myhost/A1B/1/1, false
+ //myhost/A1B/1/7FFF, false
+ //myhost/A1B/1/8000, false
+ //myhost/A1B/1/FFFF, false
+ """
+ )
+ void testIsRpcResponse(String uri, boolean shouldSucceed) {
+ UUri uuri = UriSerializer.deserialize(uri);
+ if (shouldSucceed) {
+ assertTrue(UriValidator.isRpcResponse(uuri));
+ } else {
+ assertFalse(UriValidator.isRpcResponse(uuri));
+ }
+ }
+
+ @ParameterizedTest(name = "Test isTopic: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ uri, should succeed
+ //myhost/A1B/1/0, false
+ //myhost/A1B/1/1, false
+ //myhost/A1B/1/7FFF, false
+ //myhost/A1B/1/8000, true
+ //myhost/A1B/1/ABCD, true
+ //myhost/A1B/1/FFFE, true
+ //myhost/A1B/1/FFFF, false
+ """
+ )
+ void testIsTopic(String uri, boolean shouldSucceed) {
+ UUri uuri = UriSerializer.deserialize(uri);
+ if (shouldSucceed) {
+ assertTrue(UriValidator.isTopic(uuri));
+ } else {
+ assertFalse(UriValidator.isTopic(uuri));
+ }
+ }
+
+ @ParameterizedTest(name = "Test hasWildcard: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ uri, should succeed
+ //myhost/A1B/1/0, false
+ //*/A1B/1/1, true
+ //myhost/FFFF/1/2, true
+ //myhost/FFFF0000/1/2, true
+ //myhost/FFFFFFFF/1/1, true
+ //myhost/A1B/FF/8000, true
+ //myhost/A1B/1/FFFF, true
+ //*/FFFFFFFF/FF/FFFF, true
+ """
+ )
+ void testHasWildcard(String uri, boolean shouldSucceed) {
+ UUri uuri = UriSerializer.deserialize(uri);
+ if (shouldSucceed) {
+ assertTrue(UriValidator.hasWildcard(uuri));
+ } else {
+ assertFalse(UriValidator.hasWildcard(uuri));
+ }
+ }
+
+ @ParameterizedTest(name = "Test matches: {index} {arguments}")
+ @CsvSource(useHeadersInDisplayName = true, textBlock = """
+ pattern, candidate, should match
+ //authority/A410/3/1003, //authority/A410/3/1003, true
+ //authority/2A410/3/1003, //authority/2A410/3/1003, true
+ //*/A410/3/1003, //authority/A410/3/1003, true
+ //*/A410/3/1003, /A410/3/1003, true
+ //authority/FFFF/3/1003, //authority/A410/3/1003, true
+ //authority/FFFFA410/3/1003, //authority/2A410/3/1003, true
+ //authority/A410/FF/1003, //authority/A410/3/1003, true
+ //authority/A410/3/FFFF, //authority/A410/3/1003, true
+ //Authority/A410/3/1003, //authority/A410/3/1003, false
+ //other/A410/3/1003, //authority/A410/3/1003, false
+ /A410/3/1003, //authority/A410/3/1003, false
+ //authority/45/3/1003, //authority/A410/3/1003, false
+ //authority/2A410/3/1003, //authority/A410/3/1003, false
+ //authority/A410/1/1003, //authority/A410/3/1003, false
+ //authority/A410/3/ABCD, //authority/A410/3/1003, false
+ """
+ )
+ void testMatches(String pattern, String candidate, boolean shouldMatch) {
+ UUri patternUri = UriSerializer.deserialize(pattern);
+ UUri candidateUri = UriSerializer.deserialize(candidate);
+ if (shouldMatch) {
+ assertTrue(UriValidator.matches(patternUri, candidateUri));
+ } else {
+ assertFalse(UriValidator.matches(patternUri, candidateUri));
+ }
}
}