diff --git a/source/v5/mqtt3_to_mqtt5_adapter.c b/source/v5/mqtt3_to_mqtt5_adapter.c index aa0d605a..670e80ee 100644 --- a/source/v5/mqtt3_to_mqtt5_adapter.c +++ b/source/v5/mqtt3_to_mqtt5_adapter.c @@ -1756,13 +1756,9 @@ static void s_aws_mqtt3_to_mqtt5_adapter_subscribe_completion_fn( if (subscribe_op->on_multi_suback != NULL) { AWS_VARIABLE_LENGTH_ARRAY( - uint8_t, - multi_sub_subscription_buf, - suback->reason_code_count * sizeof(struct aws_mqtt_topic_subscription)); + struct aws_mqtt_topic_subscription, multi_sub_subscription_buf, suback->reason_code_count); AWS_VARIABLE_LENGTH_ARRAY( - uint8_t, - multi_sub_subscription_ptr_buf, - suback->reason_code_count * sizeof(struct aws_mqtt_topic_subscription *)); + struct aws_mqtt_topic_subscription *, multi_sub_subscription_ptr_buf, suback->reason_code_count); struct aws_mqtt_topic_subscription *subscription_ptr = (struct aws_mqtt_topic_subscription *)multi_sub_subscription_buf; @@ -1894,6 +1890,8 @@ struct aws_mqtt3_to_mqtt5_adapter_operation_subscribe *aws_mqtt3_to_mqtt5_adapte subscribe_op->on_suback = options->on_suback; subscribe_op->on_suback_user_data = options->on_suback_user_data; + subscribe_op->on_multi_suback = options->on_multi_suback; + subscribe_op->on_multi_suback_user_data = options->on_multi_suback_user_data; return subscribe_op; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5be49eb4..c2539001 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -385,7 +385,7 @@ add_test_case(mqtt3to5_adapter_publish_no_ack) add_test_case(mqtt3to5_adapter_publish_interrupted) add_test_case(mqtt3to5_adapter_subscribe_single_success) -#add_test_case(mqtt3to5_adapter_subscribe_multi_success) +add_test_case(mqtt3to5_adapter_subscribe_multi_success) #add_test_case(mqtt3to5_adapter_subscribe_single_failure) #add_test_case(mqtt3to5_adapter_subscribe_multi_failure) #add_test_case(mqtt3to5_adapter_subscribe_single_publish) diff --git a/tests/v5/mqtt3_to_mqtt5_adapter_tests.c b/tests/v5/mqtt3_to_mqtt5_adapter_tests.c index 35e67cc4..3c4cc1c7 100644 --- a/tests/v5/mqtt3_to_mqtt5_adapter_tests.c +++ b/tests/v5/mqtt3_to_mqtt5_adapter_tests.c @@ -2310,7 +2310,7 @@ static int s_mqtt3to5_adapter_subscribe_single_success_fn(struct aws_allocator * .type = AWS_MQTT3_OET_SUBSCRIBE_COMPLETE, .error_code = AWS_ERROR_SUCCESS, }}; - aws_array_list_init_static( + aws_array_list_init_static_from_initialized( &expected_events[0].granted_subscriptions, (void *)expected_subs, 1, @@ -2327,8 +2327,120 @@ static int s_mqtt3to5_adapter_subscribe_single_success_fn(struct aws_allocator * AWS_TEST_CASE(mqtt3to5_adapter_subscribe_single_success, s_mqtt3to5_adapter_subscribe_single_success_fn) +static void s_aws_mqtt3_to_mqtt5_adapter_test_fixture_record_subscribe_multi_complete( + struct aws_mqtt_client_connection *connection, + uint16_t packet_id, + const struct aws_array_list *topic_subacks, /* contains aws_mqtt_topic_subscription pointers */ + int error_code, + void *userdata) { + + struct aws_mqtt3_to_mqtt5_adapter_test_fixture *fixture = userdata; + + struct aws_mqtt3_operation_event operation_event = { + .type = AWS_MQTT3_OET_SUBSCRIBE_COMPLETE, + .error_code = error_code, + }; + + size_t granted_count = aws_array_list_length(topic_subacks); + + aws_array_list_init_dynamic( + &operation_event.granted_subscriptions, + fixture->mqtt5_fixture.allocator, + granted_count, + sizeof(struct aws_mqtt_topic_subscription)); + + for (size_t i = 0; i < granted_count; ++i) { + struct aws_mqtt_topic_subscription *granted_sub = NULL; + aws_array_list_get_at(topic_subacks, &granted_sub, i); + + /* + * technically it's not safe to persist the topic cursor but they way the tests are built, the cursor will stay + * valid until the events are checked (as long as we don't delete the subscription internally) + */ + aws_array_list_push_back(&operation_event.granted_subscriptions, (void *)granted_sub); + } + + aws_mutex_lock(&fixture->lock); + aws_array_list_push_back(&fixture->operation_events, &operation_event); + aws_mutex_unlock(&fixture->lock); + aws_condition_variable_notify_all(&fixture->signal); +} + +static int s_mqtt3to5_adapter_subscribe_multi_success_fn(struct aws_allocator *allocator, void *ctx) { + (void)ctx; + + aws_mqtt_library_init(allocator); + + struct mqtt5_client_test_options test_options; + aws_mqtt5_client_test_init_default_options(&test_options); + + test_options.server_function_table.packet_handlers[AWS_MQTT5_PT_SUBSCRIBE] = + s_mqtt5_mock_server_handle_subscribe_suback_success; + + struct aws_mqtt5_client_mqtt5_mock_test_fixture_options test_fixture_options = { + .client_options = &test_options.client_options, + .server_function_table = &test_options.server_function_table, + }; + + struct aws_mqtt3_to_mqtt5_adapter_test_fixture fixture; + ASSERT_SUCCESS(aws_mqtt3_to_mqtt5_adapter_test_fixture_init(&fixture, allocator, &test_fixture_options, NULL)); + + struct aws_mqtt_client_connection *connection = fixture.connection; + + struct aws_mqtt_connection_options connection_options; + s_init_adapter_connection_options_from_fixture(&connection_options, &fixture); + + connection_options.on_connection_complete = s_aws_mqtt3_to_mqtt5_adapter_test_fixture_record_connection_complete; + connection_options.user_data = &fixture; + + aws_mqtt_client_connection_connect(connection, &connection_options); + + s_wait_for_n_adapter_lifecycle_events(&fixture, AWS_MQTT3_LET_CONNECTION_COMPLETE, 1); + + struct aws_mqtt_topic_subscription subscriptions[] = { + { + .topic = aws_byte_cursor_from_c_str("topic/1"), + .qos = AWS_MQTT_QOS_AT_LEAST_ONCE, + }, + { + .topic = aws_byte_cursor_from_c_str("topic/2"), + .qos = AWS_MQTT_QOS_AT_MOST_ONCE, + }}; + + struct aws_array_list subscription_list; + aws_array_list_init_static_from_initialized( + &subscription_list, subscriptions, 2, sizeof(struct aws_mqtt_topic_subscription)); + + aws_mqtt_client_connection_subscribe_multiple( + connection, + &subscription_list, + s_aws_mqtt3_to_mqtt5_adapter_test_fixture_record_subscribe_multi_complete, + &fixture); + + s_wait_for_n_adapter_operation_events(&fixture, AWS_MQTT3_OET_SUBSCRIBE_COMPLETE, 1); + + struct aws_mqtt3_operation_event expected_events[] = {{ + .type = AWS_MQTT3_OET_SUBSCRIBE_COMPLETE, + .error_code = AWS_ERROR_SUCCESS, + }}; + aws_array_list_init_static_from_initialized( + &expected_events[0].granted_subscriptions, + (void *)subscriptions, + 2, + sizeof(struct aws_mqtt_topic_subscription)); + + s_aws_mqtt3_to_mqtt5_adapter_test_fixture_verify_operation_sequence( + &fixture, AWS_ARRAY_SIZE(expected_events), expected_events, AWS_ARRAY_SIZE(expected_events)); + + aws_mqtt3_to_mqtt5_adapter_test_fixture_clean_up(&fixture); + aws_mqtt_library_clean_up(); + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(mqtt3to5_adapter_subscribe_multi_success, s_mqtt3to5_adapter_subscribe_multi_success_fn) + /* -#add_test_case(mqtt3to5_adapter_subscribe_multi_success) #add_test_case(mqtt3to5_adapter_subscribe_single_failure) #add_test_case(mqtt3to5_adapter_subscribe_multi_failure) #add_test_case(mqtt3to5_adapter_subscribe_single_publish)