From 1453607450c38453372112639261fa694fc2bd52 Mon Sep 17 00:00:00 2001 From: Keyi Xing Date: Fri, 8 Mar 2024 21:31:14 -0500 Subject: [PATCH 1/4] Use Kotlin DSL for builder functions Replace UAttributesBuilder with Kotlin DSL type safe builder functions Replace UResourceBuilder with Kotlin DSL type safe builder functions Update UCloudEventAttributes to use Kotlin DSL type safe builder instead Replace CallOptionsBuilder with Kotlin DSL type safe builder instead --- .../datamodel/UCloudEventAttributes.kt | 90 +--- .../org/eclipse/uprotocol/rpc/CallOptions.kt | 106 ++--- .../transport/builder/UAttributesBuilder.kt | 214 --------- .../uprotocol/uri/factory/UResourceFactory.kt | 85 ---- .../uri/serializer/MicroUriSerializer.kt | 5 +- .../eclipse/uprotocol/v1/UAttributesKtExt.kt | 93 ++++ .../eclipse/uprotocol/v1/UResourceKtExt.kt | 77 ++++ .../datamodel/UCloudEventAttributesTest.kt | 95 ++-- .../factory/CloudEventFactoryTest.kt | 74 ++-- .../cloudevent/factory/UCloudEventTest.kt | 64 +-- .../CloudEventToJsonSerializerTest.kt | 20 +- .../CloudEventToProtobufSerializerTest.kt | 22 +- .../validate/CloudEventValidatorTest.kt | 33 +- .../eclipse/uprotocol/rpc/CallOptionsTest.kt | 80 ++-- .../org/eclipse/uprotocol/rpc/RpcTest.kt | 3 +- .../validator/UAttributesValidatorTest.kt | 408 ++++++++++++------ .../uri/factory/UResourceFactoryTest.kt | 55 ++- .../uri/serializer/LongUriSerializerTest.kt | 3 +- .../uri/serializer/MicroUriSerializerTest.kt | 5 +- .../uri/serializer/UriSerializerTest.kt | 5 +- .../uri/validator/UriValidatorTest.kt | 13 +- .../builder => v1}/UAttributesBuilderTest.kt | 61 +-- 22 files changed, 788 insertions(+), 823 deletions(-) delete mode 100644 src/main/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilder.kt delete mode 100644 src/main/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactory.kt create mode 100644 src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt create mode 100644 src/main/kotlin/org/eclipse/uprotocol/v1/UResourceKtExt.kt rename src/test/kotlin/org/eclipse/uprotocol/{transport/builder => v1}/UAttributesBuilderTest.kt (64%) diff --git a/src/main/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributes.kt b/src/main/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributes.kt index 396c1fb..c161036 100644 --- a/src/main/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributes.kt +++ b/src/main/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributes.kt @@ -35,7 +35,7 @@ import java.util.* * Events without this attribute (or value is 0) MUST NOT timeout. * @param token Oauth2 access token to perform the access request defined in the request message. */ -class UCloudEventAttributes private constructor( +data class UCloudEventAttributes internal constructor( private val hash: String? = null, private val priority: UPriority? = null, private val ttl: Int? = null, @@ -101,111 +101,51 @@ class UCloudEventAttributes private constructor( /** * Builder for constructing the UCloudEventAttributes. */ - class UCloudEventAttributesBuilder { - var hash: String? = null - var priority: UPriority? = null - var ttl: Int? = null - var token: String? = null - var traceparent: String? = null - + class UCloudEventAttributesBuilder @PublishedApi internal constructor() { /** * add an HMAC generated on the data portion of the CloudEvent message using the device key. - * @param hash an HMAC generated on the data portion of the CloudEvent message using the device key. - * @return Returns the UCloudEventAttributesBuilder with the configured hash. */ - fun withHash(hash: String?): UCloudEventAttributesBuilder { - this.hash = hash - return this - } + var hash: String? = null /** * add a uProtocol Prioritization classifications. - * @param priority uProtocol Prioritization classifications. - * @return Returns the UCloudEventAttributesBuilder with the configured priority. */ - fun withPriority(priority: UPriority?): UCloudEventAttributesBuilder { - this.priority = priority - return this - } + var priority: UPriority? = null /** * add a time to live which is how long this event should live for after it was generated (in milliseconds). * Events without this attribute (or value is 0) MUST NOT timeout. - * @param ttl How long this event should live for after it was generated (in milliseconds). - * Events without this attribute (or value is 0) MUST NOT timeout. - * @return Returns the UCloudEventAttributesBuilder with the configured time to live. */ - fun withTtl(ttl: Int?): UCloudEventAttributesBuilder { - this.ttl = ttl - return this - } + var ttl: Int? = null /** * Add an Oauth2 access token to perform the access request defined in the request message. - * @param token An Oauth2 access token to perform the access request defined in the request message. - * @return Returns the UCloudEventAttributesBuilder with the configured OAuth token. */ - fun withToken(token: String?): UCloudEventAttributesBuilder { - this.token = token - return this - } + var token: String? = null /** * Add an identifier used to correlate observability across related events. - * @param traceparent An identifier used to correlate observability across related events. - * @return Returns the UCloudEventAttributesBuilder with the configured traceparent. */ - fun withTraceparent(traceparent: String?): UCloudEventAttributesBuilder { - this.traceparent = traceparent - return this - } + var traceparent: String? = null + /** * Construct the UCloudEventAttributes from the builder. * @return Returns a constructed UProperty. */ - fun build(): UCloudEventAttributes { + @JvmSynthetic + @PublishedApi + internal fun build(): UCloudEventAttributes { // validation if needed return UCloudEventAttributes(this) } } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || javaClass !== other.javaClass) return false - val that = other as UCloudEventAttributes - return Objects.equals(hash, that.hash) && priority == that.priority && Objects.equals( - ttl, - that.ttl - ) && Objects.equals(token, that.token) && Objects.equals(traceparent, that.traceparent) - } - - override fun hashCode(): Int { - return Objects.hash(hash, priority, ttl, token, traceparent) - } - - override fun toString(): String { - val traceParentString = traceparent?.let { ", traceparent='$it'" }?:"" - return "UCloudEventAttributes{" + - "hash='" + hash + '\'' + - ", priority=" + priority + - ", ttl=" + ttl + - ", token='" + token + '\'' + - traceParentString + - '}' - } - companion object { - private val EMPTY = UCloudEventAttributes(null, null, null, null) + val EMPTY = UCloudEventAttributes() - /** - * Static factory method for creating an empty cloud event attributes object, to avoid working with null

- * @return Returns an empty cloud event attributes that indicates - * that there are no added additional attributes to configure. - */ - fun empty(): UCloudEventAttributes { - return EMPTY - } + @JvmName("-initializeUCloudEventAttributes") + inline fun uCloudEventAttributes(block: UCloudEventAttributesBuilder.() -> Unit) = + UCloudEventAttributesBuilder().apply(block).build() } } diff --git a/src/main/kotlin/org/eclipse/uprotocol/rpc/CallOptions.kt b/src/main/kotlin/org/eclipse/uprotocol/rpc/CallOptions.kt index 632089b..5cc7515 100644 --- a/src/main/kotlin/org/eclipse/uprotocol/rpc/CallOptions.kt +++ b/src/main/kotlin/org/eclipse/uprotocol/rpc/CallOptions.kt @@ -24,114 +24,66 @@ package org.eclipse.uprotocol.rpc -import java.util.Objects -import java.util.Optional - /** * This class is used when making uRPC calls to pass additional options. Copied from Misha's class. + * @property timeout a timeout in milliseconds + * @property token An optional OAuth2 access token */ -class CallOptions private constructor(private val mTimeout: Int, token: String?) { - private val mToken: String - - private constructor(builder: Builder) : this(builder.mTimeout, builder.mToken) - - init { - mToken = token ?: "" - } - - /** - * Get a timeout. - * - * @return A timeout in milliseconds. - */ - fun timeout(): Int { - return mTimeout - } - - /** - * Get an OAuth2 access token. - * - * @return An Optional OAuth2 access token. - */ - fun token(): Optional { - return if (mToken.isBlank()) Optional.empty() else Optional.of(mToken) - } +data class CallOptions internal constructor( + val timeout: Int = TIMEOUT_DEFAULT, + val token: String = TOKEN_DEFAULT +) { + private constructor(builder: Builder) : this(builder.timeout, builder.token) /** * Builder for constructing `CallOptions`. + * @property timeout a timeout in milliseconds + * @property token an OAuth2 access token */ - class Builder { - var mTimeout = TIMEOUT_DEFAULT - var mToken = "" - - /** - * Add a timeout. - * - * @param timeout A timeout in milliseconds. - * @return This builder. - */ - fun withTimeout(timeout: Int): Builder { - mTimeout = if (timeout <= 0) TIMEOUT_DEFAULT else timeout - return this - } - - /** - * Add an OAuth2 access token. - * - * @param token An OAuth2 access token. - * @return This builder. - */ - fun withToken(token: String): Builder { - mToken = token - return this - } + class Builder @PublishedApi internal constructor() { + var timeout = TIMEOUT_DEFAULT + set(value) { + field = value.takeIf { it >= 0 } ?: TIMEOUT_DEFAULT + } + var token = TOKEN_DEFAULT + set(value) { + field = value.ifBlank { TOKEN_DEFAULT } + } /** * Construct a `CallOptions` from this builder. * * @return A constructed `CallOptions`. */ - fun build(): CallOptions { + @JvmSynthetic + @PublishedApi + internal fun build(): CallOptions { return CallOptions(this) } } - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || javaClass !== other.javaClass) return false - val that = other as CallOptions - return mTimeout == that.mTimeout && Objects.equals(mToken, that.mToken) - } - - override fun hashCode(): Int { - return Objects.hash(mTimeout, mToken) - } - - override fun toString(): String { - return "CallOptions{" + - "mTimeout=" + mTimeout + - ", mToken='" + mToken + '\'' + - '}' - } - companion object { /** * Default timeout of a call in milliseconds. */ const val TIMEOUT_DEFAULT = 10000 + /** + * Default token. + */ + const val TOKEN_DEFAULT = "" + /** * Default instance. */ - val DEFAULT = CallOptions(TIMEOUT_DEFAULT, "") + val DEFAULT = CallOptions(TIMEOUT_DEFAULT, TOKEN_DEFAULT) /** * Constructs a new builder. * * @return A builder. */ - fun newBuilder(): Builder { - return Builder() - } + @JvmName("-initializeCallOptions") + inline fun callOptions(block: Builder.() -> Unit) = Builder().apply(block).build() } } diff --git a/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilder.kt b/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilder.kt deleted file mode 100644 index d37f7b6..0000000 --- a/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilder.kt +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2024 General Motors GTO LLC - * - * 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. - * SPDX-FileType: SOURCE - * SPDX-FileCopyrightText: 2023 General Motors GTO LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.uprotocol.transport.builder - -import org.eclipse.uprotocol.uuid.factory.UUIDV8 -import org.eclipse.uprotocol.v1.* - -/** - * Builder for easy construction of the UAttributes object. - */ -class UAttributesBuilder -/** - * Construct the UAttributesBuilder with the configurations that are required for every payload transport. - * - * @param source Source address of the message. - * @param uuid Unique identifier for the message. - * @param messageType Message type such as Publish a state change, RPC request or RPC response. - * @param uPriority uProtocol Prioritization classifications. - */ private constructor( - private val source: UUri, - private val uuid: UUID, - private val messageType: UMessageType, - private val uPriority: UPriority -) { - private var timeToLive: Int? = null - private var tokenAttr: String? = null - private var sinkUUri: UUri? = null - private var plevel: Int? = null - private var commStatus: Int? = null - private var reqId: UUID? = null - private var traceparentAttr: String? = null - - /** - * Add the time to live in milliseconds. - * - * @param ttl the time to live in milliseconds. - * @return Returns the UAttributesBuilder with the configured ttl. - */ - fun withTtl(ttl: Int?): UAttributesBuilder { - timeToLive = ttl - return this - } - - /** - * Add the authorization token used for TAP. - * - * @param token the authorization token used for TAP. - * @return Returns the UAttributesBuilder with the configured token. - */ - fun withToken(token: String?): UAttributesBuilder { - tokenAttr = token - return this - } - - /** - * Add the explicit destination URI. - * - * @param sink the explicit destination URI. - * @return Returns the UAttributesBuilder with the configured sink. - */ - fun withSink(sink: UUri?): UAttributesBuilder { - sinkUUri = sink - return this - } - - /** - * Add the permission level of the message. - * - * @param plevel the permission level of the message. - * @return Returns the UAttributesBuilder with the configured plevel. - */ - fun withPermissionLevel(plevel: Int?): UAttributesBuilder { - this.plevel = plevel - return this - } - - /** - * Add the communication status of the message. - * - * @param commstatus the communication status of the message. - * @return Returns the UAttributesBuilder with the configured commstatus. - */ - fun withCommStatus(commstatus: Int?): UAttributesBuilder { - commStatus = commstatus - return this - } - - /** - * Add the request ID. - * - * @param reqid the request ID. - * @return Returns the UAttributesBuilder with the configured reqid. - */ - fun withReqId(reqid: UUID?): UAttributesBuilder { - reqId = reqid - return this - } - - /** - * Add the traceparent. - * - * @param traceparent the trace parent. - * @return Returns the UAttributesBuilder with the configured traceparent. - */ - fun withTraceparent(traceparent: String): UAttributesBuilder { - this.traceparentAttr = traceparent - return this - } - - /** - * Construct the UAttributes from the builder. - * - * @return Returns a constructed - */ - fun build(): UAttributes { - return uAttributes { - id = uuid - type = messageType - priority = uPriority - sinkUUri?.let { sink = it } - timeToLive?.let { ttl = it } - plevel?.let { permissionLevel = it } - commStatus?.let { commstatus = it } - reqId?.let { reqid = it } - tokenAttr?.let { token = it } - traceparentAttr?.let { traceparent = it } - } - } - - companion object { - /** - * Construct a UAttributesBuilder for a publish message. - * @param source Source address of the message. - * @param priority The priority of the message. - * @return Returns the UAttributesBuilder with the configured priority. - */ - fun publish(source: UUri, priority: UPriority): UAttributesBuilder { - return UAttributesBuilder( - source, - UUIDV8(), - UMessageType.UMESSAGE_TYPE_PUBLISH, priority - ) - } - - /** - * Construct a UAttributesBuilder for a notification message. - * @param source Source address of the message. - * @param sink The destination URI. - * @param priority The priority of the message. - * @return Returns the UAttributesBuilder with the configured priority and sink. - */ - fun notification(source: UUri, sink: UUri, priority: UPriority): UAttributesBuilder { - return UAttributesBuilder( - source, - UUIDV8(), - UMessageType.UMESSAGE_TYPE_PUBLISH, priority - ).withSink(sink) - } - - /** - * Construct a UAttributesBuilder for a request message. - * @param source Source address of the message. - * @param sink The destination URI. - * @param priority The priority of the message. - * @param ttl The time to live in milliseconds. - * @return Returns the UAttributesBuilder with the configured priority, sink and ttl. - */ - fun request(source: UUri, sink: UUri, priority: UPriority, ttl: Int): UAttributesBuilder { - return UAttributesBuilder( - source, - UUIDV8(), - UMessageType.UMESSAGE_TYPE_REQUEST, priority - ).withTtl(ttl).withSink(sink) - } - - /** - * Construct a UAttributesBuilder for a response message. - * @param source Source address of the message. - * @param sink The destination URI. - * @param priority The priority of the message. - * @param reqid The original request UUID used to correlate the response to the request. - * @return Returns the UAttributesBuilder with the configured priority, sink and reqid. - */ - fun response(source: UUri, sink: UUri, priority: UPriority, reqid: UUID): UAttributesBuilder { - return UAttributesBuilder( - source, - UUIDV8(), - UMessageType.UMESSAGE_TYPE_RESPONSE, priority - ).withSink(sink).withReqId(reqid) - } - } -} diff --git a/src/main/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactory.kt b/src/main/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactory.kt deleted file mode 100644 index db4aa5e..0000000 --- a/src/main/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactory.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2024 General Motors GTO LLC - * - * 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. - * SPDX-FileType: SOURCE - * SPDX-FileCopyrightText: 2023 General Motors GTO LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.eclipse.uprotocol.uri.factory - -import com.google.protobuf.ProtocolMessageEnum -import org.eclipse.uprotocol.v1.UResource -import org.eclipse.uprotocol.v1.uResource - -object UResourceFactory { - private const val MAX_RPC_ID = 1000 - - /** - * Create a UResource for an RPC response. - * @return Returns a UResource for an RPC response. - */ - fun createForRpcResponse(): UResource { - - return uResource { - name = "rpc" - instance = "response" - id = 0 - } - } - - /** - * Create a UResource for an RPC request with at least an ID or a method name - * @param method The method to be invoked. - * @param id The ID of the request. - * @return Returns a UResource for an RPC request. - */ - fun createForRpcRequest(method: String? = null, id: Int? = null): UResource { - return uResource { - name = "rpc" - if (method != null) instance = method - if (id != null) this.id = id - } - } - - /** - * Create a UResource from an ID. This method will determine if - * the id is an RPC or topic ID based on the range - * @param id The ID of the request. - * @return Returns a UResource for an RPC request. - */ - fun from(id: Int): UResource { - return if (id < MAX_RPC_ID) createForRpcRequest(id = id) else uResource { this.id = id } - } - - /** - * Build a UResource from a protobuf message. This method will determine if - * the message is a RPC or topic message based on the message type - * @param message The protobuf message. - * @return Returns a UResource for an RPC request. - */ - fun from(message: ProtocolMessageEnum): UResource { - return uResource { - message.descriptorForType.containingType.name?.let { name = it } - message.valueDescriptor.name?.let { instance = it } - id = message.number - } - } - -} diff --git a/src/main/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializer.kt b/src/main/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializer.kt index b5b57e8..e63e7c6 100644 --- a/src/main/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializer.kt +++ b/src/main/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializer.kt @@ -25,7 +25,6 @@ package org.eclipse.uprotocol.uri.serializer import com.google.protobuf.ByteString -import org.eclipse.uprotocol.uri.factory.UResourceFactory import org.eclipse.uprotocol.uri.validator.isEmpty import org.eclipse.uprotocol.uri.validator.isMicroForm import org.eclipse.uprotocol.v1.* @@ -194,7 +193,9 @@ class MicroUriSerializer private constructor() : UriSerializer { id = ueId versionMajor = uiVersion } - resource = UResourceFactory.from(uResourceId) + resource = uResource{ + from(uResourceId) + } uAuthority?.let { authority = it } } } diff --git a/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt b/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt new file mode 100644 index 0000000..9b22c27 --- /dev/null +++ b/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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. + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2024 General Motors GTO LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.uprotocol.v1 + +import org.eclipse.uprotocol.uuid.factory.UUIDV8 + +/** + * Construct a UAttributesBuilder for a publish message. + * @param source Source address of the message. + * @param priority The priority of the message. + * @return Returns the UAttributesBuilder with the configured priority. + */ +@JvmSynthetic +fun UAttributesKt.Dsl.forPublication(source: UUri, priority: UPriority) { + this@forPublication.source = source + this@forPublication.priority = priority + id = UUIDV8() + type = UMessageType.UMESSAGE_TYPE_PUBLISH +} + +/** + * Construct a UAttributesBuilder for a notification message. + * @param source Source address of the message. + * @param sink The destination URI. + * @param priority The priority of the message. + * @return Returns the UAttributesBuilder with the configured priority and sink. + */ +@JvmSynthetic +fun UAttributesKt.Dsl.forNotification(source: UUri, sink: UUri, priority: UPriority) { + this@forNotification.source = source + this@forNotification.sink = sink + this@forNotification.priority = priority + id = UUIDV8() + type = UMessageType.UMESSAGE_TYPE_PUBLISH +} + +/** + * Construct a UAttributesBuilder for a request message. + * @param source Source address of the message. + * @param sink The destination URI. + * @param priority The priority of the message. + * @param ttl The time to live in milliseconds. + * @return Returns the UAttributesBuilder with the configured priority, sink and ttl. + */ +@JvmSynthetic +fun UAttributesKt.Dsl.forRequest(source: UUri, sink: UUri, priority: UPriority, ttl: Int) { + this@forRequest.source = source + this@forRequest.sink = sink + this@forRequest.priority = priority + this@forRequest.ttl = ttl + id = UUIDV8() + type = UMessageType.UMESSAGE_TYPE_REQUEST +} + +/** + * Construct a UAttributesBuilder for a response message. + * @param source Source address of the message. + * @param sink The destination URI. + * @param priority The priority of the message. + * @param reqId The original request UUID used to correlate the response to the request. + * @return Returns the UAttributesBuilder with the configured priority, sink and reqid. + */ +@JvmSynthetic +fun UAttributesKt.Dsl.forResponse(source: UUri, sink: UUri, priority: UPriority, reqId: UUID) { + this@forResponse.source = source + this@forResponse.sink = sink + this@forResponse.priority = priority + id = UUIDV8() + type = UMessageType.UMESSAGE_TYPE_RESPONSE + reqid = reqId +} \ No newline at end of file diff --git a/src/main/kotlin/org/eclipse/uprotocol/v1/UResourceKtExt.kt b/src/main/kotlin/org/eclipse/uprotocol/v1/UResourceKtExt.kt new file mode 100644 index 0000000..df74bb2 --- /dev/null +++ b/src/main/kotlin/org/eclipse/uprotocol/v1/UResourceKtExt.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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. + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2024 General Motors GTO LLC + * SPDX-License-Identifier: Apache-2.0 + */ +package org.eclipse.uprotocol.v1 + +import com.google.protobuf.ProtocolMessageEnum + +private val MAX_RPC_ID: Int + @JvmSynthetic get() = 1000 + +/** + * Initializes a UResource for an RPC response. + */ +@JvmSynthetic +fun UResourceKt.Dsl.forRpcResponse() { + name = "rpc" + instance = "response" + id = 0 +} + +/** + * Initializes a UResource for an RPC request with an ID and/or a method name + * @param method The method to be invoked. + * @param id The ID of the request. + */ +@JvmSynthetic +fun UResourceKt.Dsl.forRpcRequest(method: String = instance, id: Int = this@forRpcRequest.id) { + name = "rpc" + if (method != instance) { + instance = method + } + if (id != this@forRpcRequest.id) { + this@forRpcRequest.id = id + } +} + +/** + * Initializes a UResource from an ID. This method will determine if + * the id is an RPC or topic ID based on the range + * @param id The ID of the request. + */ +@JvmSynthetic +fun UResourceKt.Dsl.from(id: Int) { + if (id < MAX_RPC_ID) forRpcRequest(id = id) else this@from.id = id +} + +/** + * Initializes a UResource from a protobuf message. This method will determine if + * the message is a RPC or topic message based on the message type + * @param message The protobuf message. + */ +@JvmSynthetic +fun UResourceKt.Dsl.from(message: ProtocolMessageEnum) { + message.descriptorForType.containingType.name?.let { name = it } + message.valueDescriptor.name?.let { instance = it } + id = message.number +} diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributesTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributesTest.kt index 6de80d6..94b2701 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributesTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/datamodel/UCloudEventAttributesTest.kt @@ -21,7 +21,7 @@ package org.eclipse.uprotocol.cloudevent.datamodel import nl.jqno.equalsverifier.EqualsVerifier -import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.UCloudEventAttributesBuilder +import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.Companion.uCloudEventAttributes import org.eclipse.uprotocol.v1.UPriority import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.DisplayName @@ -37,41 +37,27 @@ internal class UCloudEventAttributesTest { @Test @DisplayName("Make sure the default toString works") fun testToString() { - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1) - .withTtl(3) - .withToken("someOAuthToken") - .build() - val expected = "UCloudEventAttributes{hash='somehash', priority=UPRIORITY_CS1, ttl=3, token='someOAuthToken'}" - assertEquals(expected, uCloudEventAttributes.toString()) - } - - - @Test - @DisplayName("Make sure the toString works when all properties are filled") - fun testToStringComplete() { - val uCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1) - .withTtl(3) - .withToken("someOAuthToken") - .withTraceparent("darthvader") - .build() - val expected = - "UCloudEventAttributes{hash='somehash', priority=UPRIORITY_CS1, ttl=3, token='someOAuthToken', traceparent='darthvader'}" + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + traceparent = "someTraceparent" + } + val expected = "UCloudEventAttributes(hash=somehash, priority=UPRIORITY_CS1, ttl=3, token=someOAuthToken, traceparent=someTraceparent)" assertEquals(expected, uCloudEventAttributes.toString()) } @Test @DisplayName("Test creating a valid attributes object") fun test_create_valid() { - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS6) - .withTtl(3) - .withToken("someOAuthToken") - .build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS6 + ttl = 3 + token = "someOAuthToken" + traceparent = "someTraceparent" + } assertTrue(uCloudEventAttributes.hash().isPresent) assertEquals("somehash", uCloudEventAttributes.hash().get()) assertTrue(uCloudEventAttributes.priority().isPresent) @@ -80,26 +66,29 @@ internal class UCloudEventAttributesTest { assertEquals(3, uCloudEventAttributes.ttl().get()) assertTrue(uCloudEventAttributes.token().isPresent) assertEquals("someOAuthToken", uCloudEventAttributes.token().get()) + assertTrue(uCloudEventAttributes.traceparent().isPresent) + assertEquals("someTraceparent", uCloudEventAttributes.traceparent().get()) } @Test @DisplayName("Test the isEmpty function") fun test_Isempty_function() { - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributes.empty() + val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributes.EMPTY assertTrue(uCloudEventAttributes.isEmpty) assertTrue(uCloudEventAttributes.hash().isEmpty) assertTrue(uCloudEventAttributes.priority().isEmpty) assertTrue(uCloudEventAttributes.token().isEmpty) assertTrue(uCloudEventAttributes.ttl().isEmpty) + assertTrue(uCloudEventAttributes.traceparent().isEmpty) } @Test @DisplayName("Test the isEmpty when built with blank strings function") fun test_Isempty_function_when_built_with_blank_strings() { - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash(" ") - .withToken(" ") - .build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = " " + token = " " + } assertTrue(uCloudEventAttributes.isEmpty) assertTrue(uCloudEventAttributes.hash().isEmpty) assertTrue(uCloudEventAttributes.priority().isEmpty) @@ -110,28 +99,28 @@ internal class UCloudEventAttributesTest { @Test @DisplayName("Test the isEmpty permutations") fun test_Isempty_function_permutations() { - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash(" ") - .withToken(" ") - .build() + val uCloudEventAttributes= uCloudEventAttributes { + hash = " " + token = " " + } assertTrue(uCloudEventAttributes.isEmpty) - val uCloudEventAttributes2: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash("someHash") - .withToken(" ") - .build() + val uCloudEventAttributes2 = uCloudEventAttributes { + hash = "someHash" + token = " " + } assertFalse(uCloudEventAttributes2.isEmpty) - val uCloudEventAttributes3: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withHash(" ") - .withToken("SomeToken") - .build() + val uCloudEventAttributes3 = uCloudEventAttributes { + hash = " " + token = "SomeToken" + } assertFalse(uCloudEventAttributes3.isEmpty) - val uCloudEventAttributes4: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withPriority(UPriority.UPRIORITY_CS0) - .build() + val uCloudEventAttributes4 = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS0 + } assertFalse(uCloudEventAttributes4.isEmpty) - val uCloudEventAttributes5: UCloudEventAttributes = UCloudEventAttributesBuilder() - .withTtl(8) - .build() + val uCloudEventAttributes5 = uCloudEventAttributes { + ttl = 8 + } assertFalse(uCloudEventAttributes5.isEmpty) } } \ No newline at end of file diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/CloudEventFactoryTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/CloudEventFactoryTest.kt index e21f0e6..2d91136 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/CloudEventFactoryTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/CloudEventFactoryTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 General Motors GTO LLC + * Copyright (c) 2024 General Motors GTO LLC * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -24,6 +24,7 @@ import com.google.protobuf.Any import io.cloudevents.CloudEvent import io.cloudevents.core.builder.CloudEventBuilder import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes +import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.Companion.uCloudEventAttributes import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.v1.* import org.junit.jupiter.api.Assertions.* @@ -42,10 +43,12 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1).withTtl(3).withToken("someOAuthToken").build() - + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( "testme", source, protoPayload.toByteArray(), protoPayload.typeUrl, uCloudEventAttributes @@ -73,9 +76,12 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1).withTtl(3).withToken("someOAuthToken").build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( @@ -111,7 +117,7 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // no additional attributes - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributes.empty() + val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributes.EMPTY // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( @@ -141,9 +147,11 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1).withTtl(3).build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + } val cloudEvent: CloudEvent = CloudEventFactory.publish(source, protoPayload, uCloudEventAttributes) assertEquals("1.0", cloudEvent.specVersion.toString()) assertNotNull(cloudEvent.id) @@ -170,10 +178,11 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS2).withTtl(3).build() - + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } // build the cloud event of type publish with destination - a notification val cloudEvent: CloudEvent = CloudEventFactory.notification(source, sink, protoPayload, uCloudEventAttributes) assertEquals("1.0", cloudEvent.specVersion.toString()) @@ -202,9 +211,12 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS2).withTtl(3).withToken("someOAuthToken").build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + token = "someOAuthToken" + } val cloudEvent: CloudEvent = CloudEventFactory.request( applicationUriForRPC, serviceMethodUri, protoPayload, uCloudEventAttributes ) @@ -235,9 +247,11 @@ internal class CloudEventFactoryTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS2).withTtl(3).build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } val cloudEvent: CloudEvent = CloudEventFactory.response( applicationUriForRPC, serviceMethodUri, @@ -269,9 +283,11 @@ internal class CloudEventFactoryTest { val serviceMethodUri = buildUriForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS2).withTtl(3).build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } val cloudEvent: CloudEvent = CloudEventFactory.failedResponse( applicationUriForRPC, serviceMethodUri, @@ -304,9 +320,11 @@ internal class CloudEventFactoryTest { // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS2).withTtl(3).build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } val cloudEvent: CloudEvent = CloudEventFactory.failedResponse( applicationUriForRPC, serviceMethodUri, diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt index 1200f1e..d601dfa 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt @@ -26,6 +26,7 @@ import io.cloudevents.CloudEvent import io.cloudevents.CloudEventData import io.cloudevents.core.builder.CloudEventBuilder import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes +import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.Companion.uCloudEventAttributes import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.uuid.factory.UUIDV8 import org.eclipse.uprotocol.uuid.serializer.LongUuidSerializer @@ -623,9 +624,10 @@ internal class UCloudEventTest { @Test fun test_to_message_with_valid_event() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2).withTtl(3) - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } // CloudEvent val cloudEvent = CloudEventFactory.publish( @@ -639,9 +641,10 @@ internal class UCloudEventTest { @Test fun test_from_message_with_valid_message() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2).withTtl(3) - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } // CloudEvent val cloudEvent = CloudEventFactory.publish( @@ -658,11 +661,12 @@ internal class UCloudEventTest { @Test fun test_to_from_message_from_request_cloudevent() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2) - .withToken("someOAuthToken").withTtl(3) - .withTraceparent("someTraceparent") - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + token = "someOAuthToken" + traceparent = "someTraceparent" + } // CloudEvent val cloudEvent = CloudEventFactory.request( @@ -729,9 +733,10 @@ internal class UCloudEventTest { @Test fun test_to_from_message_from_response_cloudevent() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2).withTtl(3) - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } // CloudEvent val cloudEvent = CloudEventFactory.response( @@ -769,9 +774,10 @@ internal class UCloudEventTest { @Test fun test_umessage_has_platform_error_when_platform_error_exists() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2).withTtl(3) - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } val protoPayload = buildProtoPayloadForTest() val cloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( @@ -795,9 +801,10 @@ internal class UCloudEventTest { @Test fun test_to_from_message_from_cloudevent_with_all_payload_formats() { // Additional attributes - val uCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority(UPriority.UPRIORITY_CS2).withTtl(3) - .build() + val uCloudEventAttributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS2 + ttl = 3 + } val protoPayload = buildProtoPayloadForTest() val cloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( LongUuidSerializer.INSTANCE.serialize( @@ -866,7 +873,9 @@ internal class UCloudEventTest { @Test fun test_to_from_message_from_UCP_cloudevent() { // Additional attributes - val uCloudEventAttributes = UCloudEventAttributes.UCloudEventAttributesBuilder().withTtl(3).build() + val uCloudEventAttributes = uCloudEventAttributes { + ttl = 3 + } val protoPayload = buildProtoPayloadForTest() val cloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( LongUuidSerializer.INSTANCE.serialize( @@ -907,12 +916,13 @@ internal class UCloudEventTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash( - "somehash" - ).withPriority(UPriority.UPRIORITY_CS1).withTtl(3).withToken( - "someOAuthToken" - ).withTraceparent("someTraceparent").build() + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + traceparent = "someTraceparent" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt index 516e42f..300faa9 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 General Motors GTO LLC + * Copyright (c) 2024 General Motors GTO LLC * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -43,7 +43,6 @@ internal class CloudEventToJsonSerializerTest { @Test @DisplayName("Test serialize a CloudEvent to JSON") fun test_serialize_cloud_event_to_json() { - // fake payload val protoPayload = buildProtoPayloadForTest() @@ -58,13 +57,14 @@ internal class CloudEventToJsonSerializerTest { .withExtension("ttl", 3) .withExtension("priority", "CS1") val cloudEvent: CloudEvent = cloudEventBuilder.build() + //cloudEvent.getAttribute("traceparent") val bytes: ByteArray = serializer.serialize(cloudEvent) val jsonString = String(bytes, StandardCharsets.UTF_8) val expected = "{\"specversion\":\"1.0\",\"id\":\"hello\",\"source\":\"/body.access/1/door.front_left\",\"type\":\"pub.v1\"," + "\"datacontenttype\":\"application/x-protobuf\",\"dataschema\":\"type.googleapis.com/io.cloudevents.v1.CloudEvent\"," + "\"priority\":\"CS1\",\"ttl\":3," + - "\"data_base64\":\"CjB0eXBlLmdvb2dsZWFwaXMuY29tL2lvLmNsb3VkZXZlbnRzLnYxLkNsb3VkRXZlbnQSPAoFaGVsbG8SEmh0dHA6Ly9leGFtcGxlLmNvbRoDMS4wIgxleGFtcGxlLmRlbW8qCgoDdHRsEgMaATNCAA==\"}" + "\"data_base64\":\"CjB0eXBlLmdvb2dsZWFwaXMuY29tL2lvLmNsb3VkZXZlbnRzLnYxLkNsb3VkRXZlbnQSPQoFaGVsbG8SE2h0dHBzOi8vZXhhbXBsZS5jb20aAzEuMCIMZXhhbXBsZS5kZW1vKgoKA3R0bBIDGgEzQgA=\"}" assertEquals(expected, jsonString) } @@ -158,12 +158,12 @@ internal class CloudEventToJsonSerializerTest { val protoPayload = buildProtoPayloadForTest1() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = UCloudEventAttributes.UCloudEventAttributesBuilder() - .withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1) - .withTtl(3) - .withToken("someOAuthToken") - .build() + val uCloudEventAttributes = UCloudEventAttributes.uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( @@ -232,7 +232,7 @@ internal class CloudEventToJsonSerializerTest { val cloudEventProto: io.cloudevents.v1.proto.CloudEvent = io.cloudevents.v1.proto.CloudEvent.newBuilder() .setSpecVersion("1.0") .setId("hello") - .setSource("http://example.com") + .setSource("https://example.com") .setType("example.demo") .setProtoData(Any.newBuilder().build()) .putAttributes( diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToProtobufSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToProtobufSerializerTest.kt index ad81459..de7edb3 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToProtobufSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToProtobufSerializerTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 General Motors GTO LLC + * Copyright (c) 2024 General Motors GTO LLC * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -52,9 +52,12 @@ internal class CloudEventToProtobufSerializerTest { val protoPayload = buildProtoPayloadForTest() // configure cloud event - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS0).withTtl(3).build() + val uCloudEventAttributes = UCloudEventAttributes.uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS0 + ttl = 3 + token = "someOAuthToken" + } val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( "hello", source, protoPayload.toByteArray(), protoPayload.typeUrl, uCloudEventAttributes ) @@ -123,9 +126,12 @@ internal class CloudEventToProtobufSerializerTest { val protoPayload = buildProtoPayloadForTest1() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash("somehash") - .withPriority(UPriority.UPRIORITY_CS1).withTtl(3).withToken("someOAuthToken").build() + val uCloudEventAttributes = UCloudEventAttributes.uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( @@ -260,7 +266,7 @@ internal class CloudEventToProtobufSerializerTest { private fun buildProtoPayloadForTest(): Any { val cloudEventProto: io.cloudevents.v1.proto.CloudEvent = io.cloudevents.v1.proto.CloudEvent.newBuilder().setSpecVersion("1.0").setId("hello") - .setSource("http://example.com").setType("example.demo").setProtoData(Any.newBuilder().build()) + .setSource("https://example.com").setType("example.demo").setProtoData(Any.newBuilder().build()) .putAttributes( "ttl", io.cloudevents.v1.proto.CloudEvent.CloudEventAttributeValue.newBuilder().setCeString("3").build() diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/validate/CloudEventValidatorTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/validate/CloudEventValidatorTest.kt index 70beac3..0b8d83f 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/validate/CloudEventValidatorTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/validate/CloudEventValidatorTest.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 General Motors GTO LLC + * Copyright (c) 2024 General Motors GTO LLC * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,7 +23,7 @@ package org.eclipse.uprotocol.cloudevent.validate import com.google.protobuf.Any import io.cloudevents.CloudEvent import io.cloudevents.core.builder.CloudEventBuilder -import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes +import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.Companion.uCloudEventAttributes import org.eclipse.uprotocol.cloudevent.factory.CloudEventFactory import org.eclipse.uprotocol.cloudevent.factory.UCloudEvent import org.eclipse.uprotocol.uri.serializer.LongUriSerializer @@ -526,13 +526,12 @@ internal class CloudEventValidatorTest { val protoPayload = buildProtoPayloadForTest() // additional attributes - val uCloudEventAttributes: UCloudEventAttributes = - UCloudEventAttributes.UCloudEventAttributesBuilder().withHash( - "somehash" - ).withPriority(UPriority.UPRIORITY_CS1).withTtl(3).withToken( - "someOAuthToken" - ).build() - + val uCloudEventAttributes = uCloudEventAttributes { + hash = "somehash" + priority = UPriority.UPRIORITY_CS1 + ttl = 3 + token = "someOAuthToken" + } // build the cloud event val cloudEventBuilder: CloudEventBuilder = CloudEventFactory.buildBaseCloudEvent( "testme", source, protoPayload.toByteArray(), protoPayload.typeUrl, uCloudEventAttributes @@ -559,10 +558,10 @@ internal class CloudEventValidatorTest { // fake payload val protoPayload = buildProtoPayloadForTest() - val attributes: UCloudEventAttributes = UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority( - UPriority.UPRIORITY_CS0 - ).withTtl(1000) // live for 1 second - .build() + val attributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS0 + ttl = 1000 + } // build the cloud event val cloudEvent: CloudEvent = CloudEventFactory.buildBaseCloudEvent( @@ -585,10 +584,10 @@ internal class CloudEventValidatorTest { // fake payload val protoPayload = buildProtoPayloadForTest() - val attributes: UCloudEventAttributes = UCloudEventAttributes.UCloudEventAttributesBuilder().withPriority( - UPriority.UPRIORITY_CS0 - ).withTtl(1000) // live for 1 second - .build() + val attributes = uCloudEventAttributes { + priority = UPriority.UPRIORITY_CS0 + ttl = 1000 + } // build the cloud event val cloudEvent: CloudEvent = CloudEventFactory.buildBaseCloudEvent( diff --git a/src/test/kotlin/org/eclipse/uprotocol/rpc/CallOptionsTest.kt b/src/test/kotlin/org/eclipse/uprotocol/rpc/CallOptionsTest.kt index fa65d53..42b6901 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/rpc/CallOptionsTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/rpc/CallOptionsTest.kt @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023 General Motors GTO LLC + * Copyright (c) 2024 General Motors GTO LLC * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -22,6 +22,7 @@ package org.eclipse.uprotocol.rpc import nl.jqno.equalsverifier.EqualsVerifier +import org.eclipse.uprotocol.rpc.CallOptions.Companion.callOptions import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.assertEquals @@ -38,11 +39,11 @@ class CallOptionsTest { @Test @DisplayName("Make sure the toString works") fun testToString() { - val callOptions = CallOptions.newBuilder() - .withTimeout(30) - .withToken("someToken") - .build() - val expected = "CallOptions{mTimeout=30, mToken='someToken'}" + val callOptions = callOptions { + timeout = 30 + token = "someToken" + } + val expected = "CallOptions(timeout=30, token=someToken)" assertEquals(expected, callOptions.toString()) } @@ -50,60 +51,69 @@ class CallOptionsTest { @DisplayName("Test using the DEFAULT CallOptions") fun testCreatingCallOptionsDEFAULT() { val callOptions = CallOptions.DEFAULT - assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout()) - assertTrue(callOptions.token().isEmpty) + assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) } @Test @DisplayName("Test creating CallOptions with only a token") fun testCreatingCallOptionsWithAToken() { - val callOptions = CallOptions.newBuilder() - .withToken("someToken") - .build() - assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout()) - assertTrue(callOptions.token().isPresent) - val token = callOptions.token().get() - assertEquals("someToken", token) + val callOptions = callOptions { + token = "someToken" + } + assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout) + assertTrue(callOptions.token.isNotEmpty()) + assertEquals("someToken", callOptions.token) } @Test @DisplayName("Test creating CallOptions with only an empty string token") fun testCreatingCallOptionsWithAnEmptyStringToken() { - val callOptions = CallOptions.newBuilder() - .withToken("") - .build() - assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout()) - assertTrue(callOptions.token().isEmpty) + val callOptions = callOptions { + token = "" + } + assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) } @Test @DisplayName("Test creating CallOptions with only a token with only spaces") fun testCreatingCallOptionsWithATokenWithOnlySpaces() { - val callOptions = CallOptions.newBuilder() - .withToken(" ") - .build() - assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout()) - assertTrue(callOptions.token().isEmpty) + val callOptions = callOptions { + token = " " + } + assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) } @Test @DisplayName("Test creating CallOptions with only a timeout") fun testCreatingCallOptionsWithATimeout() { - val callOptions = CallOptions.newBuilder() - .withTimeout(30) - .build() - assertEquals(30, callOptions.timeout()) - assertTrue(callOptions.token().isEmpty) + val callOptions = callOptions { + timeout = 30 + } + assertEquals(30, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) } @Test @DisplayName("Test creating CallOptions with a negative value timeout, expect the default timeout") fun testCreatingCallOptionsWithANegativeTimeout() { - val callOptions = CallOptions.newBuilder() - .withTimeout(-3) - .build() - assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout()) - assertTrue(callOptions.token().isEmpty) + val callOptions = callOptions { + timeout = -3 + } + assertEquals(CallOptions.TIMEOUT_DEFAULT, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) + } + + @Test + @DisplayName("Test creating CallOptions with a timeout of 0 is valid") + fun testCreatingCallOptionsWithATimeoutOfZero() { + val callOptions = callOptions { + timeout = 0 + } + assertEquals(0, callOptions.timeout) + assertTrue(callOptions.token.isEmpty()) } } diff --git a/src/test/kotlin/org/eclipse/uprotocol/rpc/RpcTest.kt b/src/test/kotlin/org/eclipse/uprotocol/rpc/RpcTest.kt index 7508fee..87648df 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/rpc/RpcTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/rpc/RpcTest.kt @@ -27,6 +27,7 @@ import com.google.protobuf.kotlin.toByteString import io.cloudevents.v1.proto.CloudEvent import kotlinx.coroutines.flow.* import kotlinx.coroutines.test.runTest +import org.eclipse.uprotocol.rpc.CallOptions.Companion.callOptions import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.v1.* import org.junit.jupiter.api.Assertions.* @@ -370,6 +371,6 @@ internal class RpcTest { } private fun buildUCallOptions(): CallOptions { - return CallOptions.newBuilder().build() + return callOptions { } } } \ No newline at end of file diff --git a/src/test/kotlin/org/eclipse/uprotocol/transport/validator/UAttributesValidatorTest.kt b/src/test/kotlin/org/eclipse/uprotocol/transport/validator/UAttributesValidatorTest.kt index d00421d..fa4eb34 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/transport/validator/UAttributesValidatorTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/transport/validator/UAttributesValidatorTest.kt @@ -20,9 +20,7 @@ */ package org.eclipse.uprotocol.transport.validator -import org.eclipse.uprotocol.transport.builder.UAttributesBuilder import org.eclipse.uprotocol.transport.validate.UAttributesValidator -import org.eclipse.uprotocol.uri.factory.UResourceFactory.createForRpcResponse import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.uuid.factory.UUIDV8 import org.eclipse.uprotocol.v1.* @@ -39,18 +37,21 @@ internal class UAttributesValidatorTest { @DisplayName("test fetching validator for valid types") fun test_fetching_validator_for_valid_types() { val publish: UAttributesValidator = UAttributesValidator.getValidator( - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + } ) assertEquals("UAttributesValidator.Publish", publish.toString()) val request: UAttributesValidator = UAttributesValidator.getValidator( - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + } ) assertEquals("UAttributesValidator.Request", request.toString()) val response: UAttributesValidator = UAttributesValidator.getValidator( - UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).build() + uAttributes { + forResponse(testSource, testSink, UPriority.UPRIORITY_CS4, UUIDV8()) + } ) assertEquals("UAttributesValidator.Response", response.toString()) } @@ -58,7 +59,9 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be published") fun test_validate_uAttributes_for_publish_message_payload() { - val attributes: UAttributes = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -69,9 +72,14 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published with all values") fun test_validate_uAttributes_for_publish_message_payload_all_values() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(1000).withSink(sink) - .withPermissionLevel(2).withCommStatus(3).withReqId(UUIDV8()) - .build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = 1000 + sink = testSink + permissionLevel = 2 + commstatus = 3 + reqid = UUIDV8() + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -81,10 +89,12 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be published with invalid type") fun test_validate_uAttributes_for_publish_message_payload_invalid_type() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS0, UUIDV8() - ).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS0, UUIDV8() + ) + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -95,7 +105,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published with invalid time to live") fun test_validate_uAttributes_for_publish_message_payload_invalid_ttl() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(-1).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -106,8 +119,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published with invalid sink") fun test_validate_uAttributes_for_publish_message_payload_invalid_sink() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withSink(UUri.getDefaultInstance()) - .build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + sink = UUri.getDefaultInstance() + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -118,7 +133,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published with invalid permission level") fun test_validate_uAttributes_for_publish_message_payload_invalid_permission_level() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withPermissionLevel(-42).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + permissionLevel = -42 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -129,7 +147,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published with invalid communication status") fun test_validate_uAttributes_for_publish_message_payload_invalid_communication_status() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withCommStatus(-42).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + commstatus = -42 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -141,10 +162,13 @@ internal class UAttributesValidatorTest { fun test_validate_uAttributes_for_publish_message_payload_invalid_request_id() { val uuidJava: java.util.UUID = java.util.UUID.randomUUID() val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withReqId(uUID { - msb = uuidJava.mostSignificantBits - lsb = uuidJava.leastSignificantBits - }).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + reqid = uUID { + msb = uuidJava.mostSignificantBits + lsb = uuidJava.leastSignificantBits + } + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -156,7 +180,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request") fun test_validate_uAttributes_for_rpc_request_message_payload() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + } + val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -167,8 +194,14 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with all values") fun test_validate_uAttributes_for_rpc_request_message_payload_all_values() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000).withPermissionLevel(2) - .withCommStatus(3).withReqId(UUIDV8()).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + permissionLevel = 2 + commstatus = 3 + reqid = UUIDV8() + + } + val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -178,10 +211,13 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with invalid type") fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_type() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).withTtl(1000).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + ttl = 1000 + } val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -192,7 +228,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with invalid time to live") fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_ttl() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, -1).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, -1) + } + val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -203,7 +242,9 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with invalid sink") fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_sink() { val attributes: UAttributes = - UAttributesBuilder.request(source, UUri.getDefaultInstance(), UPriority.UPRIORITY_CS4, 1000).build() + uAttributes { + forRequest(testSource, UUri.getDefaultInstance(), UPriority.UPRIORITY_CS4, 1000) + } val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -214,8 +255,11 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with invalid permission level") fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_permission_level() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000) - .withPermissionLevel(-42).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + permissionLevel = -42 + } + val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -226,8 +270,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC request with invalid communication " + "status") fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_communication_status() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000).withCommStatus(-42) - .build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + commstatus = -42 + } val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -239,12 +285,14 @@ internal class UAttributesValidatorTest { fun test_validate_uAttributes_for_rpc_request_message_payload_invalid_request_id() { val uuidJava: java.util.UUID = java.util.UUID.randomUUID() val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, 1000).withReqId(uUID { - msb = uuidJava.mostSignificantBits - lsb = uuidJava.leastSignificantBits + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, 1000) + reqid = uUID { + msb = uuidJava.mostSignificantBits + lsb = uuidJava.leastSignificantBits + } } - ).build() val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -255,10 +303,12 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response") fun test_validate_uAttributes_for_rpc_response_message_payload() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -268,10 +318,15 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with all values") fun test_validate_uAttributes_for_rpc_response_message_payload_all_values() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).withPermissionLevel(2).withCommStatus(3).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + permissionLevel = 2 + commstatus = 3 + + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isSuccess()) @@ -282,7 +337,9 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with invalid type") fun test_validate_uAttributes_for_rpc_response_message_payload_invalid_type() { val attributes: UAttributes = - UAttributesBuilder.notification(source, sink, UPriority.UPRIORITY_CS4).build() + uAttributes { + forNotification(testSource, testSink, UPriority.UPRIORITY_CS4) + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -292,10 +349,13 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with invalid time to live") fun test_validate_uAttributes_for_rpc_response_message_payload_invalid_ttl() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).withTtl(-1).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + ttl = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -308,13 +368,14 @@ internal class UAttributesValidatorTest { ) fun test_validate_uAttributes_for_rpc_response_message_payload_missing_sink_and_missing_requestId() { val attributes: UAttributes = - UAttributesBuilder.response( - source, - UUri.getDefaultInstance(), - UPriority.UPRIORITY_CS4, - UUID.getDefaultInstance() - ) - .build() + uAttributes { + forResponse( + testSource, + UUri.getDefaultInstance(), + UPriority.UPRIORITY_CS4, + UUID.getDefaultInstance() + ) + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -324,10 +385,13 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with invalid permission level") fun test_validate_uAttributes_for_rpc_response_message_payload_invalid_permission_level() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).withPermissionLevel(-42).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + permissionLevel = -42 + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -337,10 +401,13 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with invalid communication " + "status") fun test_validate_uAttributes_for_rpc_response_message_payload_invalid_communication_status() { - val attributes: UAttributes = UAttributesBuilder.response( - source, sink, - UPriority.UPRIORITY_CS4, UUIDV8() - ).withCommStatus(-42).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, testSink, + UPriority.UPRIORITY_CS4, UUIDV8() + ) + commstatus = -42 + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -351,8 +418,9 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be an RPC response with missing request id") fun test_validate_uAttributes_for_rpc_response_message_payload_missing_request_id() { val attributes: UAttributes = - UAttributesBuilder.response(source, sink, UPriority.UPRIORITY_CS4, UUID.getDefaultInstance()) - .build() + uAttributes { + forResponse(testSource, testSink, UPriority.UPRIORITY_CS4, UUID.getDefaultInstance()) + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -368,7 +436,7 @@ internal class UAttributesValidatorTest { lsb = uuidJava.leastSignificantBits } val attributes: UAttributes = - UAttributesBuilder.response(source, sink, UPriority.UPRIORITY_CS4, reqid).build() + uAttributes { forResponse(testSource, testSink, UPriority.UPRIORITY_CS4, reqid) } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() val status: ValidationResult = validator.validate(attributes) assertTrue(status.isFailure()) @@ -379,7 +447,9 @@ internal class UAttributesValidatorTest { @Test @DisplayName("Validate a UAttributes for payload that is meant to be published not expired") fun test_validate_uAttributes_for_publish_message_payload_not_expired() { - val attributes: UAttributes = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertFalse(validator.isExpired(attributes)) } @@ -388,7 +458,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published not expired with ttl zero") fun test_validate_uAttributes_for_publish_message_payload_not_expired_with_ttl_zero() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(0).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = 0 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertFalse(validator.isExpired(attributes)) } @@ -397,7 +470,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published not expired with ttl") fun test_validate_uAttributes_for_publish_message_payload_not_expired_with_ttl() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(10000).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = 10000 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertFalse(validator.isExpired(attributes)) } @@ -406,7 +482,10 @@ internal class UAttributesValidatorTest { @DisplayName("Validate a UAttributes for payload that is meant to be published not expired with ttl") fun test_validate_uAttributes_for_publish_message_payload_with_negative_ttl() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(-1).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertFalse(validator.isExpired(attributes)) @@ -419,7 +498,10 @@ internal class UAttributesValidatorTest { ) fun test_validate_uAttributes_for_publish_message_payload_expired_with_ttl() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(1).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = 1 + } Thread.sleep(800) val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertTrue(validator.isExpired(attributes)) @@ -430,7 +512,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating publish invalid ttl attribute") fun test_validating_publish_invalid_ttl_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(-1).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateTtl(attributes) assertTrue(status.isFailure()) @@ -441,7 +526,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating publish valid ttl attribute") fun test_validating_valid_ttl_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withTtl(100).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + ttl = 100 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateTtl(attributes) assertEquals(ValidationResult.success(), status) @@ -452,7 +540,10 @@ internal class UAttributesValidatorTest { fun test_validating_invalid_sink_attribute() { val uri: UUri = LongUriSerializer.instance().deserialize("//") val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withSink(uri).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + sink = uri + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateSink(attributes) assertTrue(status.isFailure()) @@ -464,7 +555,10 @@ internal class UAttributesValidatorTest { fun test_validating_valid_sink_attribute() { val uri: UUri = LongUriSerializer.instance().deserialize("/haartley/1") val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withSink(uri).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + sink = uri + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateSink(attributes) assertEquals(ValidationResult.success(), status) @@ -475,10 +569,13 @@ internal class UAttributesValidatorTest { fun test_validating_invalid_ReqId_attribute() { val uuidJava: java.util.UUID = java.util.UUID.randomUUID() val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withReqId(uUID { - msb = uuidJava.mostSignificantBits - lsb = uuidJava.leastSignificantBits - }).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + reqid = uUID { + msb = uuidJava.mostSignificantBits + lsb = uuidJava.leastSignificantBits + } + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateReqId(attributes) assertTrue(status.isFailure()) @@ -488,8 +585,10 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test validating valid ReqId attribute") fun test_validating_valid_ReqId_attribute() { - val attributes: UAttributes = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0) - .withReqId(UUIDV8()).build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + reqid = UUIDV8() + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateReqId(attributes) assertEquals(ValidationResult.success(), status) @@ -499,7 +598,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating invalid PermissionLevel attribute") fun test_validating_invalid_PermissionLevel_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withPermissionLevel(-1).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + permissionLevel = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validatePermissionLevel(attributes) assertTrue(status.isFailure()) @@ -510,7 +612,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating valid PermissionLevel attribute") fun test_validating_valid_PermissionLevel_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withPermissionLevel(3).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + permissionLevel = 3 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validatePermissionLevel(attributes) assertEquals(ValidationResult.success(), status) @@ -520,7 +625,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating valid PermissionLevel attribute") fun test_validating_valid_PermissionLevel_attribute_invalid() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withPermissionLevel(0).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + permissionLevel = 0 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validatePermissionLevel(attributes) assertTrue(status.isFailure()) @@ -531,7 +639,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating invalid commstatus attribute") fun test_validating_invalid_commstatus_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withCommStatus(100).build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + commstatus = 100 + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateCommStatus(attributes) assertTrue(status.isFailure()) @@ -542,8 +653,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating valid commstatus attribute") fun test_validating_valid_commstatus_attribute() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withCommStatus(UCode.ABORTED_VALUE) - .build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + commstatus = UCode.ABORTED_VALUE + } val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() val status: ValidationResult = validator.validateCommStatus(attributes) assertEquals(ValidationResult.success(), status) @@ -553,7 +666,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating request message types") fun test_validating_request_message_types() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS6, 100).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS6, 100) + } + val validator: UAttributesValidator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Request", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -564,7 +680,9 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test validating request validator using wrong messagetype") fun test_validating_request_validator_with_wrong_messagetype() { - val attributes: UAttributes = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS6).build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS6) + } val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() assertEquals("UAttributesValidator.Request", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -575,10 +693,13 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test validating request validator using bad ttl") fun test_validating_request_validator_with_wrong_bad_ttl() { - val attributes: UAttributes = UAttributesBuilder.request( - source, LongUriSerializer.instance().deserialize("/hartley/1/rpc.response"), - UPriority.UPRIORITY_CS6, -1 - ).build() + val attributes: UAttributes = uAttributes { + forRequest( + testSource, LongUriSerializer.instance().deserialize("/hartley/1/rpc.response"), + UPriority.UPRIORITY_CS6, -1 + ) + } + val validator: UAttributesValidator = UAttributesValidator.Validators.REQUEST.validator() assertEquals("UAttributesValidator.Request", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -589,12 +710,15 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test validating response validator using bad ttl") fun test_validating_response_validator_with_wrong_bad_ttl() { - val attributes: UAttributes = UAttributesBuilder.response( - source, - LongUriSerializer.instance().deserialize("/hartley/1/rpc.response"), - UPriority.UPRIORITY_CS6, - UUIDV8() - ).withTtl(-1).build() + val attributes: UAttributes = uAttributes { + forResponse( + testSource, + LongUriSerializer.instance().deserialize("/hartley/1/rpc.response"), + UPriority.UPRIORITY_CS6, + UUIDV8() + ) + ttl = -1 + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() assertEquals("UAttributesValidator.Response", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -606,7 +730,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating publish validator with wrong messagetype") fun test_validating_publish_validator_with_wrong_messagetype() { val attributes: UAttributes = - UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS6, 1000).build() + uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS6, 1000) + } + val validator: UAttributesValidator = UAttributesValidator.Validators.PUBLISH.validator() assertEquals("UAttributesValidator.Publish", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -617,7 +744,9 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test validating response validator with wrong messagetype") fun test_validating_response_validator_with_wrong_messagetype() { - val attributes: UAttributes = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS6).build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS6) + } val validator: UAttributesValidator = UAttributesValidator.Validators.RESPONSE.validator() assertEquals("UAttributesValidator.Response", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -631,7 +760,10 @@ internal class UAttributesValidatorTest { @DisplayName("test validating request containing token") fun test_validating_request_containing_token() { val attributes: UAttributes = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS0).withToken("null").build() + uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS0) + token = "null" + } val validator: UAttributesValidator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Publish", validator.toString()) val status: ValidationResult = validator.validate(attributes) @@ -641,8 +773,11 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test_valid_request_methoduri_in_sink") fun test_valid_request_methoduri_in_sink() { - val sink = LongUriSerializer.instance().deserialize("/test.service/1/rpc.method") - val attributes = UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS0, 3000).build() + val testSink = LongUriSerializer.instance().deserialize("/test.service/1/rpc.method") + val attributes = uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS0, 3000) + } + val validator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Request", validator.toString()) val status = validator.validate(attributes) @@ -652,8 +787,11 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test_invalid_request_methoduri_in_sink") fun test_invalid_request_methoduri_in_sink() { - val sink = LongUriSerializer.instance().deserialize("/test.client/1/test.response") - val attributes = UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS0, 3000).build() + val testSink = LongUriSerializer.instance().deserialize("/test.client/1/test.response") + val attributes = uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS0, 3000) + } + val validator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Request", validator.toString()) val status = validator.validate(attributes) @@ -666,13 +804,15 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test_valid_response_uri_in_sink") fun test_valid_response_uri_in_sink() { - val sink = LongUriSerializer.instance().deserialize("/test.client/1/rpc.response") - val attributes = UAttributesBuilder.response( - source, - sink, - UPriority.UPRIORITY_CS0, - UUIDV8() - ).build() + val testSink = LongUriSerializer.instance().deserialize("/test.client/1/rpc.response") + val attributes = uAttributes { + forResponse( + testSource, + testSink, + UPriority.UPRIORITY_CS0, + UUIDV8() + ) + } val validator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Response", validator.toString()) val status = validator.validate(attributes) @@ -682,33 +822,39 @@ internal class UAttributesValidatorTest { @Test @DisplayName("test_invalid_response_uri_in_sink") fun test_invalid_response_uri_in_sink() { - val sink = LongUriSerializer.instance().deserialize("/test.client/1/rpc.method") - val attributes = UAttributesBuilder.response( - source, - sink, - UPriority.UPRIORITY_CS0, - UUIDV8() - ).build() + val testSink = LongUriSerializer.instance().deserialize("/test.client/1/rpc.method") + val attributes = uAttributes { + forResponse( + testSource, + testSink, + UPriority.UPRIORITY_CS0, + UUIDV8() + ) + } val validator = UAttributesValidator.getValidator(attributes) assertEquals("UAttributesValidator.Response", validator.toString()) val status = validator.validate(attributes) assertEquals("Invalid RPC response type.", status.getMessage()) } - private val sink = uUri { + private val testSink = uUri { authority = uAuthority { name = "vcu.someVin.veh.ultifi.gm.com" } entity = uEntity { name = "petapp.ultifi.gm.com" versionMajor = 1 } - resource = createForRpcResponse() + resource = uResource { + forRpcResponse() + } } - private val source: UUri = uUri { + private val testSource: UUri = uUri { entity = uEntity { name = "hartley_app" versionMajor = 1 } - resource = createForRpcResponse() + resource = uResource { + forRpcResponse() + } } } diff --git a/src/test/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactoryTest.kt b/src/test/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactoryTest.kt index ed37789..befbd4f 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactoryTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/uri/factory/UResourceFactoryTest.kt @@ -21,67 +21,82 @@ package org.eclipse.uprotocol.uri.factory -import org.eclipse.uprotocol.uri.factory.UResourceFactory.createForRpcRequest -import org.eclipse.uprotocol.uri.factory.UResourceFactory.createForRpcResponse -import org.eclipse.uprotocol.uri.factory.UResourceFactory.from +import org.eclipse.uprotocol.v1.forRpcRequest +import org.eclipse.uprotocol.v1.forRpcResponse +import org.eclipse.uprotocol.v1.from +import org.eclipse.uprotocol.v1.uResource import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.Test import kotlin.random.Random -class UResourceFactoryTest{ +class UResourceFactoryTest { @Test - fun test_forRpcResponse(){ - val resource = createForRpcResponse() + fun test_forRpcResponse() { + val resource = uResource { + forRpcResponse() + } assertEquals("rpc", resource.name) assertEquals("response", resource.instance) assertEquals(0, resource.id) } @Test - fun test_forRpcRequest_without_argu(){ - val resource = createForRpcRequest() + fun test_forRpcRequest_without_argu() { + val resource = uResource { + forRpcRequest() + } assertEquals("rpc", resource.name) assertEquals("", resource.instance) assertEquals(0, resource.id) } @Test - fun test_forRpcRequest_with_method(){ - val resource = createForRpcRequest(method = "test") + fun test_forRpcRequest_with_method() { + val resource = uResource { + forRpcRequest("test") + } assertEquals("rpc", resource.name) assertEquals("test", resource.instance) assertEquals(0, resource.id) } @Test - fun test_forRpcRequest_with_id(){ - val resource = createForRpcRequest(id = 999) + fun test_forRpcRequest_with_id() { + val resource = uResource { + forRpcRequest(id = 999) + } assertEquals("rpc", resource.name) assertEquals("", resource.instance) assertEquals(999, resource.id) } @Test - fun test_forRpcRequest(){ - val resource = createForRpcRequest(method = "test", id = 999) + fun test_forRpcRequest() { + val resource = uResource { + forRpcRequest(method = "test", id = 999) + } assertEquals("rpc", resource.name) assertEquals("test", resource.instance) assertEquals(999, resource.id) } @Test - fun test_fromId_valid_id(){ - val idTest= Random.nextInt(0,999) - val resource = from(idTest) + fun test_fromId_valid_id() { + val idTest = Random.nextInt(0, 999) + val resource = uResource { + from(idTest) + } assertEquals("rpc", resource.name) assertEquals("", resource.instance) assertEquals(idTest, resource.id) } @Test - fun test_fromId_invalid_id(){ - val idTest= Random.nextInt(1000,Int.MAX_VALUE) - val resource = from(idTest) + fun test_fromId_invalid_id() { + val idTest = Random.nextInt(1000, Int.MAX_VALUE) + val resource = uResource { + from(idTest) + } assertEquals("", resource.name) assertEquals("", resource.instance) assertEquals(idTest, resource.id) diff --git a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/LongUriSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/LongUriSerializerTest.kt index 86a3e05..eaa8b44 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/LongUriSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/LongUriSerializerTest.kt @@ -20,7 +20,6 @@ */ package org.eclipse.uprotocol.uri.serializer -import org.eclipse.uprotocol.uri.factory.UResourceFactory import org.eclipse.uprotocol.uri.validator.isEmpty import org.eclipse.uprotocol.uri.validator.isLongForm import org.eclipse.uprotocol.uri.validator.isRemote @@ -38,7 +37,7 @@ class LongUriSerializerTest { fun test_using_the_serializers() { val uri: UUri = uUri { entity = uEntity { name = "hartley" } - resource = UResourceFactory.createForRpcRequest("raise") + resource = uResource { forRpcRequest("raise") } } val strUri: String = LongUriSerializer.instance().serialize(uri) diff --git a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializerTest.kt index 91c7442..46c8278 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/MicroUriSerializerTest.kt @@ -21,7 +21,6 @@ package org.eclipse.uprotocol.uri.serializer import com.google.protobuf.ByteString -import org.eclipse.uprotocol.uri.factory.UResourceFactory import org.eclipse.uprotocol.uri.validator.isEmpty import org.eclipse.uprotocol.uri.validator.isMicroForm import org.eclipse.uprotocol.v1.* @@ -90,7 +89,7 @@ class MicroUriSerializerTest { fun test_serialize_uri_missing_ids() { val uri: UUri = uUri { entity = uEntity { name = "hartley" } - resource = UResourceFactory.createForRpcResponse() + resource = uResource { forRpcResponse() } } @@ -158,7 +157,7 @@ class MicroUriSerializerTest { id = 29999 versionMajor = 254 } - resource = UResourceFactory.createForRpcRequest(id = 99) + resource = uResource { forRpcRequest( id = 99) } } diff --git a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.kt index 57950ab..7aea902 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/uri/serializer/UriSerializerTest.kt @@ -22,7 +22,6 @@ package org.eclipse.uprotocol.uri.serializer import com.google.protobuf.ByteString import org.eclipse.uprotocol.core.usubscription.v3.Update -import org.eclipse.uprotocol.uri.factory.UResourceFactory import org.eclipse.uprotocol.uri.validator.isEmpty import org.eclipse.uprotocol.uri.validator.isMicroForm import org.eclipse.uprotocol.v1.* @@ -108,7 +107,9 @@ class UriSerializerTest { fun test_build_resolved_full_information() { val uUri = uUri { entity = uEntity { id = 0 } - resource = UResourceFactory.from(Update.Resources.subscriptions) + resource = uResource { + from(Update.Resources.subscriptions) + } } assertFalse(uUri.isEmpty()) assertTrue(uUri.isMicroForm()) diff --git a/src/test/kotlin/org/eclipse/uprotocol/uri/validator/UriValidatorTest.kt b/src/test/kotlin/org/eclipse/uprotocol/uri/validator/UriValidatorTest.kt index 2c9d7e1..5a5b27b 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/uri/validator/UriValidatorTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/uri/validator/UriValidatorTest.kt @@ -20,7 +20,6 @@ */ package org.eclipse.uprotocol.uri.validator -import org.eclipse.uprotocol.uri.factory.UResourceFactory import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.v1.* import org.eclipse.uprotocol.validation.ValidationResult @@ -515,7 +514,9 @@ internal class UriValidatorTest { fun test_valid_rpc_response_uri() { val uuri: UUri = uUri { entity = uEntity { name = "hartley" } - resource = UResourceFactory.createForRpcResponse() + resource = uResource { + forRpcResponse() + } } val status: ValidationResult = uuri.validateRpcResponse() @@ -526,7 +527,7 @@ internal class UriValidatorTest { @Test @DisplayName("Test invalid rpc response uri") @Throws(IOException::class) - fun test_invalid_rpc_response_uri(){ + fun test_invalid_rpc_response_uri() { val uuri: UUri = uUri { entity = uEntity { name = "hartley" } resource = uResource { @@ -573,9 +574,11 @@ internal class UriValidatorTest { @DisplayName("Test is Remote is false for URI without UAuthority") fun test_is_remote_is_false_for_uri_without_uauthority() { val uri = uUri { - authority = uAuthority { } + authority = uAuthority { } entity = uEntity { name = "hartley" } - resource = UResourceFactory.createForRpcResponse() + resource = uResource { + forRpcResponse() + } } assertFalse(UAuthority.getDefaultInstance().isRemote()) assertFalse(uri.authority.isRemote()) diff --git a/src/test/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilderTest.kt b/src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesBuilderTest.kt similarity index 64% rename from src/test/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilderTest.kt rename to src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesBuilderTest.kt index 856cc03..3447af2 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/transport/builder/UAttributesBuilderTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesBuilderTest.kt @@ -18,21 +18,19 @@ * specific language governing permissions and limitations * under the License. */ -package org.eclipse.uprotocol.transport.builder +package org.eclipse.uprotocol.v1 -import org.eclipse.uprotocol.uri.factory.UResourceFactory -import org.eclipse.uprotocol.v1.* import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Test -class UAttributesBuilderTest { +class UAttributesKtExtTest { @Test fun testPublish() { - val builder: UAttributesBuilder = UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS1) - assertNotNull(builder) - val attributes: UAttributes = builder.build() + val attributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS1) + } assertNotNull(attributes) assertEquals(UMessageType.UMESSAGE_TYPE_PUBLISH, attributes.type) assertEquals(UPriority.UPRIORITY_CS1, attributes.priority) @@ -40,65 +38,72 @@ class UAttributesBuilderTest { @Test fun testNotification() { - val builder: UAttributesBuilder = UAttributesBuilder.notification(source, sink, UPriority.UPRIORITY_CS1) - assertNotNull(builder) - val attributes: UAttributes = builder.build() + val attributes = uAttributes { + forNotification(testSource, testSink, UPriority.UPRIORITY_CS1) + } assertNotNull(attributes) assertEquals(UMessageType.UMESSAGE_TYPE_PUBLISH, attributes.type) assertEquals(UPriority.UPRIORITY_CS1, attributes.priority) - assertEquals(sink, attributes.sink) + assertEquals(testSink, attributes.sink) } @Test fun testRequest() { val ttl = 1000 - val builder: UAttributesBuilder = UAttributesBuilder.request(source, sink, UPriority.UPRIORITY_CS4, ttl) - assertNotNull(builder) - val attributes: UAttributes = builder.build() + val attributes: UAttributes = uAttributes { + forRequest(testSource, testSink, UPriority.UPRIORITY_CS4, ttl) + } assertNotNull(attributes) assertEquals(UMessageType.UMESSAGE_TYPE_REQUEST, attributes.type) assertEquals(UPriority.UPRIORITY_CS4, attributes.priority) - assertEquals(sink, attributes.sink) + assertEquals(testSink, attributes.sink) assertEquals(ttl, attributes.ttl) } @Test fun testResponse() { - val builder: UAttributesBuilder = UAttributesBuilder.response(source, sink, UPriority.UPRIORITY_CS6, uUID) - assertNotNull(builder) - val attributes: UAttributes = builder.build() + val attributes: UAttributes = uAttributes { + forResponse(testSource, testSink, UPriority.UPRIORITY_CS6, uUID) + } assertNotNull(attributes) assertEquals(UMessageType.UMESSAGE_TYPE_RESPONSE, attributes.type) assertEquals(UPriority.UPRIORITY_CS6, attributes.priority) - assertEquals(sink, attributes.sink) + assertEquals(testSink, attributes.sink) assertEquals(uUID, attributes.reqid) } @Test fun testBuild() { val reqId: UUID = uUID - val builder: UAttributesBuilder = - UAttributesBuilder.publish(source, UPriority.UPRIORITY_CS1).withTtl(1000).withToken("test_token") - .withSink(sink).withPermissionLevel(2).withCommStatus(1).withReqId(reqId) - val attributes: UAttributes = builder.build() + val attributes: UAttributes = uAttributes { + forPublication(testSource, UPriority.UPRIORITY_CS1) + ttl = 1000 + token = "test_token" + sink = testSink + permissionLevel = 2 + commstatus = 1 + reqid = reqId + traceparent = "test_traceparent" + } assertNotNull(attributes) assertEquals(UMessageType.UMESSAGE_TYPE_PUBLISH, attributes.type) assertEquals(UPriority.UPRIORITY_CS1, attributes.priority) assertEquals(1000, attributes.ttl) assertEquals("test_token", attributes.token) - assertEquals(sink, attributes.sink) + assertEquals(testSink, attributes.sink) assertEquals(2, attributes.permissionLevel) assertEquals(1, attributes.commstatus) assertEquals(reqId, attributes.reqid) + assertEquals("test_traceparent",attributes.traceparent) } - private val sink = uUri { + private val testSink = uUri { authority = uAuthority { name = "vcu.someVin.veh.ultifi.gm.com" } entity = uEntity { name = "petapp.ultifi.gm.com" versionMajor = 1 } - resource = UResourceFactory.createForRpcResponse() + resource = uResource { forRpcResponse() } } @@ -109,11 +114,11 @@ class UAttributesBuilderTest { } - private val source: UUri = uUri { + private val testSource: UUri = uUri { entity = uEntity { name = "hartley_app" versionMajor = 1 } - resource = UResourceFactory.createForRpcResponse() + resource = uResource { forRpcResponse() } } } From 2fab1a04601d8599ac3689596aaad854fe5f06ea Mon Sep 17 00:00:00 2001 From: Keyi Xing Date: Mon, 11 Mar 2024 21:18:17 -0400 Subject: [PATCH 2/4] Remove commented code from unit test. --- .../cloudevent/serialize/CloudEventToJsonSerializerTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt index 300faa9..997eed3 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/serialize/CloudEventToJsonSerializerTest.kt @@ -57,7 +57,6 @@ internal class CloudEventToJsonSerializerTest { .withExtension("ttl", 3) .withExtension("priority", "CS1") val cloudEvent: CloudEvent = cloudEventBuilder.build() - //cloudEvent.getAttribute("traceparent") val bytes: ByteArray = serializer.serialize(cloudEvent) val jsonString = String(bytes, StandardCharsets.UTF_8) val expected = From 042ea4dda08208db2ff58235b85499d57588de3f Mon Sep 17 00:00:00 2001 From: Keyi Xing Date: Mon, 11 Mar 2024 22:04:02 -0400 Subject: [PATCH 3/4] Replace UPayloadBuilder with Kotlin DSL type safe builder functions. --- .../uprotocol/transport/UPayloadUtils.kt | 69 ++++++++++ .../transport/builder/UPayloadBuilder.kt | 89 ------------- .../eclipse/uprotocol/v1/UAttributesKtExt.kt | 8 +- .../org/eclipse/uprotocol/v1/UPayloadKtExt.kt | 50 ++++++++ .../cloudevent/factory/UCloudEventTest.kt | 3 +- .../uprotocol/transport/UPayloadUtilsTest.kt | 118 ++++++++++++++++++ ...BuilderTest.kt => UAttributesKtExtTest.kt} | 0 .../eclipse/uprotocol/v1/UPayloadKtExtTest.kt | 54 ++++++++ 8 files changed, 296 insertions(+), 95 deletions(-) create mode 100644 src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt delete mode 100644 src/main/kotlin/org/eclipse/uprotocol/transport/builder/UPayloadBuilder.kt create mode 100644 src/main/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExt.kt create mode 100644 src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt rename src/test/kotlin/org/eclipse/uprotocol/v1/{UAttributesBuilderTest.kt => UAttributesKtExtTest.kt} (100%) create mode 100644 src/test/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExtTest.kt diff --git a/src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt b/src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt new file mode 100644 index 0000000..1ef8839 --- /dev/null +++ b/src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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. + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2023 General Motors GTO LLC + * SPDX-License-Identifier: Apache-2.0 + */ +package org.eclipse.uprotocol.transport + +import com.google.protobuf.Any +import com.google.protobuf.Internal +import com.google.protobuf.InvalidProtocolBufferException +import com.google.protobuf.Message +import org.eclipse.uprotocol.v1.UPayload +import org.eclipse.uprotocol.v1.UPayloadFormat + + +/** + * Unpack a uPayload into a google.protobuf.Message. + * + * @param payload the payload to unpack + * @param clazz the class of the message to unpack + * @return the unpacked message + */ +@Suppress("UNCHECKED_CAST") +fun unpack(payload: UPayload, clazz: Class): T? { + return try { + when (payload.format) { + UPayloadFormat.UNRECOGNIZED, UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY -> { + Any.parseFrom(payload.value).unpack(clazz) + } + + UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF -> { + val defaultInstance = Internal.getDefaultInstance(clazz) + defaultInstance.parserForType.parseFrom(payload.value) as T + } + + else -> null + } + } catch (e: InvalidProtocolBufferException) { + null + } +} + +/** + * Inline function to unpack a uPayload into a google.protobuf.Message. + * + * @return the unpacked message + */ +inline fun UPayload.unpack(): T? { + return unpack(this, T::class.java) +} + diff --git a/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UPayloadBuilder.kt b/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UPayloadBuilder.kt deleted file mode 100644 index b245877..0000000 --- a/src/main/kotlin/org/eclipse/uprotocol/transport/builder/UPayloadBuilder.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2024 General Motors GTO LLC - * - * 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. - * SPDX-FileType: SOURCE - * SPDX-FileCopyrightText: 2023 General Motors GTO LLC - * SPDX-License-Identifier: Apache-2.0 - */ -package org.eclipse.uprotocol.transport.builder - -import com.google.protobuf.Any -import com.google.protobuf.Internal -import com.google.protobuf.InvalidProtocolBufferException -import com.google.protobuf.Message -import org.eclipse.uprotocol.v1.UPayload -import org.eclipse.uprotocol.v1.UPayloadFormat -import org.eclipse.uprotocol.v1.uPayload - - -object UPayloadBuilder { - /** - * Build a uPayload from google.protobuf.Message by stuffing the message into an Any. - * - * @param message the message to pack - * @return the UPayload - */ - fun packToAny(message: Message): UPayload { - return uPayload { - format = UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY - value = Any.pack(message).toByteString() - } - } - - /** - * Build a uPayload from google.protobuf.Message using protobuf PayloadFormat. - * - * @param message the message to pack - * @return the UPayload - */ - fun pack(message: Message): UPayload = - uPayload { - format = UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF - value = message.toByteString() - } - - /** - * Unpack a uPayload into a google.protobuf.Message. - * - * @param payload the payload to unpack - * @param clazz the class of the message to unpack - * @return the unpacked message - */ - @Suppress("UNCHECKED_CAST") - fun unpack(payload: UPayload, clazz: Class): T? { - if (payload.value == null) { - return null - } - return try { - when (payload.format) { - UPayloadFormat.UNRECOGNIZED, UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY -> { - Any.parseFrom(payload.value).unpack(clazz) - } - UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF -> { - val defaultInstance = Internal.getDefaultInstance(clazz) - defaultInstance.parserForType.parseFrom(payload.value) as T - } - else -> null - } - } catch (e: InvalidProtocolBufferException) { - null - } - } - -} \ No newline at end of file diff --git a/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt b/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt index 9b22c27..475b0a8 100644 --- a/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt +++ b/src/main/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExt.kt @@ -30,7 +30,7 @@ import org.eclipse.uprotocol.uuid.factory.UUIDV8 * Construct a UAttributesBuilder for a publish message. * @param source Source address of the message. * @param priority The priority of the message. - * @return Returns the UAttributesBuilder with the configured priority. + * @return Returns the UAttributesBuilder with the configured source and priority. */ @JvmSynthetic fun UAttributesKt.Dsl.forPublication(source: UUri, priority: UPriority) { @@ -45,7 +45,7 @@ fun UAttributesKt.Dsl.forPublication(source: UUri, priority: UPriority) { * @param source Source address of the message. * @param sink The destination URI. * @param priority The priority of the message. - * @return Returns the UAttributesBuilder with the configured priority and sink. + * @return Returns the UAttributesBuilder with the configured source, sink and priority. */ @JvmSynthetic fun UAttributesKt.Dsl.forNotification(source: UUri, sink: UUri, priority: UPriority) { @@ -62,7 +62,7 @@ fun UAttributesKt.Dsl.forNotification(source: UUri, sink: UUri, priority: UPrior * @param sink The destination URI. * @param priority The priority of the message. * @param ttl The time to live in milliseconds. - * @return Returns the UAttributesBuilder with the configured priority, sink and ttl. + * @return Returns the UAttributesBuilder with the configured source, sink, priority and ttl. */ @JvmSynthetic fun UAttributesKt.Dsl.forRequest(source: UUri, sink: UUri, priority: UPriority, ttl: Int) { @@ -80,7 +80,7 @@ fun UAttributesKt.Dsl.forRequest(source: UUri, sink: UUri, priority: UPriority, * @param sink The destination URI. * @param priority The priority of the message. * @param reqId The original request UUID used to correlate the response to the request. - * @return Returns the UAttributesBuilder with the configured priority, sink and reqid. + * @return Returns the UAttributesBuilder with the configured source, sink, priority and reqid. */ @JvmSynthetic fun UAttributesKt.Dsl.forResponse(source: UUri, sink: UUri, priority: UPriority, reqId: UUID) { diff --git a/src/main/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExt.kt b/src/main/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExt.kt new file mode 100644 index 0000000..0eb0c65 --- /dev/null +++ b/src/main/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExt.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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. + * SPDX-FileType: SOURCE + * SPDX-FileCopyrightText: 2024 General Motors GTO LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.eclipse.uprotocol.v1 + +import com.google.protobuf.Any +import com.google.protobuf.Message + +/** + * Construct a UPayloadBuilder to pack google.protobuf.Message by stuffing the message into an Any. + * @param message the message to pack + * @return Returns the UPayloadBuilder with the configured format and value. + */ +@JvmSynthetic +fun UPayloadKt.Dsl.packToAny(message: Message) { + format = UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY + value = Any.pack(message).toByteString() +} + +/** + * Construct a UPayloadBuilder to pack google.protobuf.Message using protobuf PayloadFormat. + * @param message the message to pack + * @return Returns the UPayloadBuilder with the configured format and value. + */ +@JvmSynthetic +fun UPayloadKt.Dsl.pack(message: Message) { + format = UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF + value = message.toByteString() +} \ No newline at end of file diff --git a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt index d601dfa..983f904 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/cloudevent/factory/UCloudEventTest.kt @@ -25,7 +25,6 @@ import com.google.protobuf.InvalidProtocolBufferException import io.cloudevents.CloudEvent import io.cloudevents.CloudEventData import io.cloudevents.core.builder.CloudEventBuilder -import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes import org.eclipse.uprotocol.cloudevent.datamodel.UCloudEventAttributes.Companion.uCloudEventAttributes import org.eclipse.uprotocol.uri.serializer.LongUriSerializer import org.eclipse.uprotocol.uuid.factory.UUIDV8 @@ -705,7 +704,7 @@ internal class UCloudEventTest { @Test fun test_to_from_message_from_request_cloudevent_without_attributes() { // Additional attributes - val uCloudEventAttributes = UCloudEventAttributes.UCloudEventAttributesBuilder().build() + val uCloudEventAttributes = uCloudEventAttributes { } // CloudEvent val cloudEvent = CloudEventFactory.request( diff --git a/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt b/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt new file mode 100644 index 0000000..6c69090 --- /dev/null +++ b/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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.eclipse.uprotocol.transport + +import com.google.protobuf.Message +import org.junit.jupiter.api.Test + +import org.eclipse.uprotocol.v1.* +import kotlin.test.assertEquals +import kotlin.test.assertNull + +class UPayloadUtilsTest { + + @Test + fun test_unpack_with_UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY(){ + val message = uStatus { } + val payload = uPayload { + packToAny(message) + } + val result = unpack(payload, UStatus::class.java) + checkNotNull(result) + assertEquals(message, result) + } + + @Test + fun test_unpack_with_UPAYLOAD_FORMAT_PROTOBUF(){ + val message = uStatus { } + val payload = uPayload { + pack(message) + } + val result = unpack(payload, UStatus::class.java) + checkNotNull(result) + assertEquals(message, result) + } + + @Test + fun test_unpack_with_UPAYLOAD_FORMAT_RAW(){ + val message = uStatus { } + val payload = uPayload { + format = UPayloadFormat.UPAYLOAD_FORMAT_RAW + value = message.toByteString() + } + val result = unpack(payload, UStatus::class.java) + assertNull(result) + } + + @Test + fun test_unpack_but_InvalidProtocolBufferException(){ + val message = uStatus { } + val payload = uPayload { + packToAny(message) + } + val result = unpack(payload, UUri::class.java) + assertNull(result) + } + + @Test + fun test_inline_unpack_with_UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY(){ + val message = uStatus { } + val payload = uPayload { + packToAny(message) + } + val result = payload.unpack() + checkNotNull(result) + assertEquals(message, result) + } + + @Test + fun test_inline_unpack_with_UPAYLOAD_FORMAT_PROTOBUF(){ + val message = uStatus { } + val payload = uPayload { + pack(message) + } + val result = payload.unpack() + checkNotNull(result) + assertEquals(message, result) + } + + @Test + fun test_inline_unpack_with_UPAYLOAD_FORMAT_RAW(){ + val message = uStatus { } + val payload = uPayload { + format = UPayloadFormat.UPAYLOAD_FORMAT_RAW + value = message.toByteString() + } + val result = payload.unpack() + assertNull(result) + } + + @Test + fun test_inline_unpack_but_InvalidProtocolBufferException(){ + val message = uStatus { } + val payload = uPayload { + packToAny(message) + } + val result = payload.unpack() + assertNull(result) + } +} \ No newline at end of file diff --git a/src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesBuilderTest.kt b/src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExtTest.kt similarity index 100% rename from src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesBuilderTest.kt rename to src/test/kotlin/org/eclipse/uprotocol/v1/UAttributesKtExtTest.kt diff --git a/src/test/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExtTest.kt b/src/test/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExtTest.kt new file mode 100644 index 0000000..2ba2ed1 --- /dev/null +++ b/src/test/kotlin/org/eclipse/uprotocol/v1/UPayloadKtExtTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 General Motors GTO LLC + * + * 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.eclipse.uprotocol.v1 + +import com.google.protobuf.Any +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Test + + +class UPayloadKtExtTest { + @Test + fun testPackToAny() { + val uStatus = uStatus { } + val uPayload = uPayload { + packToAny(uStatus) + } + assertNotNull(uPayload) + assertEquals(UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY, uPayload.format) + assertEquals( + Any.pack(uStatus).toByteString(), + uPayload.value + ) + } + + @Test + fun testPack() { + val uStatus = uStatus { } + val uPayload = uPayload { + pack(uStatus) + } + assertNotNull(uPayload) + assertEquals(UPayloadFormat.UPAYLOAD_FORMAT_PROTOBUF, uPayload.format) + assertEquals(uStatus.toByteString(), uPayload.value) + } +} From 0ed2e52b0be0c0d552acc8d9169c098d4b382247 Mon Sep 17 00:00:00 2001 From: Keyi Xing Date: Wed, 13 Mar 2024 09:15:53 -0400 Subject: [PATCH 4/4] Rename UPayloadUtils.kt to UPayloadExt.kt --- .../uprotocol/transport/{UPayloadUtils.kt => UPayloadExt.kt} | 0 .../transport/{UPayloadUtilsTest.kt => UPayloadExtTest.kt} | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) rename src/main/kotlin/org/eclipse/uprotocol/transport/{UPayloadUtils.kt => UPayloadExt.kt} (100%) rename src/test/kotlin/org/eclipse/uprotocol/transport/{UPayloadUtilsTest.kt => UPayloadExtTest.kt} (98%) diff --git a/src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt b/src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadExt.kt similarity index 100% rename from src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadUtils.kt rename to src/main/kotlin/org/eclipse/uprotocol/transport/UPayloadExt.kt diff --git a/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt b/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadExtTest.kt similarity index 98% rename from src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt rename to src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadExtTest.kt index 6c69090..69eaf0c 100644 --- a/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadUtilsTest.kt +++ b/src/test/kotlin/org/eclipse/uprotocol/transport/UPayloadExtTest.kt @@ -21,14 +21,13 @@ package org.eclipse.uprotocol.transport -import com.google.protobuf.Message import org.junit.jupiter.api.Test import org.eclipse.uprotocol.v1.* import kotlin.test.assertEquals import kotlin.test.assertNull -class UPayloadUtilsTest { +class UPayloadExtTest { @Test fun test_unpack_with_UPAYLOAD_FORMAT_PROTOBUF_WRAPPED_IN_ANY(){