2017-05-18 05:02:48 +00:00
|
|
|
/*
|
|
|
|
* UUIDGenerationTest.cpp
|
|
|
|
*
|
|
|
|
* Copyright 2017 Amazon.com, Inc. or its affiliates. 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.
|
|
|
|
* A copy of the License is located at
|
|
|
|
*
|
|
|
|
* http://aws.amazon.com/apache2.0/
|
|
|
|
*
|
|
|
|
* or in the "license" file accompanying this file. This file 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 <string>
|
|
|
|
#include <future>
|
|
|
|
#include <vector>
|
|
|
|
#include <unordered_set>
|
|
|
|
#include <cctype>
|
2017-07-18 22:25:37 +00:00
|
|
|
#include <random>
|
2017-05-18 05:02:48 +00:00
|
|
|
|
|
|
|
#include <gmock/gmock.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include "AVSCommon/Utils/UUIDGeneration/UUIDGeneration.h"
|
|
|
|
|
|
|
|
namespace alexaClientSDK {
|
|
|
|
namespace avsCommon {
|
2017-06-23 23:26:34 +00:00
|
|
|
namespace test {
|
2017-05-18 05:02:48 +00:00
|
|
|
|
|
|
|
using namespace testing;
|
|
|
|
using namespace avsCommon::utils::uuidGeneration;
|
|
|
|
|
|
|
|
/// The version of the UUID generated.
|
|
|
|
static const std::string UUID_VERSION("4");
|
|
|
|
|
|
|
|
/// The variant of the UUID generated.
|
|
|
|
static const unsigned int UUID_VARIANT(8);
|
|
|
|
|
|
|
|
/// The offset of the UUID version in the string.
|
|
|
|
static const unsigned int UUID_VERSION_OFFSET(14);
|
|
|
|
|
|
|
|
/// The offset of the UUID variant in the string.
|
|
|
|
static const unsigned int UUID_VARIANT_OFFSET(19);
|
|
|
|
|
|
|
|
/// Hyphen.
|
|
|
|
static const std::string HYPHEN("-");
|
|
|
|
|
|
|
|
/// Position of first hyphen.
|
|
|
|
static const unsigned int HYPHEN1_POSITION(8);
|
|
|
|
|
|
|
|
/// Position of second hyphen.
|
|
|
|
static const unsigned int HYPHEN2_POSITION(13);
|
|
|
|
|
|
|
|
/// Position of third hyphen.
|
|
|
|
static const unsigned int HYPHEN3_POSITION(18);
|
|
|
|
|
|
|
|
/// Position of fourth hyphen.
|
|
|
|
static const unsigned int HYPHEN4_POSITION(23);
|
|
|
|
|
|
|
|
/// The length of the UUID string - 32 hexadecimal digits and 4 hyphens.
|
|
|
|
static const unsigned int UUID_LENGTH(36);
|
|
|
|
|
|
|
|
/// The maximum UUIDs to generate to test for uniqueness.
|
|
|
|
static const unsigned int MAX_UUIDS_TO_GENERATE(100);
|
|
|
|
|
|
|
|
/// The maximum threads to test with.
|
|
|
|
static const unsigned int MAX_TEST_THREADS(10);
|
|
|
|
|
2017-07-18 22:25:37 +00:00
|
|
|
/// The maximum number of retries.
|
|
|
|
static const unsigned int MAX_RETRIES(20);
|
|
|
|
|
2017-10-02 22:59:05 +00:00
|
|
|
class UUIDGenerationTest : public ::testing::Test {};
|
2017-05-18 05:02:48 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID and expect a string of length @c UUID_LENGTH.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testUUIDStringLength) {
|
|
|
|
ASSERT_EQ(UUID_LENGTH, generateUUID().length());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-06-23 23:26:34 +00:00
|
|
|
* Call @c generateUUID and expect a string of length @c UUID_LENGTH. Check that each character in the string
|
|
|
|
* is a hexedecimal number except for the hyphens.
|
|
|
|
*/
|
2017-05-18 05:02:48 +00:00
|
|
|
TEST_F(UUIDGenerationTest, testUUIDContainsOnlyHexCharacters) {
|
|
|
|
auto uuid = generateUUID();
|
|
|
|
ASSERT_EQ(UUID_LENGTH, uuid.length());
|
|
|
|
for (unsigned int i = 0; i < uuid.length(); i++) {
|
2017-06-23 23:26:34 +00:00
|
|
|
if (i == HYPHEN1_POSITION || i == HYPHEN2_POSITION || i == HYPHEN3_POSITION || i == HYPHEN4_POSITION) {
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(HYPHEN, uuid.substr(i, 1));
|
2017-05-18 05:02:48 +00:00
|
|
|
} else {
|
|
|
|
ASSERT_TRUE(isxdigit(uuid[i]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID and check that the version is set correctly.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testUUIDVersion) {
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(UUID_VERSION, generateUUID().substr(UUID_VERSION_OFFSET, 1));
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID and check the variant is set correctly.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testUUIDVariant) {
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(UUID_VARIANT, strtoul(generateUUID().substr(UUID_VARIANT_OFFSET, 1).c_str(), nullptr, 16) & UUID_VARIANT);
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID and check that the hyphens are in the right positions.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testUUIDHyphens) {
|
|
|
|
std::string uuid = generateUUID();
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(HYPHEN, uuid.substr(HYPHEN1_POSITION, 1));
|
|
|
|
ASSERT_EQ(HYPHEN, uuid.substr(HYPHEN2_POSITION, 1));
|
|
|
|
ASSERT_EQ(HYPHEN, uuid.substr(HYPHEN3_POSITION, 1));
|
|
|
|
ASSERT_EQ(HYPHEN, uuid.substr(HYPHEN4_POSITION, 1));
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID multiple times and check the version and variant are set correctly.
|
|
|
|
* Check for uniqueness of the UUIDs generated.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testMultipleRequests) {
|
|
|
|
std::unordered_set<std::string> uuidsGenerated;
|
|
|
|
|
2017-06-23 23:26:34 +00:00
|
|
|
for (unsigned int i = 0; i < MAX_UUIDS_TO_GENERATE; ++i) {
|
2017-05-18 05:02:48 +00:00
|
|
|
unsigned int prevSizeOfSet = uuidsGenerated.size();
|
|
|
|
auto uuid = generateUUID();
|
|
|
|
uuidsGenerated.insert(uuid);
|
|
|
|
ASSERT_EQ(UUID_LENGTH, uuid.length());
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(UUID_VERSION, uuid.substr(UUID_VERSION_OFFSET, 1));
|
|
|
|
ASSERT_EQ(UUID_VARIANT, strtoul(uuid.substr(UUID_VARIANT_OFFSET, 1).c_str(), nullptr, 16) & UUID_VARIANT);
|
|
|
|
ASSERT_EQ(prevSizeOfSet + 1, uuidsGenerated.size());
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Call @c generateUUID from multiple threads and check the version and variant are set correctly.
|
|
|
|
* Check for uniqueness of the UUIDs generated.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testMultipleConcurrentRequests) {
|
|
|
|
int no_of_threads = MAX_TEST_THREADS;
|
|
|
|
std::vector<std::future<std::string>> uuidRequesters;
|
|
|
|
std::unordered_set<std::string> uuidsGenerated;
|
|
|
|
|
2017-06-23 23:26:34 +00:00
|
|
|
for (int i = 0; i < no_of_threads; ++i) {
|
|
|
|
auto future = std::async(std::launch::async, [this]() { return generateUUID(); });
|
2017-05-18 05:02:48 +00:00
|
|
|
uuidRequesters.push_back(std::move(future));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& future : uuidRequesters) {
|
|
|
|
unsigned int prevSizeOfSet = uuidsGenerated.size();
|
|
|
|
auto uuid = future.get();
|
|
|
|
uuidsGenerated.insert(uuid);
|
|
|
|
ASSERT_EQ(UUID_LENGTH, uuid.length());
|
2017-10-02 22:59:05 +00:00
|
|
|
ASSERT_EQ(UUID_VERSION, uuid.substr(UUID_VERSION_OFFSET, 1));
|
|
|
|
ASSERT_EQ(UUID_VARIANT, strtoul(uuid.substr(UUID_VARIANT_OFFSET, 1).c_str(), nullptr, 16) & UUID_VARIANT);
|
|
|
|
ASSERT_EQ(prevSizeOfSet + 1, uuidsGenerated.size());
|
2017-05-18 05:02:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 22:25:37 +00:00
|
|
|
/**
|
|
|
|
* Call @c generateUUID and ensure all hex values are generated. Will retry @c MAX_RETRIES times.
|
|
|
|
*/
|
|
|
|
TEST_F(UUIDGenerationTest, testAllHexValuesGenerated) {
|
|
|
|
std::unordered_set<char> hexCharacters = {
|
2017-10-02 22:59:05 +00:00
|
|
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
2017-07-18 22:25:37 +00:00
|
|
|
for (unsigned int retry = 0; retry < MAX_RETRIES && !hexCharacters.empty(); retry++) {
|
|
|
|
std::string uuid = generateUUID();
|
2017-10-02 22:59:05 +00:00
|
|
|
for (const char& digit : uuid) {
|
2017-07-18 22:25:37 +00:00
|
|
|
hexCharacters.erase(digit);
|
|
|
|
if (hexCharacters.empty()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_TRUE(hexCharacters.empty());
|
|
|
|
}
|
|
|
|
|
2017-10-02 22:59:05 +00:00
|
|
|
} // namespace test
|
|
|
|
} // namespace avsCommon
|
|
|
|
} // namespace alexaClientSDK
|