blob: 117b3ddf4a081bc3dd0f9d3b9d32d00bdaa3d394 [file] [log] [blame]
/*
*
* Copyright 2018 gRPC authors.
*
* 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 "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include <stdio.h>
#include <stdlib.h>
#include <gtest/gtest.h>
#include "upb/upb.hpp"
#include <grpc/grpc.h>
#include <grpc/support/sync.h>
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/tsi/alts/handshaker/alts_handshaker_client.h"
#include "src/core/tsi/alts/handshaker/alts_shared_resource.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h"
#include "src/core/tsi/transport_security_grpc.h"
#include "src/proto/grpc/gcp/altscontext.upb.h"
#include "test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.h"
#include "test/core/util/test_config.h"
#define ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES "Hello World"
#define ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME "Hello Google"
#define ALTS_TSI_HANDSHAKER_TEST_CONSUMED_BYTES "Hello "
#define ALTS_TSI_HANDSHAKER_TEST_REMAIN_BYTES "Google"
#define ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY "chapi@service.google.com"
#define ALTS_TSI_HANDSHAKER_TEST_SECURITY_LEVEL "TSI_PRIVACY_AND_INTEGRITY"
#define ALTS_TSI_HANDSHAKER_TEST_KEY_DATA \
"ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKL"
#define ALTS_TSI_HANDSHAKER_TEST_BUFFER_SIZE 100
#define ALTS_TSI_HANDSHAKER_TEST_SLEEP_TIME_IN_SECONDS 2
#define ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MAJOR 3
#define ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MINOR 2
#define ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MAJOR 2
#define ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MINOR 1
#define ALTS_TSI_HANDSHAKER_TEST_LOCAL_IDENTITY "chapilocal@service.google.com"
#define ALTS_TSI_HANDSHAKER_TEST_APPLICATION_PROTOCOL \
"test application protocol"
#define ALTS_TSI_HANDSHAKER_TEST_RECORD_PROTOCOL "test record protocol"
#define ALTS_TSI_HANDSHAKER_TEST_MAX_FRAME_SIZE (2 * 1024 * 1024)
#define ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_KEY "peer"
#define ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_VALUE "attributes"
using grpc_core::internal::alts_handshaker_client_check_fields_for_testing;
using grpc_core::internal::alts_handshaker_client_get_handshaker_for_testing;
using grpc_core::internal::
alts_handshaker_client_get_recv_buffer_addr_for_testing;
using grpc_core::internal::
alts_handshaker_client_on_status_received_for_testing;
using grpc_core::internal::alts_handshaker_client_ref_for_testing;
using grpc_core::internal::alts_handshaker_client_set_cb_for_testing;
using grpc_core::internal::alts_handshaker_client_set_fields_for_testing;
using grpc_core::internal::alts_handshaker_client_set_recv_bytes_for_testing;
using grpc_core::internal::alts_tsi_handshaker_get_client_for_testing;
using grpc_core::internal::alts_tsi_handshaker_get_is_client_for_testing;
using grpc_core::internal::alts_tsi_handshaker_set_client_vtable_for_testing;
static bool should_handshaker_client_api_succeed = true;
/* ALTS mock notification. */
typedef struct notification {
gpr_cv cv;
gpr_mu mu;
bool notified;
} notification;
/* Type of ALTS handshaker response. */
typedef enum {
INVALID,
FAILED,
CLIENT_START,
SERVER_START,
CLIENT_NEXT,
SERVER_NEXT,
} alts_handshaker_response_type;
static alts_handshaker_client* cb_event = nullptr;
static notification caller_to_tsi_notification;
static notification tsi_to_caller_notification;
static void notification_init(notification* n) {
gpr_mu_init(&n->mu);
gpr_cv_init(&n->cv);
n->notified = false;
}
static void notification_destroy(notification* n) {
gpr_mu_destroy(&n->mu);
gpr_cv_destroy(&n->cv);
}
static void signal(notification* n) {
gpr_mu_lock(&n->mu);
n->notified = true;
gpr_cv_signal(&n->cv);
gpr_mu_unlock(&n->mu);
}
static void wait(notification* n) {
gpr_mu_lock(&n->mu);
while (!n->notified) {
gpr_cv_wait(&n->cv, &n->mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
n->notified = false;
gpr_mu_unlock(&n->mu);
}
/**
* This method mocks ALTS handshaker service to generate handshaker response
* for a specific request.
*/
static grpc_byte_buffer* generate_handshaker_response(
alts_handshaker_response_type type) {
upb::Arena arena;
grpc_gcp_HandshakerResult* result;
grpc_gcp_Identity* peer_identity;
grpc_gcp_HandshakerResp* resp = grpc_gcp_HandshakerResp_new(arena.ptr());
grpc_gcp_HandshakerStatus* status =
grpc_gcp_HandshakerResp_mutable_status(resp, arena.ptr());
grpc_gcp_HandshakerStatus_set_code(status, 0);
grpc_gcp_Identity* local_identity;
switch (type) {
case INVALID:
break;
case CLIENT_START:
case SERVER_START:
grpc_gcp_HandshakerResp_set_out_frames(
resp, upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
break;
case CLIENT_NEXT:
grpc_gcp_HandshakerResp_set_out_frames(
resp, upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
grpc_gcp_HandshakerResp_set_bytes_consumed(
resp, strlen(ALTS_TSI_HANDSHAKER_TEST_CONSUMED_BYTES));
result = grpc_gcp_HandshakerResp_mutable_result(resp, arena.ptr());
peer_identity =
grpc_gcp_HandshakerResult_mutable_peer_identity(result, arena.ptr());
grpc_gcp_Identity_attributes_set(
peer_identity,
upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_KEY),
upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_VALUE),
arena.ptr());
grpc_gcp_Identity_set_service_account(
peer_identity,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY));
grpc_gcp_HandshakerResult_set_key_data(
result, upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_KEY_DATA));
EXPECT_TRUE(grpc_gcp_handshaker_resp_set_peer_rpc_versions(
resp, arena.ptr(), ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MAJOR,
ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MINOR,
ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MAJOR,
ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MINOR));
local_identity =
grpc_gcp_HandshakerResult_mutable_local_identity(result, arena.ptr());
grpc_gcp_Identity_set_service_account(
local_identity,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_LOCAL_IDENTITY));
grpc_gcp_HandshakerResult_set_application_protocol(
result, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_APPLICATION_PROTOCOL));
grpc_gcp_HandshakerResult_set_record_protocol(
result,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_RECORD_PROTOCOL));
grpc_gcp_HandshakerResult_set_max_frame_size(
result, ALTS_TSI_HANDSHAKER_TEST_MAX_FRAME_SIZE);
break;
case SERVER_NEXT:
grpc_gcp_HandshakerResp_set_bytes_consumed(
resp, strlen(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
result = grpc_gcp_HandshakerResp_mutable_result(resp, arena.ptr());
peer_identity =
grpc_gcp_HandshakerResult_mutable_peer_identity(result, arena.ptr());
grpc_gcp_Identity_attributes_set(
peer_identity,
upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_KEY),
upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_VALUE),
arena.ptr());
grpc_gcp_Identity_set_service_account(
peer_identity,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY));
grpc_gcp_HandshakerResult_set_key_data(
result, upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_KEY_DATA));
EXPECT_TRUE(grpc_gcp_handshaker_resp_set_peer_rpc_versions(
resp, arena.ptr(), ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MAJOR,
ALTS_TSI_HANDSHAKER_TEST_MAX_RPC_VERSION_MINOR,
ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MAJOR,
ALTS_TSI_HANDSHAKER_TEST_MIN_RPC_VERSION_MINOR));
local_identity =
grpc_gcp_HandshakerResult_mutable_local_identity(result, arena.ptr());
grpc_gcp_Identity_set_service_account(
local_identity,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_LOCAL_IDENTITY));
grpc_gcp_HandshakerResult_set_application_protocol(
result, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_APPLICATION_PROTOCOL));
grpc_gcp_HandshakerResult_set_record_protocol(
result,
upb_StringView_FromString(ALTS_TSI_HANDSHAKER_TEST_RECORD_PROTOCOL));
break;
case FAILED:
grpc_gcp_HandshakerStatus_set_code(status, 3 /* INVALID ARGUMENT */);
break;
}
size_t buf_len;
char* buf = grpc_gcp_HandshakerResp_serialize(resp, arena.ptr(), &buf_len);
grpc_slice slice = gpr_slice_from_copied_buffer(buf, buf_len);
if (type == INVALID) {
grpc_slice bad_slice =
grpc_slice_split_head(&slice, GRPC_SLICE_LENGTH(slice) - 1);
grpc_slice_unref(slice);
slice = grpc_slice_ref(bad_slice);
grpc_slice_unref(bad_slice);
}
grpc_byte_buffer* buffer =
grpc_raw_byte_buffer_create(&slice, 1 /* number of slices */);
grpc_slice_unref(slice);
return buffer;
}
static void check_must_not_be_called(tsi_result /*status*/, void* /*user_data*/,
const unsigned char* /*bytes_to_send*/,
size_t /*bytes_to_send_size*/,
tsi_handshaker_result* /*result*/) {
ASSERT_TRUE(0);
}
static void on_client_start_success_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_OK);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send_size, strlen(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
ASSERT_EQ(memcmp(bytes_to_send, ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME,
bytes_to_send_size),
0);
ASSERT_EQ(result, nullptr);
/* Validate peer identity. */
tsi_peer peer;
ASSERT_EQ(tsi_handshaker_result_extract_peer(result, &peer),
TSI_INVALID_ARGUMENT);
/* Validate frame protector. */
tsi_frame_protector* protector = nullptr;
ASSERT_EQ(
tsi_handshaker_result_create_frame_protector(result, nullptr, &protector),
TSI_INVALID_ARGUMENT);
/* Validate unused bytes. */
const unsigned char* unused_bytes = nullptr;
size_t unused_bytes_size = 0;
ASSERT_EQ(tsi_handshaker_result_get_unused_bytes(result, &unused_bytes,
&unused_bytes_size),
TSI_INVALID_ARGUMENT);
signal(&tsi_to_caller_notification);
}
static void on_server_start_success_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_OK);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send_size, strlen(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
ASSERT_EQ(memcmp(bytes_to_send, ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME,
bytes_to_send_size),
0);
ASSERT_EQ(result, nullptr);
/* Validate peer identity. */
tsi_peer peer;
ASSERT_EQ(tsi_handshaker_result_extract_peer(result, &peer),
TSI_INVALID_ARGUMENT);
/* Validate frame protector. */
tsi_frame_protector* protector = nullptr;
ASSERT_EQ(
tsi_handshaker_result_create_frame_protector(result, nullptr, &protector),
TSI_INVALID_ARGUMENT);
/* Validate unused bytes. */
const unsigned char* unused_bytes = nullptr;
size_t unused_bytes_size = 0;
ASSERT_EQ(tsi_handshaker_result_get_unused_bytes(result, &unused_bytes,
&unused_bytes_size),
TSI_INVALID_ARGUMENT);
signal(&tsi_to_caller_notification);
}
static void on_client_next_success_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_OK);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send_size, strlen(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME));
ASSERT_EQ(memcmp(bytes_to_send, ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME,
bytes_to_send_size),
0);
ASSERT_NE(result, nullptr);
// Validate max frame size value after Frame Size Negotiation. Here peer max
// frame size is greater than default value, and user specified max frame size
// is absent.
tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr;
ASSERT_EQ(tsi_handshaker_result_create_zero_copy_grpc_protector(
result, nullptr, &zero_copy_protector),
TSI_OK);
size_t actual_max_frame_size;
tsi_zero_copy_grpc_protector_max_frame_size(zero_copy_protector,
&actual_max_frame_size);
ASSERT_EQ(actual_max_frame_size, kTsiAltsMaxFrameSize);
tsi_zero_copy_grpc_protector_destroy(zero_copy_protector);
/* Validate peer identity. */
tsi_peer peer;
ASSERT_EQ(tsi_handshaker_result_extract_peer(result, &peer), TSI_OK);
ASSERT_EQ(peer.property_count, kTsiAltsNumOfPeerProperties);
ASSERT_EQ(memcmp(TSI_ALTS_CERTIFICATE_TYPE, peer.properties[0].value.data,
peer.properties[0].value.length),
0);
ASSERT_EQ(
memcmp(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY,
peer.properties[1].value.data, peer.properties[1].value.length),
0);
/* Validate alts context. */
upb::Arena context_arena;
grpc_gcp_AltsContext* ctx = grpc_gcp_AltsContext_parse(
peer.properties[3].value.data, peer.properties[3].value.length,
context_arena.ptr());
ASSERT_NE(ctx, nullptr);
upb_StringView application_protocol =
grpc_gcp_AltsContext_application_protocol(ctx);
upb_StringView record_protocol = grpc_gcp_AltsContext_record_protocol(ctx);
upb_StringView peer_account = grpc_gcp_AltsContext_peer_service_account(ctx);
upb_StringView local_account =
grpc_gcp_AltsContext_local_service_account(ctx);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_APPLICATION_PROTOCOL,
application_protocol.data, application_protocol.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_RECORD_PROTOCOL,
record_protocol.data, record_protocol.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY, peer_account.data,
peer_account.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_LOCAL_IDENTITY, local_account.data,
local_account.size),
0);
size_t iter = kUpb_Map_Begin;
grpc_gcp_AltsContext_PeerAttributesEntry* peer_attributes_entry =
grpc_gcp_AltsContext_peer_attributes_nextmutable(ctx, &iter);
ASSERT_NE(peer_attributes_entry, nullptr);
while (peer_attributes_entry != nullptr) {
upb_StringView key = grpc_gcp_AltsContext_PeerAttributesEntry_key(
const_cast<grpc_gcp_AltsContext_PeerAttributesEntry*>(
peer_attributes_entry));
upb_StringView val = grpc_gcp_AltsContext_PeerAttributesEntry_value(
const_cast<grpc_gcp_AltsContext_PeerAttributesEntry*>(
peer_attributes_entry));
ASSERT_TRUE(upb_StringView_IsEqual(
key, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_KEY)));
ASSERT_TRUE(upb_StringView_IsEqual(
val, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_VALUE)));
peer_attributes_entry =
grpc_gcp_AltsContext_peer_attributes_nextmutable(ctx, &iter);
}
/* Validate security level. */
ASSERT_EQ(
memcmp(ALTS_TSI_HANDSHAKER_TEST_SECURITY_LEVEL,
peer.properties[4].value.data, peer.properties[4].value.length),
0);
tsi_peer_destruct(&peer);
/* Validate unused bytes. */
const unsigned char* bytes = nullptr;
size_t bytes_size = 0;
ASSERT_EQ(tsi_handshaker_result_get_unused_bytes(result, &bytes, &bytes_size),
TSI_OK);
ASSERT_EQ(bytes_size, strlen(ALTS_TSI_HANDSHAKER_TEST_REMAIN_BYTES));
ASSERT_EQ(memcmp(bytes, ALTS_TSI_HANDSHAKER_TEST_REMAIN_BYTES, bytes_size),
0);
/* Validate frame protector. */
tsi_frame_protector* protector = nullptr;
ASSERT_EQ(
tsi_handshaker_result_create_frame_protector(result, nullptr, &protector),
TSI_OK);
ASSERT_NE(protector, nullptr);
tsi_frame_protector_destroy(protector);
tsi_handshaker_result_destroy(result);
signal(&tsi_to_caller_notification);
}
static void on_server_next_success_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_OK);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_NE(result, nullptr);
// Validate max frame size value after Frame Size Negotiation. The negotiated
// frame size value equals minimum send frame size, due to the absence of peer
// max frame size.
tsi_zero_copy_grpc_protector* zero_copy_protector = nullptr;
size_t user_specified_max_frame_size =
ALTS_TSI_HANDSHAKER_TEST_MAX_FRAME_SIZE;
ASSERT_EQ(tsi_handshaker_result_create_zero_copy_grpc_protector(
result, &user_specified_max_frame_size, &zero_copy_protector),
TSI_OK);
size_t actual_max_frame_size;
tsi_zero_copy_grpc_protector_max_frame_size(zero_copy_protector,
&actual_max_frame_size);
ASSERT_EQ(actual_max_frame_size, kTsiAltsMinFrameSize);
tsi_zero_copy_grpc_protector_destroy(zero_copy_protector);
/* Validate peer identity. */
tsi_peer peer;
ASSERT_EQ(tsi_handshaker_result_extract_peer(result, &peer), TSI_OK);
ASSERT_EQ(peer.property_count, kTsiAltsNumOfPeerProperties);
ASSERT_EQ(memcmp(TSI_ALTS_CERTIFICATE_TYPE, peer.properties[0].value.data,
peer.properties[0].value.length),
0);
ASSERT_EQ(
memcmp(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY,
peer.properties[1].value.data, peer.properties[1].value.length),
0);
/* Validate alts context. */
upb::Arena context_arena;
grpc_gcp_AltsContext* ctx = grpc_gcp_AltsContext_parse(
peer.properties[3].value.data, peer.properties[3].value.length,
context_arena.ptr());
ASSERT_NE(ctx, nullptr);
upb_StringView application_protocol =
grpc_gcp_AltsContext_application_protocol(ctx);
upb_StringView record_protocol = grpc_gcp_AltsContext_record_protocol(ctx);
upb_StringView peer_account = grpc_gcp_AltsContext_peer_service_account(ctx);
upb_StringView local_account =
grpc_gcp_AltsContext_local_service_account(ctx);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_APPLICATION_PROTOCOL,
application_protocol.data, application_protocol.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_RECORD_PROTOCOL,
record_protocol.data, record_protocol.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_PEER_IDENTITY, peer_account.data,
peer_account.size),
0);
ASSERT_EQ(memcmp(ALTS_TSI_HANDSHAKER_TEST_LOCAL_IDENTITY, local_account.data,
local_account.size),
0);
size_t iter = kUpb_Map_Begin;
grpc_gcp_AltsContext_PeerAttributesEntry* peer_attributes_entry =
grpc_gcp_AltsContext_peer_attributes_nextmutable(ctx, &iter);
ASSERT_NE(peer_attributes_entry, nullptr);
while (peer_attributes_entry != nullptr) {
upb_StringView key = grpc_gcp_AltsContext_PeerAttributesEntry_key(
const_cast<grpc_gcp_AltsContext_PeerAttributesEntry*>(
peer_attributes_entry));
upb_StringView val = grpc_gcp_AltsContext_PeerAttributesEntry_value(
const_cast<grpc_gcp_AltsContext_PeerAttributesEntry*>(
peer_attributes_entry));
ASSERT_TRUE(upb_StringView_IsEqual(
key, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_KEY)));
ASSERT_TRUE(upb_StringView_IsEqual(
val, upb_StringView_FromString(
ALTS_TSI_HANDSHAKER_TEST_PEER_ATTRIBUTES_VALUE)));
peer_attributes_entry =
grpc_gcp_AltsContext_peer_attributes_nextmutable(ctx, &iter);
}
/* Check security level. */
ASSERT_EQ(
memcmp(ALTS_TSI_HANDSHAKER_TEST_SECURITY_LEVEL,
peer.properties[4].value.data, peer.properties[4].value.length),
0);
tsi_peer_destruct(&peer);
/* Validate unused bytes. */
const unsigned char* bytes = nullptr;
size_t bytes_size = 0;
ASSERT_EQ(tsi_handshaker_result_get_unused_bytes(result, &bytes, &bytes_size),
TSI_OK);
ASSERT_EQ(bytes_size, 0);
ASSERT_EQ(bytes, nullptr);
/* Validate frame protector. */
tsi_frame_protector* protector = nullptr;
ASSERT_EQ(
tsi_handshaker_result_create_frame_protector(result, nullptr, &protector),
TSI_OK);
ASSERT_NE(protector, nullptr);
tsi_frame_protector_destroy(protector);
tsi_handshaker_result_destroy(result);
signal(&tsi_to_caller_notification);
}
static tsi_result mock_client_start(alts_handshaker_client* client) {
if (!should_handshaker_client_api_succeed) {
return TSI_INTERNAL_ERROR;
}
/* Note that the alts_tsi_handshaker needs to set its
* has_sent_start_message field field to true
* before the call to alts_handshaker_client_start is made because
* because it's unsafe to access it afterwards. */
alts_handshaker_client_check_fields_for_testing(
client, on_client_start_success_cb, nullptr, true, nullptr);
/* Populate handshaker response for client_start request. */
grpc_byte_buffer** recv_buffer_ptr =
alts_handshaker_client_get_recv_buffer_addr_for_testing(client);
*recv_buffer_ptr = generate_handshaker_response(CLIENT_START);
cb_event = client;
signal(&caller_to_tsi_notification);
return TSI_OK;
}
static void mock_shutdown(alts_handshaker_client* /*self*/) {}
static tsi_result mock_server_start(alts_handshaker_client* client,
grpc_slice* bytes_received) {
if (!should_handshaker_client_api_succeed) {
return TSI_INTERNAL_ERROR;
}
alts_handshaker_client_check_fields_for_testing(
client, on_server_start_success_cb, nullptr, true, nullptr);
grpc_slice slice = grpc_empty_slice();
EXPECT_EQ(grpc_slice_cmp(*bytes_received, slice), 0);
/* Populate handshaker response for server_start request. */
grpc_byte_buffer** recv_buffer_ptr =
alts_handshaker_client_get_recv_buffer_addr_for_testing(client);
*recv_buffer_ptr = generate_handshaker_response(SERVER_START);
cb_event = client;
grpc_slice_unref(slice);
signal(&caller_to_tsi_notification);
return TSI_OK;
}
static tsi_result mock_next(alts_handshaker_client* client,
grpc_slice* bytes_received) {
if (!should_handshaker_client_api_succeed) {
return TSI_INTERNAL_ERROR;
}
alts_tsi_handshaker* handshaker =
alts_handshaker_client_get_handshaker_for_testing(client);
bool is_client = alts_tsi_handshaker_get_is_client_for_testing(handshaker);
tsi_handshaker_on_next_done_cb cb =
is_client ? on_client_next_success_cb : on_server_next_success_cb;
alts_handshaker_client_set_cb_for_testing(client, cb);
alts_handshaker_client_set_recv_bytes_for_testing(client, bytes_received);
alts_handshaker_client_check_fields_for_testing(client, cb, nullptr, true,
bytes_received);
EXPECT_NE(bytes_received, nullptr);
EXPECT_EQ(memcmp(GRPC_SLICE_START_PTR(*bytes_received),
ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
GRPC_SLICE_LENGTH(*bytes_received)),
0);
/* Populate handshaker response for next request. */
grpc_slice out_frame =
grpc_slice_from_static_string(ALTS_TSI_HANDSHAKER_TEST_OUT_FRAME);
grpc_byte_buffer** recv_buffer_ptr =
alts_handshaker_client_get_recv_buffer_addr_for_testing(client);
*recv_buffer_ptr = is_client ? generate_handshaker_response(CLIENT_NEXT)
: generate_handshaker_response(SERVER_NEXT);
alts_handshaker_client_set_recv_bytes_for_testing(client, &out_frame);
cb_event = client;
signal(&caller_to_tsi_notification);
grpc_slice_unref(out_frame);
return TSI_OK;
}
static void mock_destruct(alts_handshaker_client* /*client*/) {}
static alts_handshaker_client_vtable vtable = {mock_client_start,
mock_server_start, mock_next,
mock_shutdown, mock_destruct};
static tsi_handshaker* create_test_handshaker(bool is_client) {
tsi_handshaker* handshaker = nullptr;
grpc_alts_credentials_options* options =
grpc_alts_credentials_client_options_create();
alts_tsi_handshaker_create(options, "target_name",
ALTS_HANDSHAKER_SERVICE_URL_FOR_TESTING, is_client,
nullptr, &handshaker, 0);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
alts_tsi_handshaker_set_client_vtable_for_testing(alts_handshaker, &vtable);
grpc_alts_credentials_options_destroy(options);
return handshaker;
}
static void run_tsi_handshaker_destroy_with_exec_ctx(
tsi_handshaker* handshaker) {
grpc_core::ExecCtx exec_ctx;
tsi_handshaker_destroy(handshaker);
}
TEST(AltsTsiHandshakerTest, CheckHandshakerNextInvalidInput) {
should_handshaker_client_api_succeed = true;
/* Initialization. */
tsi_handshaker* handshaker = create_test_handshaker(true);
/* Check nullptr handshaker. */
ASSERT_EQ(tsi_handshaker_next(nullptr, nullptr, 0, nullptr, nullptr, nullptr,
check_must_not_be_called, nullptr),
TSI_INVALID_ARGUMENT);
/* Check nullptr callback. */
ASSERT_EQ(tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr,
nullptr, nullptr, nullptr),
TSI_INVALID_ARGUMENT);
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
}
TEST(AltsTsiHandshakerTest, CheckHandshakerShutdownInvalidInput) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
/* Check nullptr handshaker. */
tsi_handshaker_shutdown(nullptr);
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
}
static void check_handshaker_next_success() {
/**
* Create handshakers for which internal mock client is going to do
* correctness check.
*/
tsi_handshaker* client_handshaker =
create_test_handshaker(true /* is_client */);
tsi_handshaker* server_handshaker =
create_test_handshaker(false /* is_client */);
/* Client start. */
ASSERT_EQ(tsi_handshaker_next(client_handshaker, nullptr, 0, nullptr, nullptr,
nullptr, on_client_start_success_cb, nullptr),
TSI_ASYNC);
wait(&tsi_to_caller_notification);
/* Client next. */
ASSERT_EQ(tsi_handshaker_next(
client_handshaker,
(const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
nullptr, on_client_next_success_cb, nullptr),
TSI_ASYNC);
wait(&tsi_to_caller_notification);
/* Server start. */
ASSERT_EQ(tsi_handshaker_next(server_handshaker, nullptr, 0, nullptr, nullptr,
nullptr, on_server_start_success_cb, nullptr),
TSI_ASYNC);
wait(&tsi_to_caller_notification);
/* Server next. */
ASSERT_EQ(tsi_handshaker_next(
server_handshaker,
(const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
nullptr, on_server_next_success_cb, nullptr),
TSI_ASYNC);
wait(&tsi_to_caller_notification);
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(server_handshaker);
run_tsi_handshaker_destroy_with_exec_ctx(client_handshaker);
}
static void check_handshaker_next_with_shutdown() {
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client*/);
/* next(success) -- shutdown(success) -- next (fail) */
ASSERT_EQ(tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr,
nullptr, on_client_start_success_cb, nullptr),
TSI_ASYNC);
wait(&tsi_to_caller_notification);
tsi_handshaker_shutdown(handshaker);
ASSERT_EQ(
tsi_handshaker_next(
handshaker, (const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
nullptr, on_client_next_success_cb, nullptr),
TSI_HANDSHAKE_SHUTDOWN);
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
}
static void check_handle_response_with_shutdown(void* /*unused*/) {
wait(&caller_to_tsi_notification);
alts_handshaker_client_handle_response(cb_event, true /* is_ok */);
}
TEST(AltsTsiHandshakerTest, CheckHandshakerNextFailure) {
should_handshaker_client_api_succeed = false;
/**
* Create handshakers for which internal mock client is always going to fail.
*/
tsi_handshaker* client_handshaker =
create_test_handshaker(true /* is_client */);
tsi_handshaker* server_handshaker =
create_test_handshaker(false /* is_client */);
/* Client start. */
ASSERT_EQ(tsi_handshaker_next(client_handshaker, nullptr, 0, nullptr, nullptr,
nullptr, check_must_not_be_called, nullptr),
TSI_INTERNAL_ERROR);
/* Server start. */
ASSERT_EQ(tsi_handshaker_next(server_handshaker, nullptr, 0, nullptr, nullptr,
nullptr, check_must_not_be_called, nullptr),
TSI_INTERNAL_ERROR);
/* Server next. */
ASSERT_EQ(tsi_handshaker_next(
server_handshaker,
(const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
nullptr, check_must_not_be_called, nullptr),
TSI_INTERNAL_ERROR);
/* Client next. */
ASSERT_EQ(tsi_handshaker_next(
client_handshaker,
(const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
nullptr, check_must_not_be_called, nullptr),
TSI_INTERNAL_ERROR);
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(server_handshaker);
run_tsi_handshaker_destroy_with_exec_ctx(client_handshaker);
}
static void on_invalid_input_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_INTERNAL_ERROR);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(result, nullptr);
}
static void on_failed_grpc_call_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_INTERNAL_ERROR);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(result, nullptr);
}
TEST(AltsTsiHandshakerTest, CheckHandleResponseNullptrHandshaker) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
grpc_slice slice = grpc_empty_slice();
grpc_byte_buffer* recv_buffer = grpc_raw_byte_buffer_create(&slice, 1);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Check nullptr handshaker. */
alts_handshaker_client_set_fields_for_testing(
client, nullptr, on_invalid_input_cb, nullptr, recv_buffer,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, true);
/* Note: here and elsewhere in this test, we first ref the handshaker in order
* to match the unref that on_status_received will do. This necessary
* because this test mocks out the grpc call in such a way that the code
* path that would usually take this ref is skipped. */
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
grpc_slice_unref(slice);
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
TEST(AltsTsiHandshakerTest, CheckHandleResponseNullptrRecvBytes) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Check nullptr recv_bytes. */
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_invalid_input_cb, nullptr, nullptr,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, true);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
TEST(AltsTsiHandshakerTest,
CheckHandleResponseFailedGrpcCallToHandshakerService) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
grpc_slice slice = grpc_empty_slice();
grpc_byte_buffer* recv_buffer = grpc_raw_byte_buffer_create(&slice, 1);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Check failed grpc call made to handshaker service. */
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_failed_grpc_call_cb, nullptr, recv_buffer,
/*inject_read_failure=*/true);
alts_handshaker_client_handle_response(client, true);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_UNKNOWN, GRPC_ERROR_NONE);
}
/* Cleanup. */
grpc_slice_unref(slice);
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
TEST(AltsTsiHandshakerTest,
CheckHandleResponseFailedRecvMessageFromHandshakerService) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
grpc_slice slice = grpc_empty_slice();
grpc_byte_buffer* recv_buffer = grpc_raw_byte_buffer_create(&slice, 1);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Check failed recv message op from handshaker service. */
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_failed_grpc_call_cb, nullptr, recv_buffer,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, false);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
grpc_slice_unref(slice);
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
static void on_invalid_resp_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_DATA_CORRUPTED);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(result, nullptr);
}
TEST(AltsTsiHandshakerTest, CheckHandleResponseInvalidResp) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Tests. */
grpc_byte_buffer* recv_buffer = generate_handshaker_response(INVALID);
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_invalid_resp_cb, nullptr, recv_buffer,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, true);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
static void check_handle_response_success(void* /*unused*/) {
/* Client start. */
wait(&caller_to_tsi_notification);
alts_handshaker_client_handle_response(cb_event, true /* is_ok */);
/* Client next. */
wait(&caller_to_tsi_notification);
alts_handshaker_client_handle_response(cb_event, true /* is_ok */);
alts_handshaker_client_ref_for_testing(cb_event);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
cb_event, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Server start. */
wait(&caller_to_tsi_notification);
alts_handshaker_client_handle_response(cb_event, true /* is_ok */);
/* Server next. */
wait(&caller_to_tsi_notification);
alts_handshaker_client_handle_response(cb_event, true /* is_ok */);
alts_handshaker_client_ref_for_testing(cb_event);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
cb_event, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
}
static void on_failed_resp_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_INVALID_ARGUMENT);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(result, nullptr);
}
TEST(AltsTsiHandshakerTest, CheckHandleResponseFailure) {
should_handshaker_client_api_succeed = false;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/**
* Create a handshaker at the client side, for which internal mock client is
* always going to fail.
*/
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
/* Tests. */
grpc_byte_buffer* recv_buffer = generate_handshaker_response(FAILED);
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_failed_resp_cb, nullptr, recv_buffer,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, true /* is_ok*/);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
static void on_shutdown_resp_cb(tsi_result status, void* user_data,
const unsigned char* bytes_to_send,
size_t bytes_to_send_size,
tsi_handshaker_result* result) {
ASSERT_EQ(status, TSI_HANDSHAKE_SHUTDOWN);
ASSERT_EQ(user_data, nullptr);
ASSERT_EQ(bytes_to_send, nullptr);
ASSERT_EQ(bytes_to_send_size, 0);
ASSERT_EQ(result, nullptr);
}
TEST(AltsTsiHandshakerTest, CheckHandleResponseAfterShutdown) {
should_handshaker_client_api_succeed = true;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
tsi_handshaker* handshaker = create_test_handshaker(true /* is_client */);
tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr, nullptr,
on_client_start_success_cb, nullptr);
alts_tsi_handshaker* alts_handshaker =
reinterpret_cast<alts_tsi_handshaker*>(handshaker);
alts_handshaker_client* client =
alts_tsi_handshaker_get_client_for_testing(alts_handshaker);
grpc_byte_buffer** recv_buffer_ptr =
alts_handshaker_client_get_recv_buffer_addr_for_testing(client);
grpc_byte_buffer_destroy(*recv_buffer_ptr);
/* Tests. */
tsi_handshaker_shutdown(handshaker);
grpc_byte_buffer* recv_buffer = generate_handshaker_response(CLIENT_START);
alts_handshaker_client_set_fields_for_testing(
client, alts_handshaker, on_shutdown_resp_cb, nullptr, recv_buffer,
/*inject_read_failure=*/false);
alts_handshaker_client_handle_response(client, true);
alts_handshaker_client_ref_for_testing(client);
{
grpc_core::ExecCtx exec_ctx;
alts_handshaker_client_on_status_received_for_testing(
client, GRPC_STATUS_OK, GRPC_ERROR_NONE);
}
/* Cleanup. */
run_tsi_handshaker_destroy_with_exec_ctx(handshaker);
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
TEST(AltsTsiHandshakerTest, CheckHandshakerNextFailsAfterShutdown) {
should_handshaker_client_api_succeed = true;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
cb_event = nullptr;
/* Tests. */
grpc_core::Thread thd("alts_tsi_handshaker_test",
&check_handle_response_with_shutdown, nullptr);
thd.Start();
check_handshaker_next_with_shutdown();
thd.Join();
/* Cleanup. */
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
TEST(AltsTsiHandshakerTest, CheckHandshakerSuccess) {
should_handshaker_client_api_succeed = true;
/* Initialization. */
notification_init(&caller_to_tsi_notification);
notification_init(&tsi_to_caller_notification);
/* Tests. */
grpc_core::Thread thd("alts_tsi_handshaker_test",
&check_handle_response_success, nullptr);
thd.Start();
check_handshaker_next_success();
thd.Join();
/* Cleanup. */
notification_destroy(&caller_to_tsi_notification);
notification_destroy(&tsi_to_caller_notification);
}
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(&argc, argv);
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestGrpcScope grpc_scope;
grpc_alts_shared_resource_dedicated_init();
int ret = RUN_ALL_TESTS();
grpc_alts_shared_resource_dedicated_shutdown();
return ret;
}