From d4a8372b03f1a0c4a1a7180782e1bd0d46d38e8e Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Mon, 9 Jan 2023 18:20:41 +0900 Subject: [PATCH] include/uipc: Implement uipc module as extension of ipc module The uipc module contains several functions that are identical with their ipc-counterpart. This kind of code-duplication can be avoided using the new interface/implements mechanism. This commit modifies the uipc module so that it extends the interface provided by the ipc module, reusing methods of the ipc module where possible. --- include/uipc.sh | 326 +--------------------------------------------- test/uipc_spec.sh | 198 ++++++++++++++++------------ 2 files changed, 119 insertions(+), 405 deletions(-) diff --git a/include/uipc.sh b/include/uipc.sh index 4b998ab..ccc0b47 100644 --- a/include/uipc.sh +++ b/include/uipc.sh @@ -31,7 +31,11 @@ __init() { return 0 } -_uipc_msg_get() { +uipc_get_root() { + echo "$__uipc_root" +} + +uipc_msg_get() { local msg="$1" local field="$2" @@ -50,7 +54,7 @@ _uipc_msg_version_supported() { local -i version - if ! version=$(uipc_msg_get_version "$msg"); then + if ! version=$(ipc_msg_get_version "$msg"); then log_error "Could not get version from message" return 1 fi @@ -85,7 +89,7 @@ EOF return 0 } -_uipc_msg_new() { +uipc_msg_new() { local source="$1" local destination="$2" local data="$3" @@ -125,319 +129,3 @@ _uipc_msg_new() { return 1 } - -uipc_msg_get_version() { - local msg="$1" - - local version - - if ! version=$(_uipc_msg_get "$msg" "version"); then - return 1 - fi - - echo "$version" - return 0 -} - -uipc_msg_get_source() { - local msg="$1" - - local src - - if ! src=$(_uipc_msg_get "$msg" "source"); then - return 1 - fi - - echo "$src" - return 0 -} - -uipc_msg_get_destination() { - local msg="$1" - - local dst - - if ! dst=$(_uipc_msg_get "$msg" "destination"); then - return 1 - fi - - echo "$dst" - return 0 -} - -uipc_msg_get_user() { - local msg="$1" - - local user - - if ! user=$(_uipc_msg_get "$msg" "user"); then - return 1 - fi - - echo "$user" - return 0 -} - -uipc_msg_get_timestamp() { - local msg="$1" - - local timestamp - - if ! timestamp=$(_uipc_msg_get "$msg" "timestamp"); then - return 1 - fi - - echo "$timestamp" - return 0 -} - -uipc_msg_get_data() { - local msg="$1" - - local data - local data_raw - - if ! data=$(_uipc_msg_get "$msg" "data"); then - return 1 - fi - - if ! data_raw=$(ipc_decode <<< "$data"); then - return 1 - fi - - echo "$data_raw" - return 0 -} - -uipc_msg_get_topic() { - local msg="$1" - - local topic - - if ! topic=$(_uipc_msg_get "$msg" "topic"); then - return 1 - fi - - echo "$topic" - return 0 -} - -uipc_endpoint_open() { - local name="$1" - - local endpoint - - if [[ -z "$name" ]]; then - local self - - self="${0##*/}" - name="priv/$USER.$self.$$.$(date +"%s").$RANDOM" - fi - - endpoint="$__uipc_root/$name" - - if ! [ -d "$endpoint" ]; then - if ! mkdir -p "$endpoint/subscriptions"; then - return 1 - fi - - if ! queue_init "$endpoint/queue" || - ! echo "$USER" > "$endpoint/owner" || - ! chmod -R g+rwxs "$endpoint"; then - if ! rm -rf "$endpoint"; then - log_error "Could not clean up $endpoint" - fi - - return 1 - fi - fi - - echo "$name" - return 0 -} - -uipc_endpoint_close() { - local name="$1" - - local endpoint - local subscription - - endpoint="$__uipc_root/$name" - - if ! queue_destroy "$endpoint/queue"; then - return 1 - fi - - while read -r subscription; do - if ! rm "$subscription/${name//\//_}"; then - log_error "Could not unsubscribe $name from $subscription" - fi - done < <(find "$endpoint/subscriptions" -mindepth 1 -maxdepth 1 -type l) - - if ! rm -rf "$endpoint"; then - return 1 - fi - - return 0 -} - -_uipc_endpoint_put() { - local endpoint="$1" - local msg="$2" - - local queue - - queue="$__uipc_root/$endpoint/queue" - - if ! queue_put "$queue" "$msg"; then - return 1 - fi - - return 0 -} - -uipc_endpoint_send() { - local source="$1" - local destination="$2" - local data="$3" - local topic="$4" - - local msg - - if ! msg=$(_uipc_msg_new "$source" "$destination" "$data" "$topic"); then - return 1 - fi - - if ! _uipc_endpoint_put "$destination" "$msg"; then - return 1 - fi - - return 0 -} - -uipc_endpoint_recv() { - local endpoint="$1" - local -i timeout="${2--1}" - - local queue - local msg - - queue="$__uipc_root/$endpoint/queue" - - if ! msg=$(queue_get "$queue" "$timeout"); then - return 1 - fi - - echo "$msg" - return 0 -} - -_uipc_endpoint_topic_create() { - local topic="$1" - - if ! mkdir -p "$__uipc_pubsub_root/$topic"; then - return 1 - fi - - return 0 -} - -_uipc_endpoint_topic_subscribe() { - local endpoint="$1" - local topic="$2" - - local topicdir - local subscription - - topicdir="$__uipc_pubsub_root/$topic" - subscription="$topicdir/${endpoint//\//_}" - - if ! ln -sf "$endpoint" "$subscription"; then - return 1 - fi - - if ! ln -sfn "$topicdir" "$__uipc_root/$endpoint/subscriptions/$topic"; then - rm -f "$subscription" - return 1 - fi - - return 0 -} - -_uipc_endpoint_topic_get_subscribers() { - local topic="$1" - - local subscription - - while read -r subscription; do - local subscriber - - if ! subscriber=$(readlink "$subscription"); then - continue - fi - - echo "$subscriber" - done < <(find "$__uipc_pubsub_root/$topic" -mindepth 1 -maxdepth 1 -type l) - - return 0 -} - -uipc_endpoint_subscribe() { - local endpoint="$1" - local topic="$2" - - if ! _uipc_endpoint_topic_create "$topic"; then - return 1 - fi - - if ! _uipc_endpoint_topic_subscribe "$endpoint" "$topic"; then - return 1 - fi - - return 0 -} - -uipc_endpoint_publish() { - local endpoint="$1" - local topic="$2" - local message="$3" - - local subscriber - - if ! _uipc_endpoint_topic_create "$topic"; then - return 1 - fi - - while read -r subscriber; do - uipc_endpoint_send "$endpoint" "$subscriber" "$message" "$topic" - done < <(_uipc_endpoint_topic_get_subscribers "$topic") - - return 0 -} - -_uipc_endpoint_foreach_message_helper() { - local msg="$1" - local endpoint="$2" - local func="$3" - local args=("${@:4}") - - "$func" "$endpoint" "$msg" "${args[@]}" - return "$?" -} - -uipc_endpoint_foreach_message() { - local endpoint="$1" - local func="$2" - local args=("${@:3}") - - local queue - - queue="$__uipc_root/$endpoint/queue" - - if ! queue_foreach "$queue" _uipc_endpoint_foreach_message_helper \ - "$endpoint" "$func" "${args[@]}"; then - return 1 - fi - - return 0 -} diff --git a/test/uipc_spec.sh b/test/uipc_spec.sh index d11c494..b7bf921 100644 --- a/test/uipc_spec.sh +++ b/test/uipc_spec.sh @@ -27,6 +27,32 @@ cleanup() { return 0 } +Describe "ipc_get_root()" + It "returns /var/lib/toolbox/uipc" + When call ipc_get_root + The stdout should equal "/var/lib/toolbox/uipc" + End + + It "returns the same value as uipc_get_root()" + _test_ipc_uipc_get_root_equal() { + local uipc_root + local ipc_root + + uipc_root=$(uipc_get_root) + ipc_root=$(ipc_get_root) + + if [[ "$uipc_root" != "$ipc_root" ]]; then + return 1 + fi + + return 0 + } + + When call _test_ipc_uipc_get_root_equal + The status should equal 0 + End +End + Describe "Encoding" It "ipc_encode() outputs base64" _test_encoding() { @@ -125,11 +151,11 @@ Describe "Message" BeforeAll 'setup' AfterAll 'cleanup' - It "_uipc_msg_new() outputs base64 encoded data" - _test_uipc_msg_new_is_base64() { + It "ipc_msg_new() outputs base64 encoded data" + _test_ipc_msg_new_is_base64() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi @@ -140,15 +166,15 @@ Describe "Message" return 0 } - When call _test_uipc_msg_new_is_base64 + When call _test_ipc_msg_new_is_base64 The status should equal 0 End - It "_uipc_msg_new() outputs an encoded JSON object" - _test_uipc_msg_new_is_json() { + It "_ipc_msg_new() outputs an encoded JSON object" + _test_ipc_msg_new_is_json() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi @@ -159,17 +185,17 @@ Describe "Message" return 0 } - When call _test_uipc_msg_new_is_json + When call _test_ipc_msg_new_is_json The status should equal 0 The stdout should match pattern '{*}' The stderr should not start with "parse error" End - It "_uipc_msg_new() generates valid toolbox.ipc.message objects" - _test_uipc_msg_new_json_schema_envelope() { + It "ipc_msg_new() generates valid toolbox.ipc.message objects" + _test_ipc_msg_new_json_schema_envelope() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi @@ -180,53 +206,53 @@ Describe "Message" return 0 } - When call _test_uipc_msg_new_json_schema_envelope + When call _test_ipc_msg_new_json_schema_envelope The status should equal 0 End - It "_uipc_msg_new()/uipc_msg_get_version() sets/gets the correct version" - _test_uipc_msg_new_version() { + It "ipc_msg_new()/ipc_msg_get_version() sets/gets the correct version" + _test_ipc_msg_new_version() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi - uipc_msg_get_version "$msg" + ipc_msg_get_version "$msg" } - When call _test_uipc_msg_new_version + When call _test_ipc_msg_new_version The status should equal 0 The stdout should equal "$__uipc_version" End - It "_uipc_msg_new()/uipc_msg_get_user() sets/gets the correct user" + It "ipc_msg_new()/ipc_msg_get_user() sets/gets the correct user" - _test_uipc_msg_new_user() { + _test_ipc_msg_new_user() { local msg - msg=$(_uipc_msg_new "from" "to" "data") + msg=$(ipc_msg_new "from" "to" "data") - uipc_msg_get_user "$msg" + ipc_msg_get_user "$msg" } - When call _test_uipc_msg_new_user + When call _test_ipc_msg_new_user The status should equal 0 The stdout should equal "$USER" End - It "_uipc_msg_new()/uipc_msg_get_timestamp() sets/gets the correct timestamp" - _test_uipc_msg_new_timestamp() { + It "ipc_msg_new()/ipc_msg_get_timestamp() sets/gets the correct timestamp" + _test_ipc_msg_new_timestamp() { local before local after local msg local timestamp before=$(date +"%s") - msg=$(_uipc_msg_new "from" "to" "data") + msg=$(ipc_msg_new "from" "to" "data") after=$(date +"%s") - timestamp=$(uipc_msg_get_timestamp "$msg") + timestamp=$(ipc_msg_get_timestamp "$msg") if (( timestamp < before )) || (( timestamp > after )); then @@ -236,62 +262,62 @@ Describe "Message" return 0 } - When call _test_uipc_msg_new_timestamp + When call _test_ipc_msg_new_timestamp The status should equal 0 End - It "_uipc_msg_new()/uipc_msg_get_source() sets/gets the correct source" - _test_uipc_msg_new_source() { + It "ipc_msg_new()/ipc_msg_get_source() sets/gets the correct source" + _test_ipc_msg_new_source() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi - uipc_msg_get_source "$msg" + ipc_msg_get_source "$msg" } - When call _test_uipc_msg_new_source + When call _test_ipc_msg_new_source The status should equal 0 The stdout should equal "from" End - It "_uipc_msg_new()/uipc_msg_get_destination() sets/gets the correct destination" - _test_uipc_msg_new_destination() { + It "ipc_msg_new()/ipc_msg_get_destination() sets/gets the correct destination" + _test_ipc_msg_new_destination() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi - uipc_msg_get_destination "$msg" + ipc_msg_get_destination "$msg" } - When call _test_uipc_msg_new_destination + When call _test_ipc_msg_new_destination The status should equal 0 The stdout should equal "to" End - It "_uipc_msg_new()/uipc_msg_get_data() sets/gets the correct data" - _test_uipc_msg_new_data() { + It "ipc_msg_new()/ipc_msg_get_data() sets/gets the correct data" + _test_ipc_msg_new_data() { local msg - if ! msg=$(_uipc_msg_new "from" "to" "data"); then + if ! msg=$(ipc_msg_new "from" "to" "data"); then return 1 fi - uipc_msg_get_data "$msg" + ipc_msg_get_data "$msg" } - When call _test_uipc_msg_new_data + When call _test_ipc_msg_new_data The status should equal 0 The stdout should equal "data" End End -Describe "uipc_endpoint_open" +Describe "ipc_endpoint_open" It "opens a public endpoint when the endpoint name is specified" - _test_uipc_endpoint_open_public() { + _test_ipc_endpoint_open_public() { local endpoint_name local endpoint local res @@ -299,143 +325,143 @@ Describe "uipc_endpoint_open" endpoint_name="pub/test$RANDOM" res=1 - if endpoint=$(uipc_endpoint_open "$endpoint_name"); then + if endpoint=$(ipc_endpoint_open "$endpoint_name"); then if [[ "$endpoint" != "priv/"* ]]; then res=0 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" fi return "$res" } - When call _test_uipc_endpoint_open_public + When call _test_ipc_endpoint_open_public The status should equal 0 End It "opens a private endpoint when no endpoint name is specified" - _test_uipc_endpoint_open_private() { + _test_ipc_endpoint_open_private() { local endpoint local res res=1 - if endpoint=$(uipc_endpoint_open); then + if endpoint=$(ipc_endpoint_open); then if [[ "$endpoint" == "priv/"* ]]; then res=0 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" fi return "$res" } - When call _test_uipc_endpoint_open_private + When call _test_ipc_endpoint_open_private The status should equal 0 End End -Describe "uipc_endpoint_close" +Describe "ipc_endpoint_close" It "closes a public endpoint" - _test_uipc_endpoint_close_public() { + _test_ipc_endpoint_close_public() { local endpoint - if ! endpoint=$(uipc_endpoint_open "pub/test$RANDOM"); then + if ! endpoint=$(ipc_endpoint_open "pub/test$RANDOM"); then return 1 fi - if ! uipc_endpoint_close "$endpoint"; then + if ! ipc_endpoint_close "$endpoint"; then return 1 fi return 0 } - When call _test_uipc_endpoint_close_public + When call _test_ipc_endpoint_close_public The status should equal 0 End It "closes a private endpoint" - _test_uipc_endpoint_close_private() { + _test_ipc_endpoint_close_private() { local endpoint - if ! endpoint=$(uipc_endpoint_open); then + if ! endpoint=$(ipc_endpoint_open); then return 1 fi - if ! uipc_endpoint_close "$endpoint"; then + if ! ipc_endpoint_close "$endpoint"; then return 1 fi return 0 } - When call _test_uipc_endpoint_close_private + When call _test_ipc_endpoint_close_private The status should equal 0 End End -Describe "uipc_endpoint_send" +Describe "ipc_endpoint_send" BeforeAll 'setup' AfterAll 'cleanup' It "sends a message to a public endpoint" - _test_uipc_endpoint_send_public() { + _test_ipc_endpoint_send_public() { local endpoint local res - if ! endpoint=$(uipc_endpoint_open "pub/test$RANDOM"); then + if ! endpoint=$(ipc_endpoint_open "pub/test$RANDOM"); then return 1 fi - if uipc_endpoint_send "-" "$endpoint" "data"; then + if ipc_endpoint_send "-" "$endpoint" "data"; then res=0 else res=1 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" return "$res" } - When call _test_uipc_endpoint_send_public + When call _test_ipc_endpoint_send_public The status should equal 0 End It "sends a message to a private endpoint" - _test_uipc_endpoint_send_private() { + _test_ipc_endpoint_send_private() { local endpoint local res - if ! endpoint=$(uipc_endpoint_open); then + if ! endpoint=$(ipc_endpoint_open); then return 1 fi - if uipc_endpoint_send "-" "$endpoint" "data"; then + if ipc_endpoint_send "-" "$endpoint" "data"; then res=0 else res=1 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" return "$res" } - When call _test_uipc_endpoint_send_private + When call _test_ipc_endpoint_send_private The status should equal 0 End End -Describe "uipc_endpoint_recv" +Describe "ipc_endpoint_recv" BeforeAll 'setup' AfterAll 'cleanup' It "receives messages on a public endpoint" - _test_uipc_endpoint_recv_public() { + _test_ipc_endpoint_recv_public() { local endpoint local res local txdata @@ -445,14 +471,14 @@ Describe "uipc_endpoint_recv" txdata="data$RANDOM" res=1 - if endpoint=$(uipc_endpoint_open "pub/test$RANDOM"); then - if ! uipc_endpoint_send "-" "$endpoint" "$txdata"; then + if endpoint=$(ipc_endpoint_open "pub/test$RANDOM"); then + if ! ipc_endpoint_send "-" "$endpoint" "$txdata"; then res=2 - elif ! msg=$(uipc_endpoint_recv "$endpoint" 10); then + elif ! msg=$(ipc_endpoint_recv "$endpoint" 10); then res=3 - elif ! rxdata=$(uipc_msg_get_data "$msg"); then + elif ! rxdata=$(ipc_msg_get_data "$msg"); then res=4 elif [[ "$rxdata" != "$txdata" ]]; then @@ -462,18 +488,18 @@ Describe "uipc_endpoint_recv" res=0 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" fi return "$res" } - When call _test_uipc_endpoint_recv_public + When call _test_ipc_endpoint_recv_public The status should equal 0 End It "receives messages on a private endpoint" - _test_uipc_endpoint_recv_private() { + _test_ipc_endpoint_recv_private() { local endpoint local res local txdata @@ -483,14 +509,14 @@ Describe "uipc_endpoint_recv" res=1 txdata="data$RANDOM" - if endpoint=$(uipc_endpoint_open); then - if ! uipc_endpoint_send "-" "$endpoint" "$txdata"; then + if endpoint=$(ipc_endpoint_open); then + if ! ipc_endpoint_send "-" "$endpoint" "$txdata"; then res=2 - elif ! msg=$(uipc_endpoint_recv "$endpoint"); then + elif ! msg=$(ipc_endpoint_recv "$endpoint"); then res=3 - elif ! rxdata=$(uipc_msg_get_data "$msg"); then + elif ! rxdata=$(ipc_msg_get_data "$msg"); then res=4 elif [[ "$rxdata" != "$txdata" ]]; then @@ -500,13 +526,13 @@ Describe "uipc_endpoint_recv" res=0 fi - uipc_endpoint_close "$endpoint" + ipc_endpoint_close "$endpoint" fi return "$res" } - When call _test_uipc_endpoint_recv_private + When call _test_ipc_endpoint_recv_private The status should equal 0 End End -- 2.47.3