* Copyright (c) 2026 Huawei Device Co., Ltd.
* 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 <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include "gtest/gtest.h"
#include "napi/native_api.h"
#include "napi/native_node_api.h"
#include "verify_cert_chain_context.h"
#include "net_ssl.h"
#include "securec.h"
#include "net_ssl_verify_cert.h"
#include "netstack_log.h"
namespace OHOS::NetStack::Ssl {
namespace {
class VerifyCertChainContextTest : public testing::Test {
public:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
virtual void SetUp() {}
virtual void TearDown() {}
};
HWTEST_F(VerifyCertChainContextTest, Constructor_001, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
EXPECT_EQ(context.GetInputCerts(), nullptr);
EXPECT_EQ(context.GetInputCertCount(), 0);
EXPECT_EQ(context.GetCaCert(), nullptr);
EXPECT_EQ(context.GetHostname(), nullptr);
EXPECT_EQ(context.GetSortedChain(), nullptr);
EXPECT_EQ(context.GetSortedChainCount(), 0);
}
HWTEST_F(VerifyCertChainContextTest, Destructor_NoLeak_002, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
{
VerifyCertChainContext context(env, manager);
}
EXPECT_TRUE(true);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorCode_ParseError_003, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(PARSE_ERROR_CODE);
EXPECT_EQ(context.GetErrorCode(), PARSE_ERROR_CODE);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorCode_SSLError_004, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(SSL_X509_V_ERR_CERT_HAS_EXPIRED);
EXPECT_EQ(context.GetErrorCode(), SSL_X509_V_ERR_CERT_HAS_EXPIRED);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorCode_Unspecified_005, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(999999);
EXPECT_EQ(context.GetErrorCode(), SSL_X509_V_ERR_UNSPECIFIED);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorCode_Success_006, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(0);
EXPECT_EQ(context.GetErrorCode(), 0);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorMessage_ParseError_007, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(PARSE_ERROR_CODE);
std::string msg = context.GetErrorMessage();
EXPECT_EQ(msg, PARSE_ERROR_MSG);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorMessage_KnownError_008, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(SSL_X509_V_ERR_CERT_HAS_EXPIRED);
std::string msg = context.GetErrorMessage();
EXPECT_FALSE(msg.empty());
std::string lowerMsg = msg;
std::transform(lowerMsg.begin(), lowerMsg.end(), lowerMsg.begin(), ::tolower);
EXPECT_NE(lowerMsg.find("expired"), std::string::npos);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorMessage_HostnameMismatch_009, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(SSL_X509_V_ERR_HOSTNAME_MISMATCH);
std::string msg = context.GetErrorMessage();
EXPECT_FALSE(msg.empty());
std::string lowerMsg = msg;
std::transform(lowerMsg.begin(), lowerMsg.end(), lowerMsg.begin(), ::tolower);
EXPECT_NE(lowerMsg.find("hostname"), std::string::npos);
}
HWTEST_F(VerifyCertChainContextTest, GetErrorMessage_Fallback_010, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(999999);
std::string msg = context.GetErrorMessage();
EXPECT_FALSE(msg.empty());
}
HWTEST_F(VerifyCertChainContextTest, AllErrorMessages_NonEmpty_011, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
std::vector<int32_t> errorCodes = {
SSL_NONE_ERR,
SSL_X509_V_ERR_UNSPECIFIED,
SSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT,
SSL_X509_V_ERR_UNABLE_TO_GET_CRL,
SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE,
SSL_X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE,
SSL_X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY,
SSL_X509_V_ERR_CERT_SIGNATURE_FAILURE,
SSL_X509_V_ERR_CRL_SIGNATURE_FAILURE,
SSL_X509_V_ERR_CERT_NOT_YET_VALID,
SSL_X509_V_ERR_CERT_HAS_EXPIRED,
SSL_X509_V_ERR_CRL_NOT_YET_VALID,
SSL_X509_V_ERR_CRL_HAS_EXPIRED,
SSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,
SSL_X509_V_ERR_CERT_REVOKED,
SSL_X509_V_ERR_INVALID_CA,
SSL_X509_V_ERR_CERT_UNTRUSTED,
SSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT,
SSL_X509_V_ERR_INVALID_CALL,
SSL_X509_V_ERR_HOSTNAME_MISMATCH
};
for (int32_t errorCode : errorCodes) {
VerifyCertChainContext context(env, manager);
context.SetErrorCode(errorCode);
std::string msg = context.GetErrorMessage();
EXPECT_FALSE(msg.empty()) << "Error code " << errorCode << " has empty message";
}
}
HWTEST_F(VerifyCertChainContextTest, SetGetSortedChain_012, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
CertBlob *chain = new CertBlob[2];
chain[0].type = CERT_TYPE_PEM;
chain[0].size = 100;
chain[0].data = new uint8_t[100];
if (memset_s(chain[0].data, 100, 0xAA, 100) != EOK) {
delete[] chain[0].data;
delete[] chain;
FAIL() << "memset_s failed";
return;
}
chain[1].type = CERT_TYPE_DER;
chain[1].size = 200;
chain[1].data = new uint8_t[200];
if (memset_s(chain[1].data, 200, 0xBB, 200) != EOK) {
delete[] chain[0].data;
delete[] chain[1].data;
delete[] chain;
FAIL() << "memset_s failed";
return;
}
context.SetSortedChain(chain, 2);
EXPECT_EQ(context.GetSortedChain(), chain);
EXPECT_EQ(context.GetSortedChainCount(), 2);
}
HWTEST_F(VerifyCertChainContextTest, SetSortedChain_Null_013, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetSortedChain(nullptr, 0);
EXPECT_EQ(context.GetSortedChain(), nullptr);
EXPECT_EQ(context.GetSortedChainCount(), 0);
}
HWTEST_F(VerifyCertChainContextTest, SetSortedChain_LargeCount_014, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
const size_t count = 50;
CertBlob *chain = new CertBlob[count];
for (size_t i = 0; i < count; i++) {
chain[i].type = CERT_TYPE_PEM;
chain[i].size = 10;
chain[i].data = new uint8_t[10];
}
context.SetSortedChain(chain, count);
EXPECT_EQ(context.GetSortedChainCount(), count);
}
HWTEST_F(VerifyCertChainContextTest, SetSortedChain_ZeroSized_015, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
CertBlob *chain = new CertBlob[1];
chain[0].type = CERT_TYPE_PEM;
chain[0].size = 0;
chain[0].data = nullptr;
context.SetSortedChain(chain, 1);
EXPECT_EQ(context.GetSortedChainCount(), 1);
}
HWTEST_F(VerifyCertChainContextTest, InputGetters_Default_016, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
EXPECT_EQ(context.GetInputCerts(), nullptr);
EXPECT_EQ(context.GetInputCertCount(), 0);
EXPECT_EQ(context.GetCaCert(), nullptr);
EXPECT_EQ(context.GetHostname(), nullptr);
}
HWTEST_F(VerifyCertChainContextTest, ErrorCodeSetMembership_017, testing::ext::TestSize.Level1)
{
EXPECT_NE(SslErrorCodeSetBase.find(SSL_NONE_ERR), SslErrorCodeSetBase.end());
EXPECT_NE(SslErrorCodeSetBase.find(SSL_X509_V_ERR_CERT_HAS_EXPIRED), SslErrorCodeSetBase.end());
EXPECT_NE(SslErrorCodeSetBase.find(SSL_X509_V_ERR_CERT_UNTRUSTED), SslErrorCodeSetBase.end());
EXPECT_NE(SslErrorCodeSetSinceAPI12.find(SSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT),
SslErrorCodeSetSinceAPI12.end());
EXPECT_NE(SslErrorCodeSetSinceAPI26.find(SSL_X509_V_ERR_HOSTNAME_MISMATCH),
SslErrorCodeSetSinceAPI26.end());
}
HWTEST_F(VerifyCertChainContextTest, MultipleErrorOverwrite_018, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(SSL_X509_V_ERR_CERT_HAS_EXPIRED);
EXPECT_EQ(context.GetErrorCode(), SSL_X509_V_ERR_CERT_HAS_EXPIRED);
context.SetErrorCode(SSL_X509_V_ERR_CERT_UNTRUSTED);
EXPECT_EQ(context.GetErrorCode(), SSL_X509_V_ERR_CERT_UNTRUSTED);
context.SetErrorCode(SSL_X509_V_ERR_HOSTNAME_MISMATCH);
EXPECT_EQ(context.GetErrorCode(), SSL_X509_V_ERR_HOSTNAME_MISMATCH);
}
HWTEST_F(VerifyCertChainContextTest, StateAfterParseError_019, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
context.SetErrorCode(PARSE_ERROR_CODE);
EXPECT_EQ(context.GetErrorCode(), PARSE_ERROR_CODE);
EXPECT_EQ(context.GetErrorMessage(), PARSE_ERROR_MSG);
EXPECT_EQ(context.GetInputCerts(), nullptr);
EXPECT_EQ(context.GetSortedChain(), nullptr);
}
HWTEST_F(VerifyCertChainContextTest, CheckParamsType_InvalidCount_020, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
napi_value params[4] = {nullptr, nullptr, nullptr, nullptr};
EXPECT_EQ(context.CheckParamsType(params, 0), false);
EXPECT_EQ(context.CheckParamsType(params, 4), false);
}
HWTEST_F(VerifyCertChainContextTest, Destructor_FreesSortedChain_021, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
{
VerifyCertChainContext context(env, manager);
CertBlob *chain = new CertBlob[1];
chain[0].type = CERT_TYPE_PEM;
chain[0].size = 100;
chain[0].data = new uint8_t[100];
if (memset_s(chain[0].data, 100, 0xFF, 100) != EOK) {
delete[] chain[0].data;
delete[] chain;
FAIL() << "memset_s failed";
return;
}
context.SetSortedChain(chain, 1);
}
EXPECT_TRUE(true);
}
HWTEST_F(VerifyCertChainContextTest, MixedCertTypes_022, testing::ext::TestSize.Level1)
{
napi_env env = nullptr;
std::shared_ptr<EventManager> manager = nullptr;
VerifyCertChainContext context(env, manager);
CertBlob *chain = new CertBlob[3];
chain[0].type = CERT_TYPE_PEM;
chain[0].size = 100;
chain[0].data = new uint8_t[100];
chain[1].type = CERT_TYPE_DER;
chain[1].size = 200;
chain[1].data = new uint8_t[200];
chain[2].type = CERT_TYPE_PEM;
chain[2].size = 150;
chain[2].data = new uint8_t[150];
context.SetSortedChain(chain, 3);
EXPECT_EQ(context.GetSortedChainCount(), 3);
EXPECT_EQ(context.GetSortedChain()[0].type, CERT_TYPE_PEM);
EXPECT_EQ(context.GetSortedChain()[1].type, CERT_TYPE_DER);
EXPECT_EQ(context.GetSortedChain()[2].type, CERT_TYPE_PEM);
}
}
}