diff --git a/CMakeSettings.json b/CMakeSettings.json index a22be684e..b0e226343 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,7 +1,7 @@ { "configurations": [ { - "name": "x64-Debug", + "name": "x64-DebugWithTests", "generator": "Ninja", "configurationType": "Debug", "inheritEnvironments": [ "msvc_x64_x64" ], diff --git a/sdk/core/azure-core/inc/context.hpp b/sdk/core/azure-core/inc/context.hpp index 5e9b95c5e..1b3fa13ea 100644 --- a/sdk/core/azure-core/inc/context.hpp +++ b/sdk/core/azure-core/inc/context.hpp @@ -21,6 +21,7 @@ namespace Azure { namespace Core { * @brief ContextValue exists as a substitute for variant which isn't available until C++17 */ class ContextValue { + public: enum class ContextValueType { Undefined, @@ -30,6 +31,7 @@ namespace Azure { namespace Core { UniquePtr }; + private: ContextValueType m_contextValueType; union { @@ -40,12 +42,23 @@ namespace Azure { namespace Core { }; public: - ContextValue() noexcept : m_contextValueType(ContextValueType::Undefined), m_b(false) {} +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 26495) +#endif + + ContextValue() noexcept : m_contextValueType(ContextValueType::Undefined) {} ContextValue(bool b) noexcept : m_contextValueType(ContextValueType::Bool), m_b(b) {} ContextValue(int i) noexcept : m_contextValueType(ContextValueType::Int), m_i(i) {} ContextValue(const std::string& s) : m_contextValueType(ContextValueType::StdString), m_s(s) {} - ContextValue(std::string&& s) noexcept - : m_contextValueType(ContextValueType::UniquePtr), m_s(std::move(s)) + + ContextValue(const char* s) + : m_contextValueType(ContextValueType::StdString), m_s(s) + { + } + + ContextValue(std::string&& s) + : m_contextValueType(ContextValueType::StdString), m_s(std::move(s)) { } @@ -74,6 +87,9 @@ namespace Azure { namespace Core { break; } } +#ifdef _MSC_VER +#pragma warning(pop) +#endif ~ContextValue() { diff --git a/sdk/core/azure-core/test/ut/CMakeLists.txt b/sdk/core/azure-core/test/ut/CMakeLists.txt index a1b67fe41..f7c5bb5d9 100644 --- a/sdk/core/azure-core/test/ut/CMakeLists.txt +++ b/sdk/core/azure-core/test/ut/CMakeLists.txt @@ -31,7 +31,7 @@ add_executable ( transport_adapter.cpp transport_adapter.hpp uuid.cpp - ) + context.cpp) target_link_libraries(${TARGET_NAME} PRIVATE azure-core) add_gtest(${TARGET_NAME}) diff --git a/sdk/core/azure-core/test/ut/context.cpp b/sdk/core/azure-core/test/ut/context.cpp new file mode 100644 index 000000000..ca76ad5e7 --- /dev/null +++ b/sdk/core/azure-core/test/ut/context.cpp @@ -0,0 +1,162 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include "gtest/gtest.h" + +#include "context.hpp" + +#include +#include +#include +#include + +using namespace Azure::Core; + +TEST(Context, Basic) +{ + Context context; + auto& valueT = context["key"]; + EXPECT_FALSE(context.HasKey("")); + EXPECT_FALSE(context.HasKey("key")); + + auto kind = valueT.Alternative(); + EXPECT_TRUE(kind == ContextValue::ContextValueType::Undefined); +} + +TEST(Context, BasicBool) +{ + Context context; + // New context from previous + auto c2 = context.WithValue("key", true); + auto& valueT = c2["key"]; + auto value = valueT.Get(); + EXPECT_TRUE(value == true); + + auto kind = valueT.Alternative(); + EXPECT_TRUE(kind == ContextValue::ContextValueType::Bool); +} + +TEST(Context, BasicInt) +{ + Context context; + // New context from previous + auto c2 = context.WithValue("key", 123); + auto& valueT = c2["key"]; + auto value = valueT.Get(); + EXPECT_TRUE(value == 123); + + auto kind = valueT.Alternative(); + EXPECT_TRUE(kind == ContextValue::ContextValueType::Int); +} + +TEST(Context, BasicStdString) +{ + std::string s("Test String"); + + Context context; + // New context from previous + auto c2 = context.WithValue("key", s); + auto& valueT = c2["key"]; + auto value = valueT.Get(); + EXPECT_TRUE(value == s); + + auto kind = valueT.Alternative(); + EXPECT_TRUE(kind == ContextValue::ContextValueType::StdString); +} + +TEST(Context, BasicChar) +{ + const char* str = "Test String"; + std::string s(str); + + Context context; + // New context from previous + auto c2 = context.WithValue("key", str); + auto& valueT = c2["key"]; + auto value = valueT.Get(); + EXPECT_TRUE(value == s); + + auto kind = valueT.Alternative(); + EXPECT_TRUE(kind == ContextValue::ContextValueType::StdString); +} + +TEST(Context, Alternative) +{ + Context context; + // New context from previous + auto c2 = context.WithValue("key", 123); + auto& valueT1 = c2["key"]; + auto& valueT2 = c2["otherKey"]; + + EXPECT_TRUE(valueT1.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(valueT2.Alternative() == ContextValue::ContextValueType::Undefined); +} + +TEST(Context, Chain) +{ + Context context; + // New context from previous + auto c2 = context.WithValue("c2", 123); + auto c3 = c2.WithValue("c3", 456); + auto c4 = c3.WithValue("c4", 789); + auto c5 = c4.WithValue("c5", "5"); + auto c6 = c5.WithValue("c6", "6"); + auto c7 = c6.WithValue("c7", "7"); + auto finalContext = c7.WithValue("finalContext", "Final"); + + auto& valueT2 = finalContext["c2"]; + auto& valueT3 = finalContext["c3"]; + auto& valueT4 = finalContext["c4"]; + auto& valueT5 = finalContext["c5"]; + auto& valueT6 = finalContext["c6"]; + auto& valueT7 = finalContext["c7"]; + auto& valueT8 = finalContext["finalContext"]; + auto& valueT9 = finalContext["otherKey"]; + + EXPECT_TRUE(valueT2.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(valueT3.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(valueT4.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(valueT5.Alternative() == ContextValue::ContextValueType::StdString); + EXPECT_TRUE(valueT6.Alternative() == ContextValue::ContextValueType::StdString); + EXPECT_TRUE(valueT7.Alternative() == ContextValue::ContextValueType::StdString); + EXPECT_TRUE(valueT8.Alternative() == ContextValue::ContextValueType::StdString); + EXPECT_TRUE(valueT9.Alternative() == ContextValue::ContextValueType::Undefined); + + auto value = valueT2.Get(); + EXPECT_TRUE(value == 123); + value = valueT3.Get(); + EXPECT_TRUE(value == 456); + value = valueT4.Get(); + EXPECT_TRUE(value == 789); + + auto str = valueT5.Get(); + EXPECT_TRUE(str == "5"); + str = valueT6.Get(); + EXPECT_TRUE(str == "6"); + str = valueT7.Get(); + EXPECT_TRUE(str == "7"); + + str = valueT8.Get(); + EXPECT_TRUE(str == "Final"); +} + +TEST(Context, MatchingKeys) +{ + Context context; + // New context from previous + auto c2 = context.WithValue("key", 123); + auto c3 = c2.WithValue("key", 456); + + auto& valueT2 = c2["key"]; + auto& valueT3 = c3["key"]; + auto& missing = c3["otherKey"]; + + EXPECT_TRUE(valueT2.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(valueT3.Alternative() == ContextValue::ContextValueType::Int); + EXPECT_TRUE(missing.Alternative() == ContextValue::ContextValueType::Undefined); + + auto value = valueT2.Get(); + EXPECT_TRUE(value == 123); + value = valueT3.Get(); + EXPECT_TRUE(value == 456); +}