From 36ed1e18faf6a3c094539f2dcde54c3041e48cd9 Mon Sep 17 00:00:00 2001 From: Anton Kolesnyk <41349689+antkmsft@users.noreply.github.com> Date: Fri, 2 Apr 2021 00:32:43 +0000 Subject: [PATCH] Add live tests for Identity (#2011) --- sdk/identity/azure-identity/CMakeLists.txt | 6 +-- .../azure-identity/test/live/CMakeLists.txt | 43 +++++++++++++++++++ .../test/live/client_secret_credential.cpp | 22 ++++++++++ .../test/live/environment_credential.cpp | 27 ++++++++++++ .../azure-identity/test/live/getenv.hpp | 19 ++++++++ .../azure-identity/test/live/main.cpp | 34 +++++++++++++++ .../azure-identity/test/ut/CMakeLists.txt | 2 +- sdk/identity/ci.yml | 4 +- sdk/identity/test-resources.json | 40 +++++++++++++++++ 9 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 sdk/identity/azure-identity/test/live/CMakeLists.txt create mode 100644 sdk/identity/azure-identity/test/live/client_secret_credential.cpp create mode 100644 sdk/identity/azure-identity/test/live/environment_credential.cpp create mode 100644 sdk/identity/azure-identity/test/live/getenv.hpp create mode 100644 sdk/identity/azure-identity/test/live/main.cpp create mode 100644 sdk/identity/test-resources.json diff --git a/sdk/identity/azure-identity/CMakeLists.txt b/sdk/identity/azure-identity/CMakeLists.txt index 91f8bd311..cff17f83a 100644 --- a/sdk/identity/azure-identity/CMakeLists.txt +++ b/sdk/identity/azure-identity/CMakeLists.txt @@ -52,9 +52,8 @@ add_library(azure-identity ${AZURE_IDENTITY_HEADER} ${AZURE_IDENTITY_SOURCE}) # make sure that users can consume the project as a library. add_library(Azure::azure-identity ALIAS azure-identity) -# Uncomment once identity have tests -# coverage. Has no effect if BUILD_CODE_COVERAGE is OFF -# create_code_coverage(identity azure-identity azure-identity-test) +create_code_coverage(identity azure-identity azure-identity-test) +create_code_coverage(identity azure-identity-livetest azure-identity-livetest) target_include_directories( azure-identity @@ -82,6 +81,7 @@ if(BUILD_TESTING) enable_testing () endif() + add_subdirectory(test/live) add_subdirectory(test/ut) endif() diff --git a/sdk/identity/azure-identity/test/live/CMakeLists.txt b/sdk/identity/azure-identity/test/live/CMakeLists.txt new file mode 100644 index 000000000..50c0df467 --- /dev/null +++ b/sdk/identity/azure-identity/test/live/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# SPDX-License-Identifier: MIT + +cmake_minimum_required (VERSION 3.13) + +project (azure-identity-livetest LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +include(GoogleTest) + +add_executable ( + azure-identity-livetest + client_secret_credential.cpp + environment_credential.cpp + getenv.hpp + main.cpp +) + +if (MSVC) + # Disable warnings: + # - C26495: Variable + # - 'testing::internal::Mutex::critical_section_' + # - 'testing::internal::Mutex::critical_section_init_phase_' + # - 'testing::internal::Mutex::owner_thread_id_' + # - 'testing::internal::Mutex::type_' + # is uninitialized. Always initialize member variables (type.6). + # - C26812: The enum type + # - 'testing::internal::Mutex::StaticConstructorSelector' + # - 'testing::TestPartResult::Type' + # is unscoped. Prefer 'enum class' over 'enum' (Enum.3) + target_compile_options(azure-identity-livetest PUBLIC /wd6326 /wd26495 /wd26812) +endif() + +target_link_libraries(azure-identity-livetest PRIVATE azure-identity gtest gmock) + +# gtest_discover_tests will scan the test from azure-core-test and call add_test +# for each test to ctest. This enables `ctest -r` to run specific tests directly. +gtest_discover_tests(azure-identity-livetest + TEST_PREFIX azure-identity-livetest. + NO_PRETTY_TYPES + NO_PRETTY_VALUES +) diff --git a/sdk/identity/azure-identity/test/live/client_secret_credential.cpp b/sdk/identity/azure-identity/test/live/client_secret_credential.cpp new file mode 100644 index 000000000..ce75e2f23 --- /dev/null +++ b/sdk/identity/azure-identity/test/live/client_secret_credential.cpp @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include + +#include + +#include + +#include "getenv.hpp" + +TEST(ClientSecretCredential, Basic) +{ + Azure::Identity::ClientSecretCredential const credential( + GetEnv("AZURE_TENANT_ID"), GetEnv("AZURE_CLIENT_ID"), GetEnv("AZURE_CLIENT_SECRET")); + + auto const token = credential.GetToken( + {{"https://vault.azure.net/.default"}}, Azure::Core::Context::GetApplicationContext()); + + EXPECT_FALSE(token.Token.empty()); + EXPECT_GE(token.ExpiresOn, std::chrono::system_clock::now()); +} diff --git a/sdk/identity/azure-identity/test/live/environment_credential.cpp b/sdk/identity/azure-identity/test/live/environment_credential.cpp new file mode 100644 index 000000000..dd5e5cdb3 --- /dev/null +++ b/sdk/identity/azure-identity/test/live/environment_credential.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include + +#include + +#include + +#include "getenv.hpp" + +TEST(EnvironmentCredential, ClientSecret) +{ + // See EnvironmentCredential's documentation - these below are the environment variables it reads + // from. + EXPECT_FALSE(GetEnv("AZURE_TENANT_ID").empty()); + EXPECT_FALSE(GetEnv("AZURE_CLIENT_ID").empty()); + EXPECT_FALSE(GetEnv("AZURE_CLIENT_SECRET").empty()); + + Azure::Identity::EnvironmentCredential const credential; + + auto const token = credential.GetToken( + {{"https://vault.azure.net/.default"}}, Azure::Core::Context::GetApplicationContext()); + + EXPECT_FALSE(token.Token.empty()); + EXPECT_GE(token.ExpiresOn, std::chrono::system_clock::now()); +} diff --git a/sdk/identity/azure-identity/test/live/getenv.hpp b/sdk/identity/azure-identity/test/live/getenv.hpp new file mode 100644 index 000000000..4c1257833 --- /dev/null +++ b/sdk/identity/azure-identity/test/live/getenv.hpp @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include + +inline std::string GetEnv(std::string const& name) +{ +#if defined(_MSC_VER) +#pragma warning(push) +// warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s +// instead. +#pragma warning(disable : 4996) +#endif + auto const result = std::getenv(name.c_str()); + return result != nullptr ? result : ""; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +} diff --git a/sdk/identity/azure-identity/test/live/main.cpp b/sdk/identity/azure-identity/test/live/main.cpp new file mode 100644 index 000000000..485ac80f9 --- /dev/null +++ b/sdk/identity/azure-identity/test/live/main.cpp @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// SPDX-License-Identifier: MIT + +#include + +#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) +#include +#include +#include +#endif + +int main(int argc, char** argv) +{ +#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) + curl_global_init(CURL_GLOBAL_ALL); +#if defined(AZ_PLATFORM_POSIX) + // OpenSSL signals SIGPIPE when trying to clean an HTTPS closed connection. + // End users need to decide if SIGPIPE should be ignored or not. + signal(SIGPIPE, SIG_IGN); +#endif +#endif + + testing::InitGoogleTest(&argc, argv); + auto r = RUN_ALL_TESTS(); + +#if defined(BUILD_CURL_HTTP_TRANSPORT_ADAPTER) +#if defined(AZ_PLATFORM_POSIX) + // Cleaning ssl connections on Windows is broken until + // https://github.com/Azure/azure-sdk-for-cpp/pull/1500 is merged. + curl_global_cleanup(); +#endif +#endif + return r; +} diff --git a/sdk/identity/azure-identity/test/ut/CMakeLists.txt b/sdk/identity/azure-identity/test/ut/CMakeLists.txt index d67e924c1..f56333304 100644 --- a/sdk/identity/azure-identity/test/ut/CMakeLists.txt +++ b/sdk/identity/azure-identity/test/ut/CMakeLists.txt @@ -44,6 +44,6 @@ target_link_libraries(azure-identity-test PRIVATE azure-identity gtest gmock) # gtest_discover_tests will scan the test from azure-identity-test and call add_test # for each test to ctest. This enables `ctest -r` to run specific tests directly. gtest_discover_tests(azure-identity-test - TEST_PREFIX azure-identity. + TEST_PREFIX azure-identity-unittest. NO_PRETTY_TYPES NO_PRETTY_VALUES) diff --git a/sdk/identity/ci.yml b/sdk/identity/ci.yml index a693e1b90..432ac1d6c 100644 --- a/sdk/identity/ci.yml +++ b/sdk/identity/ci.yml @@ -31,8 +31,8 @@ stages: - template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml parameters: ServiceDirectory: identity - CtestRegex: azure-identity - Coverage: disabled + CtestRegex: azure-identity-unittest. + LiveTestCtestRegex: azure-identity-livetest. Artifacts: - Name: azure-identity Path: azure-identity diff --git a/sdk/identity/test-resources.json b/sdk/identity/test-resources.json new file mode 100644 index 000000000..b7d84ff61 --- /dev/null +++ b/sdk/identity/test-resources.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "tenantId": { + "type": "string", + "defaultValue": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "metadata": { + "description": "The tenant ID to which the application and resources belong." + } + }, + "testApplicationId": { + "type": "string", + "metadata": { + "description": "The application client ID used to run tests." + } + }, + "testApplicationSecret": { + "type": "string", + "metadata": { + "description": "The application client secret used to run tests." + } + } + }, + "resources": [], + "outputs": { + "AZURE_TENANT_ID": { + "type": "string", + "value": "[parameters('tenantId')]" + }, + "AZURE_CLIENT_ID": { + "type": "string", + "value": "[parameters('testApplicationId')]" + }, + "AZURE_CLIENT_SECRET": { + "type": "string", + "value": "[parameters('testApplicationSecret')]" + } + } +}