public void PersistenceGenericTest(int statusCode, string timeToExecute, bool includeException, string payload)
        {
            Exception exception          = includeException ? new ApplicationException("ABC") : null;
            TimeSpan? timeToExecuteValue = null;

            var response = new SecretStoreResponse <string>
            {
                Exception     = exception,
                IsSuccessCode = statusCode >= 200 && statusCode < 300,
                StatusCode    = statusCode,
                Value         = payload
            };

            if (!string.IsNullOrWhiteSpace(timeToExecute))
            {
                timeToExecuteValue     = TimeSpan.Parse(timeToExecute);
                response.TimeToExecute = timeToExecuteValue;
            }

            Assert.IsTrue(response.Exception == exception, "Exception not expected value");
            Assert.IsTrue(response.StatusCode == statusCode, "Status Code not expected value");
            Assert.IsTrue(response.IsSuccessCode == (statusCode >= 200 && statusCode < 300), "Is Success code not expected value");
            Assert.IsTrue(response.Exception == exception, "Exception not expected value");
            Assert.IsTrue((response.TimeToExecute ?? TimeSpan.Zero) == (timeToExecuteValue ?? TimeSpan.Zero), "Time to execute not expected value");
            Assert.IsTrue(string.Equals(response.Value, payload, StringComparison.Ordinal), "The value was not the expected value");
            Assert.IsTrue(response == response.IsSuccessCode, "Implicit conversion is expected to be same as IsSuccessCode");

            string responseText = response;

            Assert.IsTrue(responseText == payload, "Conversion to string shoudl be the payload");
        }
        /// <inheritdoc />
        public async Task <SecretStoreResponse <string> > GetSecretAsync(string secretName, string version = null, CancellationToken cancellationToken = default)
        {
            Guard.NotNullOrWhitespace(nameof(secretName), secretName);

            var results = new SecretStoreResponse <string>();

            if (_secrets == null)
            {
                using (await _control.LockAsync(cancellationToken).ConfigureAwait(false))
                {
                    if (_secrets == null)
                    {
                        _secrets = _keyVault.GetSecretsClient(SecretClientOptions.ServiceVersion.V7_1);
                    }
                }
            }

            var secretResponse = await _secrets.GetAsync(secretName, version, cancellationToken).ConfigureAwait(false);

            results.Exception     = secretResponse.Exception;
            results.IsSuccessCode = secretResponse.IsSuccess;
            results.StatusCode    = secretResponse.HttpStatus;
            results.TimeToExecute = TimeSpan.FromMilliseconds(secretResponse.ElapsedMilliseconds);
            if (secretResponse.IsSuccess)
            {
                results.Value = secretResponse.Value.SecureStringToString();
            }

            return(results);
        }
        public void PersistenceTest(int statusCode, string timeToExecute, bool includeException)
        {
            Exception exception          = includeException ? new ApplicationException("ABC") : null;
            TimeSpan? timeToExecuteValue = null;

            var response = new SecretStoreResponse
            {
                Exception     = exception,
                IsSuccessCode = statusCode >= 200 && statusCode < 300,
                StatusCode    = statusCode
            };

            if (!string.IsNullOrWhiteSpace(timeToExecute))
            {
                timeToExecuteValue     = TimeSpan.Parse(timeToExecute);
                response.TimeToExecute = timeToExecuteValue;
            }

            Assert.IsTrue(response.Exception == exception, "Exception not expected value");
            Assert.IsTrue(response.StatusCode == statusCode, "Status Code not expected value");
            Assert.IsTrue(response.IsSuccessCode == (statusCode >= 200 && statusCode < 300), "Is Success code not expected value");
            Assert.IsTrue(response.Exception == exception, "Exception not expected value");
            Assert.IsTrue((response.TimeToExecute ?? TimeSpan.Zero) == (timeToExecuteValue ?? TimeSpan.Zero), "Time to execute not expected value");
            Assert.IsTrue(response == response.IsSuccessCode, "Implicit conversion is expected to be same as IsSuccessCode");
        }
        /// <inheritdoc />
        public async Task <SecretStoreResponse <T> > GetSecretAsync <T>(string secretName, string version = null, CancellationToken cancellationToken = default) where T : class
        {
            var response = new SecretStoreResponse <T>();
            SecretStoreResponse <string> secretStringResponse;

            try
            {
                secretStringResponse = await GetSecretAsync(secretName, version, cancellationToken).ConfigureAwait(false);

                if (secretStringResponse == null)
                {
                    response.Exception     = null;
                    response.TimeToExecute = TimeSpan.Zero;
                    response.StatusCode    = (int)HttpStatusCode.InternalServerError;
                }
                else
                {
                    response.Exception     = secretStringResponse.Exception;
                    response.TimeToExecute = secretStringResponse.TimeToExecute;

                    if (secretStringResponse.IsSuccessCode)
                    {
                        try
                        {
                            var json = Encoding.UTF8.GetString(Convert.FromBase64String(secretStringResponse.Value));
                            response.Value         = JsonConvert.DeserializeObject <T>(json);
                            response.StatusCode    = (int)HttpStatusCode.OK;
                            response.IsSuccessCode = true;
                        }
                        catch (Exception e)
                        {
                            response.Exception  = new ApplicationException("Error deserializing BASE 64 / UTF-8 encoded JSON", e);
                            response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        }
                    }
                    else
                    {
                        response.StatusCode = secretStringResponse.StatusCode;
                        response.Value      = default;
                    }
                }
            }
            catch (Exception e)
            {
                response.Exception     = e;
                response.TimeToExecute = TimeSpan.Zero;
                response.StatusCode    = (int)HttpStatusCode.InternalServerError;
            }

            return(response);
        }
        /// <inheritdoc />
        public async Task <SecretStoreResponse <X509Certificate2> > GetCertificateAsync(string certificateName, string version = null, CancellationToken cancellationToken = default)
        {
            Guard.NotNullOrWhitespace(nameof(certificateName), certificateName);

            var results = new SecretStoreResponse <X509Certificate2>();

            if (_certificates == null)
            {
                using (await _control.LockAsync(cancellationToken).ConfigureAwait(false))
                {
                    if (_certificates == null)
                    {
                        _certificates = _keyVault.GetCertificatesClient(CertificateClientOptions.ServiceVersion.V7_1);
                    }
                }
            }

            var certificateResponse = await _certificates.GetAsync(certificateName, version, cancellationToken).ConfigureAwait(false);

            if (certificateResponse.IsSuccess)
            {
                var secretId = certificateResponse.SecretId;

                var elements = secretId.AbsoluteUri.Split("/", StringSplitOptions.RemoveEmptyEntries);

                if (elements.Length > 2)
                {
                    try
                    {
                        var secretVersion = elements[elements.Length - 1];
                        var name          = elements[elements.Length - 2];

                        if (_secrets == null)
                        {
                            using (await _control.LockAsync(cancellationToken).ConfigureAwait(false))
                            {
                                if (_secrets == null)
                                {
                                    _secrets = _keyVault.GetSecretsClient(SecretClientOptions.ServiceVersion.V7_1);
                                }
                            }
                        }

                        var secretResponse = await _secrets.GetCertificateAsync(name, secretVersion, cancellationToken).ConfigureAwait(false);

                        results.Exception     = secretResponse.Exception;
                        results.IsSuccessCode = secretResponse.IsSuccess;
                        results.StatusCode    = secretResponse.HttpStatus;
                        results.TimeToExecute = TimeSpan.FromMilliseconds(secretResponse.ElapsedMilliseconds);
                        if (secretResponse.IsSuccess)
                        {
                            results.Value = secretResponse.Value;
                        }
                    }
                    catch (Exception e)
                    {
                        results.Exception     = e;
                        results.IsSuccessCode = false;
                        results.StatusCode    = (int)HttpStatusCode.ServiceUnavailable;
                        results.TimeToExecute = TimeSpan.FromMilliseconds(certificateResponse.ElapsedMilliseconds);
                    }
                }
            }
            else
            {
                results.Exception     = certificateResponse.Exception;
                results.IsSuccessCode = certificateResponse.IsSuccess;
                results.StatusCode    = certificateResponse.HttpStatus;
                results.TimeToExecute = TimeSpan.FromMilliseconds(certificateResponse.ElapsedMilliseconds);
            }

            return(results);
        }