From: Pawel Wasowski Date: Fri, 28 Feb 2020 13:43:19 +0000 (+0100) Subject: [Bluetooth] Add unit tests for UUID class X-Git-Tag: submit/tizen/20200324.115410~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F84%2F226284%2F1;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Bluetooth] Add unit tests for UUID class Change-Id: I28bcc5e0bc48eb613a9076e93e6d68abe27cdc13 Verification: tests build; pass rate: 100% Signed-off-by: Pawel Wasowski --- diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 3b03db59..3b980c6d 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -1202,6 +1202,7 @@ mkdir -p %{buildroot}%{crosswalk_extensions_path}/mobile %if "%{?tizen_ut_build}" == "1" mkdir -p %{buildroot}/usr/bin install -p -m 755 out/bin_mobile/webapi_common_tests %{buildroot}/usr/bin/ +install -p -m 755 out/bin_mobile/webapi_bluetooth_tests %{buildroot}/usr/bin/ %endif install -p -m 644 out/bin_mobile/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/mobile @@ -1230,6 +1231,14 @@ install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/mobile_e %if "%{?unified_build}" == "1" || "%{?profile}" == "wearable" mkdir -p %{buildroot}%{crosswalk_extensions_path}/wearable + +# tizen ut wearable +%if "%{?tizen_ut_build}" == "1" +mkdir -p %{buildroot}/usr/bin +install -p -m 755 out/bin_wearable/webapi_common_tests %{buildroot}/usr/bin/ +install -p -m 755 out/bin_wearable/webapi_bluetooth_tests %{buildroot}/usr/bin/ +%endif + install -p -m 644 out/bin_wearable/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/wearable # execute desc_gentool LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/wearable out/Default/desc_gentool \ @@ -1339,6 +1348,7 @@ fi %if "%{?tizen_ut_build}" == "1" %license GTEST.BSD-3-Clause /usr/bin/webapi_common_tests +/usr/bin/webapi_bluetooth_tests %endif # mobile-extension-emulator @@ -1382,6 +1392,13 @@ fi %{crosswalk_extensions_path}/wearable/plugins.json %manifest webapi-plugins.manifest +# UT files +%if "%{?tizen_ut_build}" == "1" +%license GTEST.BSD-3-Clause +/usr/bin/webapi_common_tests +/usr/bin/webapi_bluetooth_tests +%endif + # wearable-extension-emulator %ifarch %{ix86} x86_64 %post wearable-extension-emulator diff --git a/src/bluetooth/bluetooth_ut.gyp b/src/bluetooth/bluetooth_ut.gyp new file mode 100644 index 00000000..c3a13573 --- /dev/null +++ b/src/bluetooth/bluetooth_ut.gyp @@ -0,0 +1,41 @@ +{ + 'includes': [ + '../common/common.gypi', + ], + 'targets': [ + { + 'target_name': 'webapi_bluetooth_tests', + 'type': 'executable', + 'dependencies': [ + '../common/common.gyp:tizen_common' + ], + 'include_dirs': [ + '../googletest/include/', + '../googletest/', + '../googlemock/include/', + '../googlemock/' + ], + 'sources': [ + '../googletest/src/gtest-all.cc', + '../googlemock/src/gmock-all.cc', + 'ut/bluetooth_ut_extension.cc', + 'ut/uuid.cc', + 'uuid.cc', + 'bluetooth_util.cc', + 'ut/main.cc', + ], + 'libraries': [ + '-pthread' + ], + 'conditions': [ + ['tizen == 1', { + 'variables': { + 'packages': [ + 'capi-network-bluetooth' + ] + }, + }], + ], + }, + ], +} diff --git a/src/bluetooth/ut/bluetooth_ut_extension.cc b/src/bluetooth/ut/bluetooth_ut_extension.cc new file mode 100644 index 00000000..c3c694c3 --- /dev/null +++ b/src/bluetooth/ut/bluetooth_ut_extension.cc @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ +#include "bluetooth/ut/bluetooth_ut_extension.h" + +common::Extension* CreateExtension() { + return new BluetoothUtExtension; +} + +BluetoothUtExtension::BluetoothUtExtension() { + SetExtensionName("bluetooth"); + SetJavaScriptAPI(""); +} + +BluetoothUtExtension::~BluetoothUtExtension() { +} diff --git a/src/bluetooth/ut/bluetooth_ut_extension.h b/src/bluetooth/ut/bluetooth_ut_extension.h new file mode 100644 index 00000000..052e8a8b --- /dev/null +++ b/src/bluetooth/ut/bluetooth_ut_extension.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ + +#ifndef TIZEN_BLUETOOTH_UT_EXTENSION_H_ +#define TIZEN_BLUETOOTH_UT_EXTENSION_H_ + +#include "common/extension.h" + +class BluetoothUtExtension : public common::Extension { + public: + BluetoothUtExtension(); + virtual ~BluetoothUtExtension(); +}; + +#endif // TIZEN_BLUETOOTH_UT_EXTENSION_H_ diff --git a/src/bluetooth/ut/main.cc b/src/bluetooth/ut/main.cc new file mode 100644 index 00000000..b209c4a5 --- /dev/null +++ b/src/bluetooth/ut/main.cc @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ + +#include "gtest/gtest.h" + +#include "bluetooth/ut/uuid.h" +#include "bluetooth/ut/uuid.h" + +int main(int argc, char* argv[]) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/bluetooth/ut/uuid.cc b/src/bluetooth/ut/uuid.cc new file mode 100644 index 00000000..05588461 --- /dev/null +++ b/src/bluetooth/ut/uuid.cc @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "bluetooth/bluetooth_util.h" +#include "bluetooth/ut/uuid.h" +#include "bluetooth/uuid.h" + +#include +#include +#include +#include + +#include "common/logger.h" +#include "common/platform_result.h" +#include "common/scope_exit.h" + +#if __cplusplus > 201402L +#include +using std::optional; +#else +#include "common/optional.h" +using common::optional; +#endif + +using namespace std; +using testing::_; +using testing::StrEq; +using testing::internal::ColoredPrintf; +using testing::internal::GTestColor; + +using namespace extension::bluetooth; +using namespace extension::bluetooth::util; + +class UUIDTest : public testing::Test { + protected: + virtual void SetUp() override { + invalid_uuids_ = { + "", "1", "12", "123", // less than 4 digits + "12345", "123456", "1234567", // less than 8 digits + "123456789", // more than 8 digits + "1ga2", "1%22", "1 abd", // invalid characters + "not_a_uuid_123", "09i0821AF7-30A0-1C00-8F0B-00805F9B34FB", + "09b0821AF7 30A0-1C00-8F0B-00805F9B34FB", + "109b0821AF7-30A0-1C00-8F0B-00805F9B34FB" // too long + "09A0821AF730A01C008F0B00805F9B34FB" // no hyphens + }; + + const std::string kTrailing96b = "-0000-1000-8000-00805f9b34fb"; + + valid_uuids_ = { + /* 16 bit UUIDs */ + UUIDFormats{"1ab2", "00001ab2" + kTrailing96b, "00001ab2"s, "1ab2"s}, + UUIDFormats{"0000", "00000000" + kTrailing96b, "00000000"s, "0000"s}, // zero + UUIDFormats{"0001", "00000001" + kTrailing96b, "00000001"s, "0001"s}, // leading zeros + UUIDFormats{"AabB", "0000aabb" + kTrailing96b, "0000aabb"s, "aabb"s}, // mixed case digits + UUIDFormats{"c1e0", "0000c1e0" + kTrailing96b, "0000c1e0"s, "c1e0"s}, // lower case digits + UUIDFormats{"C1E0", "0000c1e0" + kTrailing96b, "0000c1e0"s, "c1e0"s}, // upper case digits + + /* 32 bit UUIDs */ + UUIDFormats{"1ab203bd", "1ab203bd" + kTrailing96b, "1ab203bd"s, {}}, + UUIDFormats{"0001391f", "0001391f" + kTrailing96b, "0001391f"s, {}}, // leading zeros + UUIDFormats{"AabB1bDC", "aabb1bdc" + kTrailing96b, "aabb1bdc"s, {}}, // mixed case digits + UUIDFormats{"aabb1bdc", "aabb1bdc" + kTrailing96b, "aabb1bdc"s, {}}, // lower case digits + UUIDFormats{"AABB1BDC", "aabb1bdc" + kTrailing96b, "aabb1bdc"s, {}}, // upper case digits + + /* 128 bit-only UUIDs */ + UUIDFormats{"00000000-0000-0000-0000-000000000000", + "00000000-0000-0000-0000-000000000000", + {}, + {}}, // zero + UUIDFormats{"10821Af7-30a0-1C00-8f0B-00805f9B34Fb", + "10821af7-30a0-1c00-8f0b-00805f9b34fb", + {}, + {}}, // mixed case digits + UUIDFormats{"10821af7-30a0-1c00-8f0b-00805f9b34fb", + "10821af7-30a0-1c00-8f0b-00805f9b34fb", + {}, + {}}, // lower case digits + {"10821AF7-30A0-1C00-8F0B-00805F9B34FB", + "10821af7-30a0-1c00-8f0b-00805f9b34fb", + {}, + {}} // upper case digits + }; + } + + virtual void TearDown() override { + } + + static const int StringInit = 0; + static const int Format128 = 1; + static const int Format32 = 2; + static const int Format16 = 3; + + /* + * Values of the tuple are indexed with Init and Format* constant defined + * above. + * The values contain: + * StringInit: the argument passed to UUID constructor + * Format128: the valid value that should be stored in UUID::uuid_128_bit + * Format16: the valid value that should be returned by UUID::To16Bit() + * Format32: the valid value that should be returned by UUID::To32Bit() + */ + using UUIDFormats = std::tuple, // 32 bit + optional>; // 16 bit + std::vector valid_uuids_; + std::vector invalid_uuids_; + + struct BTHelper { + struct BTInitializationError : std::runtime_error { + using std::runtime_error::runtime_error; + }; + + BTHelper(const std::vector& valid_uuids) { + auto ret = bt_initialize(); + if (ret != BT_ERROR_NONE) { + throw BTInitializationError{"bt_initialize() failed: " + GetBluetoothErrorMessage(ret)}; + } + + auto adapter_state = BT_ADAPTER_DISABLED; + ret = bt_adapter_get_state(&adapter_state); + if (ret != BT_ERROR_NONE) { + throw BTInitializationError{"bt_adapter_get_state() failed: " + + GetBluetoothErrorMessage(ret)}; + } + + if (adapter_state == BT_ADAPTER_DISABLED) { + throw BTInitializationError{ + "Bluetooth adapter is disabled." + " Enable it before running tests."}; + } + + ret = bt_gatt_service_create(std::get(valid_uuids[0])->c_str(), + BT_GATT_SERVICE_TYPE_PRIMARY, &gatt_handle_16_bit); + if (ret != BT_ERROR_NONE) { + throw BTInitializationError{"Could not create bt_gatt_handle from 16 bit UUID: " + + GetBluetoothErrorMessage(ret)}; + } + + ret = bt_gatt_service_create(std::get(valid_uuids[0])->c_str(), + BT_GATT_SERVICE_TYPE_PRIMARY, &gatt_handle_32_bit); + if (ret != BT_ERROR_NONE) { + throw BTInitializationError{"Could not create bt_gatt_handle from 32 bit UUID: " + + GetBluetoothErrorMessage(ret)}; + } + + ret = bt_gatt_service_create(std::get(valid_uuids[0]).c_str(), + BT_GATT_SERVICE_TYPE_PRIMARY, &gatt_handle_128_bit); + if (ret != BT_ERROR_NONE) { + throw BTInitializationError{"Could not create bt_gatt_handle from 128 bit UUID: " + + GetBluetoothErrorMessage(ret)}; + } + } + + ~BTHelper() { + auto ret = bt_gatt_service_destroy(gatt_handle_16_bit); + if (ret != BT_ERROR_NONE) { + ColoredPrintf(GTestColor::COLOR_YELLOW, "Could not destroy gatt_handle_16_bit %s", + GetBluetoothErrorMessage(ret).c_str()); + } + + ret = bt_gatt_service_destroy(gatt_handle_32_bit); + if (ret != BT_ERROR_NONE) { + ColoredPrintf(GTestColor::COLOR_YELLOW, "Could not destroy gatt_handle_32_bit %s", + GetBluetoothErrorMessage(ret).c_str()); + } + + ret = bt_gatt_service_destroy(gatt_handle_128_bit); + if (ret != BT_ERROR_NONE) { + ColoredPrintf(GTestColor::COLOR_YELLOW, "Could not destroy gatt_handle_128_bit %s", + GetBluetoothErrorMessage(ret).c_str()); + } + + ret = bt_deinitialize(); + if (ret != BT_ERROR_NONE) { + ColoredPrintf(GTestColor::COLOR_YELLOW, "bt_deinitialize failed: %s", + GetBluetoothErrorMessage(ret).c_str()); + } + } + + bt_gatt_h gatt_handle_16_bit; + bt_gatt_h gatt_handle_32_bit; + bt_gatt_h gatt_handle_128_bit; + }; +}; + +TEST_F(UUIDTest, CreateFromString) { + ScopeLogger("CreateFromString"); + + for (const auto& uuid : valid_uuids_) { + auto uuid_obj = UUID::create(std::get(uuid)); + EXPECT_TRUE(uuid_obj) << "Failed for UUID: " << std::get(uuid); + } + + for (const auto& invalid_uuid : invalid_uuids_) { + auto uuid_obj = UUID::create(invalid_uuid); + EXPECT_FALSE(uuid_obj) << "Failed for UUID: " << invalid_uuid; + } +} + +TEST_F(UUIDTest, CreateFromCString) { + ScopeLogger("CreateFromCString"); + + for (const auto& uuid : valid_uuids_) { + auto uuid_obj = UUID::create(std::get(uuid).c_str()); + EXPECT_TRUE(uuid_obj) << "Failed for UUID: " << std::get(uuid).c_str(); + } + + for (const auto& invalid_uuid : invalid_uuids_) { + auto uuid_obj = UUID::create(invalid_uuid.c_str()); + EXPECT_FALSE(uuid_obj) << "Failed for UUID: " << invalid_uuid.c_str(); + } +} + +TEST_F(UUIDTest, CreateFromGATTHandle) { + ScopeLogger("CreateFromGATTHandle"); + + BTHelper bt_helper{valid_uuids_}; + + const auto valid_uuid_128_bit = std::get(valid_uuids_[0]); + + auto uuid_from_16_bit = UUID::createFromGatt(bt_helper.gatt_handle_16_bit); + ASSERT_TRUE(uuid_from_16_bit); + EXPECT_EQ(uuid_from_16_bit->uuid_128_bit, valid_uuid_128_bit); + + auto uuid_from_32_bit = UUID::createFromGatt(bt_helper.gatt_handle_32_bit); + ASSERT_TRUE(uuid_from_32_bit); + EXPECT_EQ(uuid_from_32_bit->uuid_128_bit, valid_uuid_128_bit); + + auto uuid_from_128_bit = UUID::createFromGatt(bt_helper.gatt_handle_128_bit); + ASSERT_TRUE(uuid_from_128_bit); + EXPECT_EQ(uuid_from_128_bit->uuid_128_bit, valid_uuid_128_bit); +} + +TEST_F(UUIDTest, ToXXXBits) { + for (const auto& uuid : valid_uuids_) { + auto uuid_obj = UUID::create(std::get(uuid)); + + /* Assert prevents the crash caused by referencing uuid_obj with no value */ + ASSERT_TRUE(uuid_obj) << "Failed for UUID: " << std::get(uuid); + + EXPECT_EQ(uuid_obj->To16Bit(), std::get(uuid)) + << "Failed for UUID: " << std::get(uuid) << " expected: (" + << (std::get(uuid) ? *std::get(uuid) : "") + ")" + << " got: (" << (uuid_obj->To16Bit() ? *uuid_obj->To16Bit() : "") + ")"; + EXPECT_EQ(uuid_obj->To32Bit(), std::get(uuid)) + << "Failed for UUID: " << std::get(uuid) << " expected: (" + << (std::get(uuid) ? *std::get(uuid) : "") + ")" + << " got: (" << (uuid_obj->To32Bit() ? *uuid_obj->To32Bit() : "") + ")"; + EXPECT_EQ(uuid_obj->uuid_128_bit, std::get(uuid)) + << "Failed for UUID: " << std::get(uuid) << " expected: (" + << std::get(uuid) << ")" + << " got: (" << uuid_obj->uuid_128_bit; + } +} + +TEST_F(UUIDTest, EqualsOperatorEqualUUIDs) { + const auto uuid_from_16_bit = UUID::create(*std::get(valid_uuids_[0])); + const auto uuid_from_32_bit = UUID::create(*std::get(valid_uuids_[0])); + const auto uuid_from_128_bit = UUID::create(std::get(valid_uuids_[0])); + + /* + * UUIDs created from strings of different lengths should all be equal. + */ + EXPECT_EQ(uuid_from_16_bit, uuid_from_16_bit); + EXPECT_EQ(uuid_from_16_bit, uuid_from_32_bit); + EXPECT_EQ(uuid_from_16_bit, uuid_from_128_bit); + EXPECT_EQ(uuid_from_32_bit, uuid_from_32_bit); + EXPECT_EQ(uuid_from_32_bit, uuid_from_128_bit); + EXPECT_EQ(uuid_from_128_bit, uuid_from_128_bit); +} + +TEST_F(UUIDTest, EqualsOperatorUnequalUUIDs) { + const auto uuid_A_from_16_bit = UUID::create(*std::get(valid_uuids_[0])); + const auto uuid_A_from_32_bit = UUID::create(*std::get(valid_uuids_[0])); + const auto uuid_A_from_128_bit = UUID::create(std::get(valid_uuids_[0])); + + const auto uuid_B_from_16_bit = UUID::create(*std::get(valid_uuids_[1])); + const auto uuid_B_from_32_bit = UUID::create(*std::get(valid_uuids_[1])); + const auto uuid_B_from_128_bit = UUID::create(std::get(valid_uuids_[1])); + + EXPECT_FALSE(uuid_A_from_16_bit == uuid_B_from_16_bit); + EXPECT_FALSE(uuid_A_from_16_bit == uuid_B_from_32_bit); + EXPECT_FALSE(uuid_A_from_16_bit == uuid_B_from_128_bit); + EXPECT_FALSE(uuid_A_from_32_bit == uuid_B_from_32_bit); + EXPECT_FALSE(uuid_A_from_32_bit == uuid_B_from_128_bit); + EXPECT_FALSE(uuid_A_from_128_bit == uuid_B_from_128_bit); +} + +TEST_F(UUIDTest, ShortestPossibleFormat) { + for (const auto& uuid : valid_uuids_) { + auto uuid_obj = UUID::create(std::get(uuid)); + + /* Assert prevents the crash caused by referencing uuid_obj with no value */ + ASSERT_TRUE(uuid_obj) << "Failed for UUID: " << std::get(uuid); + + const auto shortest_uuid_format = uuid_obj->ShortestPossibleFormat(); + if (std::get(uuid)) { + EXPECT_EQ(*std::get(uuid), shortest_uuid_format); + } else if (std::get(uuid)) { + EXPECT_EQ(*std::get(uuid), shortest_uuid_format); + } else { + EXPECT_EQ(std::get(uuid), shortest_uuid_format); + } + } +} diff --git a/src/bluetooth/ut/uuid.h b/src/bluetooth/ut/uuid.h new file mode 100644 index 00000000..9b9049ca --- /dev/null +++ b/src/bluetooth/ut/uuid.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed 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. + */ + +#ifndef BLUETOOTH_UT_UUID_H +#define BLUETOOTH_UT_UUID_H + +class UUIDTest; + +#endif // BLUETOOTH_UT_UUID_H diff --git a/src/tizen-wrt.gyp b/src/tizen-wrt.gyp index 78c12311..f3e10034 100755 --- a/src/tizen-wrt.gyp +++ b/src/tizen-wrt.gyp @@ -17,7 +17,8 @@ [ 'tizen_ut_build==1', { 'dependencies': [ - 'common/common_ut.gyp:*' + 'common/common_ut.gyp:*', + 'bluetooth/bluetooth_ut.gyp:*' ] } ],