From 4e9d9f56c4e393219d4e5f815b787944295043fa Mon Sep 17 00:00:00 2001 From: Jelani Date: Wed, 20 Jul 2016 16:12:39 -0700 Subject: [PATCH] Removed the requirement to always have a password if the username is available --- src/mqtt_codec.c | 8 +- .../mqtt_client_unittests.c | 32 ++++++++ .../mqtt_codec_unittests.c | 74 +++++++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/src/mqtt_codec.c b/src/mqtt_codec.c index e818dda..5575340 100644 --- a/src/mqtt_codec.c +++ b/src/mqtt_codec.c @@ -400,7 +400,7 @@ static int constructConnPayload(BUFFER_HANDLE ctrlPacket, const MQTT_CLIENT_OPTI { result = __LINE__; } - else if (usernameLen > 0 && passwordLen == 0) + else if (usernameLen == 0 && passwordLen > 0) { result = __LINE__; } @@ -440,8 +440,12 @@ static int constructConnPayload(BUFFER_HANDLE ctrlPacket, const MQTT_CLIENT_OPTI } if (usernameLen > 0) { - packet[CONN_FLAG_BYTE_OFFSET] |= USERNAME_FLAG | PASSWORD_FLAG; + packet[CONN_FLAG_BYTE_OFFSET] |= USERNAME_FLAG; byteutil_writeUTF(&iterator, mqttOptions->username, (uint16_t)usernameLen); + } + if (passwordLen > 0) + { + packet[CONN_FLAG_BYTE_OFFSET] |= PASSWORD_FLAG; byteutil_writeUTF(&iterator, mqttOptions->password, (uint16_t)passwordLen); } // TODO: Get the rest of the flags diff --git a/tests/mqtt_client_unittests/mqtt_client_unittests.c b/tests/mqtt_client_unittests/mqtt_client_unittests.c index 6f18e9c..f5fc53b 100644 --- a/tests/mqtt_client_unittests/mqtt_client_unittests.c +++ b/tests/mqtt_client_unittests/mqtt_client_unittests.c @@ -1452,6 +1452,38 @@ TEST_FUNCTION(mqtt_client_recvCompleteCallback_CONNACK_succeeds) mqtt_client_deinit(mqttHandle); } +/*Test_SRS_MQTT_CLIENT_07_028: [If the actionResult parameter is of type CONNECT_ACK then the msgInfo value shall be a CONNECT_ACK structure.]*/ +TEST_FUNCTION(mqtt_client_recvCompleteCallback_CONNACK_auth_reject_succeeds) +{ + // arrange + unsigned char CONNACK_RESP[] ={ 0x00, 0x05 }; + size_t length = sizeof(CONNACK_RESP) / sizeof(CONNACK_RESP[0]); + TEST_COMPLETE_DATA_INSTANCE testData; + + CONNECT_ACK connack = { 0 }; + connack.isSessionPresent = false; + connack.returnCode = CONN_REFUSED_NOT_AUTHORIZED; + testData.actionResult = MQTT_CLIENT_ON_CONNACK; + testData.msgInfo = &connack; + + MQTT_CLIENT_HANDLE mqttHandle = mqtt_client_init(TestRecvCallback, TestOpCallback, (void*)&testData); + umock_c_reset_all_calls(); + + BUFFER_HANDLE connack_handle = TEST_BUFFER_HANDLE; + STRICT_EXPECTED_CALL(BUFFER_length(TEST_BUFFER_HANDLE)).SetReturn(length); + STRICT_EXPECTED_CALL(BUFFER_u_char(TEST_BUFFER_HANDLE)).SetReturn(CONNACK_RESP); + + // act + g_packetComplete(mqttHandle, CONNACK_TYPE, 0, connack_handle); + + // assert + ASSERT_IS_TRUE(g_operationCallbackInvoked); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // cleanup + mqtt_client_deinit(mqttHandle); +} + /*Test_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/ TEST_FUNCTION(mqtt_client_recvCompleteCallback_PUBLISH_EXACTLY_ONCE_succeeds) { diff --git a/tests/mqtt_codec_unittests/mqtt_codec_unittests.c b/tests/mqtt_codec_unittests/mqtt_codec_unittests.c index 7a2404a..f3fe43b 100644 --- a/tests/mqtt_codec_unittests/mqtt_codec_unittests.c +++ b/tests/mqtt_codec_unittests/mqtt_codec_unittests.c @@ -362,6 +362,45 @@ TEST_FUNCTION(mqtt_codec_connect_succeeds) real_BUFFER_delete(handle); } +/* Tests_SRS_MQTT_CODEC_07_009: [mqtt_codec_connect shall construct a BUFFER_HANDLE that represents a MQTT CONNECT packet.] */ +TEST_FUNCTION(mqtt_codec_connect_no_password_succeeds) +{ + // arrange + MQTT_CLIENT_OPTIONS mqttOptions ={ 0 }; + SetupMqttLibOptions(&mqttOptions, TEST_CLIENT_ID, NULL, NULL, "testuser", NULL, 20, false, true, DELIVER_AT_MOST_ONCE); + + const unsigned char CONNECT_VALUE[] = { 0x10, 0x2a, 0x00, 0x04, 0x4d, 0x51, 0x54, 0x54, 0x04, 0x82, 0x00, 0x14, 0x00, 0x14, 0x73, 0x69, \ + 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x00, 0x08, 0x74, \ + 0x65, 0x73, 0x74, 0x75, 0x73, 0x65, 0x72, 0x00, 0x00 }; + + EXPECTED_CALL(BUFFER_new()); + EXPECTED_CALL(BUFFER_enlarge(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_enlarge(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_new()); + EXPECTED_CALL(BUFFER_pre_build(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_prepend(IGNORED_PTR_ARG, IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)); + + // act + BUFFER_HANDLE handle = mqtt_codec_connect(&mqttOptions); + + unsigned char* data = real_BUFFER_u_char(handle); + size_t length = BUFFER_length(handle); + + // assert + ASSERT_IS_NOT_NULL(handle); + ASSERT_ARE_EQUAL(int, 0, memcmp(data, CONNECT_VALUE, length)); + + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + real_BUFFER_delete(handle); +} + /* Tests_SRS_MQTT_CODEC_07_009: [mqtt_codec_connect shall construct a BUFFER_HANDLE that represents a MQTT CONNECT packet.] */ TEST_FUNCTION(mqtt_codec_connect_Large_Data_succeeds) { @@ -1198,6 +1237,41 @@ TEST_FUNCTION(mqtt_codec_bytesReceived_connack_succeed) mqtt_codec_destroy(handle); } +TEST_FUNCTION(mqtt_codec_bytesReceived_connack_auth_reject_succeed) +{ + // arrange + unsigned char CONNACK_RESP[] ={ 0x20, 0x2, 0x00, 0x05 }; + size_t length = sizeof(CONNACK_RESP) / sizeof(CONNACK_RESP[0]); + + TEST_COMPLETE_DATA_INSTANCE testData ={ 0 }; + testData.dataHeader = CONNACK_RESP + FIXED_HEADER_SIZE; + testData.Length = 2; + + MQTTCODEC_HANDLE handle = mqtt_codec_create(TestOnCompleteCallback, &testData); + + umock_c_reset_all_calls(); + + EXPECTED_CALL(BUFFER_new()); + EXPECTED_CALL(BUFFER_pre_build(IGNORED_PTR_ARG, IGNORED_NUM_ARG)); + EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_u_char(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_length(IGNORED_PTR_ARG)); + EXPECTED_CALL(BUFFER_delete(IGNORED_PTR_ARG)); + + g_curr_packet_type = CONNACK_TYPE; + + // act + mqtt_codec_bytesReceived(handle, CONNACK_RESP, length); + + // assert + ASSERT_IS_TRUE(g_callbackInvoked); + ASSERT_ARE_EQUAL(char_ptr, umock_c_get_expected_calls(), umock_c_get_actual_calls()); + + // cleanup + mqtt_codec_destroy(handle); +} + /* Codes_SRS_MQTT_CODEC_07_033: [mqtt_codec_bytesReceived constructs a sequence of bytes into the corresponding MQTT packets and on success returns zero.] */ /* Codes_SRS_MQTT_CODEC_07_034: [Upon a constructing a complete MQTT packet mqtt_codec_bytesReceived shall call the ON_PACKET_COMPLETE_CALLBACK function.] */ TEST_FUNCTION(mqtt_codec_bytesReceived_puback_succeed)