Skip to content

Commit 06afae5

Browse files
authored
test: Test safe GetElementCount and GetByteSize APIs at common and core repos (#8689)
1 parent d8f1616 commit 06afae5

4 files changed

Lines changed: 147 additions & 59 deletions

File tree

Dockerfile.QA

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2018-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# Copyright 2018-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
#
33
# Redistribution and use in source and binary forms, with or without
44
# modification, are permitted provided that the following conditions
@@ -139,7 +139,7 @@ RUN mkdir -p qa/common && \
139139
mkdir qa/L0_data_compression/models && \
140140
cp -r docs/examples/model_repository/simple qa/L0_data_compression/models && \
141141
cp bin/data_compressor_test qa/L0_data_compression/. && \
142-
cp bin/backend_tensor_size_test qa/L0_input_validation/. && \
142+
cp bin/tensor_size_test qa/L0_input_validation/. && \
143143
cp bin/metrics_api_test qa/L0_metrics/. && \
144144
cp bin/response_cache_test qa/L0_response_cache/. && \
145145
cp bin/request_cancellation_test qa/L0_request_cancellation/. && \

qa/L0_input_validation/test.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,15 @@ if [ $? -ne 0 ]; then
162162
fi
163163
set -e
164164

165-
# backend_tensor_size_test
166-
TEST_LOG="./backend_tensor_size_test.log"
167-
TEST_EXEC=./backend_tensor_size_test
165+
# tensor_size_test
166+
TEST_LOG="./tensor_size_test.log"
167+
TEST_EXEC=./tensor_size_test
168168

169169
set +e
170170
LD_LIBRARY_PATH=/opt/tritonserver/lib:$LD_LIBRARY_PATH $TEST_EXEC >> $TEST_LOG 2>&1
171171
if [ $? -ne 0 ]; then
172172
cat $TEST_LOG
173-
echo -e "\n***\n*** backend_tensor_size_test FAILED\n***"
173+
echo -e "\n***\n*** tensor_size_test FAILED\n***"
174174
RET=1
175175
fi
176176
set -e

src/test/CMakeLists.txt

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
# Copyright 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
#
33
# Redistribution and use in source and binary forms, with or without
44
# modification, are permitted provided that the following conditions
@@ -78,43 +78,53 @@ if(${TRITON_ENABLE_HTTP} OR ${TRITON_ENABLE_METRICS} OR
7878
endif()
7979

8080
#
81-
# Unit test for Backend API
81+
# Unit test for Backend + Common + Core tensor size APIs (GetElementCount,
82+
# GetByteSize). Core template headers are used directly; the few core symbols
83+
# not available via libtritonserver.so (hidden by linker script) are defined
84+
# in the test source.
8285
#
83-
add_executable(
84-
backend_tensor_size_test
85-
backend_tensor_size_test.cc
86-
)
86+
if(TARGET proto-library)
87+
add_executable(
88+
tensor_size_test
89+
tensor_size_test.cc
90+
)
8791

88-
set_target_properties(
89-
backend_tensor_size_test
90-
PROPERTIES
91-
SKIP_BUILD_RPATH TRUE
92-
BUILD_WITH_INSTALL_RPATH TRUE
93-
INSTALL_RPATH_USE_LINK_PATH FALSE
94-
INSTALL_RPATH ""
95-
)
92+
set_target_properties(
93+
tensor_size_test
94+
PROPERTIES
95+
SKIP_BUILD_RPATH TRUE
96+
BUILD_WITH_INSTALL_RPATH TRUE
97+
INSTALL_RPATH_USE_LINK_PATH FALSE
98+
INSTALL_RPATH "$ORIGIN/../lib"
99+
)
96100

97-
target_include_directories(
98-
backend_tensor_size_test
99-
PRIVATE
100-
${CMAKE_CURRENT_SOURCE_DIR}/..
101-
${GTEST_INCLUDE_DIRS}
102-
)
101+
target_include_directories(
102+
tensor_size_test
103+
PRIVATE
104+
${CMAKE_CURRENT_SOURCE_DIR}/..
105+
${GTEST_INCLUDE_DIRS}
106+
${repo-core_SOURCE_DIR}/src
107+
$<TARGET_PROPERTY:proto-library,INTERFACE_INCLUDE_DIRECTORIES>
108+
)
103109

104-
target_link_libraries(
105-
backend_tensor_size_test
106-
PRIVATE
107-
triton-backend-utils # from repo-backend
108-
triton-core-serverapi # from repo-core
109-
triton-core-serverstub # from repo-core
110-
GTest::gtest
111-
GTest::gtest_main
112-
)
110+
target_link_libraries(
111+
tensor_size_test
112+
PRIVATE
113+
triton-backend-utils
114+
triton-core-serverapi
115+
triton-core-serverstub
116+
triton-common-model-config
117+
proto-library
118+
protobuf::libprotobuf
119+
GTest::gtest
120+
GTest::gtest_main
121+
)
113122

114-
install(
115-
TARGETS backend_tensor_size_test
116-
RUNTIME DESTINATION bin
117-
)
123+
install(
124+
TARGETS tensor_size_test
125+
RUNTIME DESTINATION bin
126+
)
127+
endif()
118128

119129
add_subdirectory(repoagent/relocation_repoagent repoagent/relocation_repoagent)
120130

Lines changed: 98 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1+
// Copyright 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
22
//
33
// Redistribution and use in source and binary forms, with or without
44
// modification, are permitted provided that the following conditions
@@ -35,10 +35,25 @@
3535
#include <string>
3636
#include <vector>
3737

38+
#include "model_config_utils.h"
39+
#undef RETURN_IF_ERROR // core (Status) vs backend (TRITONSERVER_Error*); avoid
40+
// redefinition
3841
#include "triton/backend/backend_common.h"
39-
#include "triton/core/tritonserver.h"
42+
#include "triton/common/model_config.h"
4043

4144
namespace tb = triton::backend;
45+
namespace tc = triton::common;
46+
namespace tcore = triton::core;
47+
48+
// Core's linker script hides C++ symbols from libtritonserver.so.
49+
// Provide the small set of definitions the header-only templates need.
50+
const tcore::Status tcore::Status::Success(tcore::Status::Code::SUCCESS);
51+
52+
inference::DataType
53+
tcore::TritonToDataType(const TRITONSERVER_DataType dtype)
54+
{
55+
return static_cast<inference::DataType>(dtype);
56+
}
4257

4358
namespace {
4459

@@ -76,28 +91,39 @@ TRITONSERVER_ErrorMessage(TRITONSERVER_Error* error)
7691
namespace {
7792

7893
enum class ErrorCode {
79-
kInvalidDim = -2,
80-
kOverflow = -3,
94+
kInvalidDim = tc::INVALID_SIZE,
95+
kOverflow = tc::OVERFLOW_SIZE,
8196
};
8297

98+
static const std::string kTensorName{"input0"};
99+
83100
void
84101
assert_get_element_count_success(
85102
std::vector<int64_t>& shape, int64_t expected_cnt)
86103
{
87104
int64_t cnt;
88105
TRITONSERVER_Error* err;
89106

90-
// assert old APIs
107+
// Backend (old APIs)
91108
ASSERT_EQ(expected_cnt, tb::GetElementCount(shape.data(), shape.size()));
92109
ASSERT_EQ(expected_cnt, tb::GetElementCount(shape));
93110

94-
// assert new APIs
111+
// Backend (new APIs)
95112
err = tb::GetElementCount(shape.data(), shape.size(), &cnt);
96113
ASSERT_EQ(err, nullptr);
97114
ASSERT_EQ(cnt, expected_cnt);
98115
err = tb::GetElementCount(shape, &cnt);
99116
ASSERT_EQ(err, nullptr);
100117
ASSERT_EQ(cnt, expected_cnt);
118+
119+
// Common
120+
ASSERT_EQ(tc::GetElementCount(shape), expected_cnt);
121+
122+
// Core
123+
cnt = 0;
124+
auto status = tcore::GetElementCount(shape, kTensorName, &cnt);
125+
ASSERT_TRUE(status.IsOk()) << status.Message();
126+
ASSERT_EQ(cnt, expected_cnt);
101127
}
102128

103129
void
@@ -108,13 +134,13 @@ assert_get_element_count_error(
108134
int64_t cnt;
109135
TRITONSERVER_Error* err;
110136

111-
// assert old APIs
137+
// Backend (old APIs)
112138
ASSERT_EQ(
113139
static_cast<int>(error_code),
114140
tb::GetElementCount(shape.data(), shape.size()));
115141
ASSERT_EQ(static_cast<int>(error_code), tb::GetElementCount(shape));
116142

117-
// assert new APIs
143+
// Backend (new APIs)
118144
err = tb::GetElementCount(shape.data(), shape.size(), &cnt);
119145
ASSERT_NE(err, nullptr);
120146
ASSERT_EQ(TRITONSERVER_ERROR_INVALID_ARG, TRITONSERVER_ErrorCode(err));
@@ -123,23 +149,50 @@ assert_get_element_count_error(
123149
ASSERT_NE(err, nullptr);
124150
ASSERT_EQ(TRITONSERVER_ERROR_INVALID_ARG, TRITONSERVER_ErrorCode(err));
125151
ASSERT_STREQ(error_msg.c_str(), TRITONSERVER_ErrorMessage(err));
152+
153+
// Common
154+
ASSERT_EQ(tc::GetElementCount(shape), static_cast<int64_t>(error_code));
155+
156+
// Core
157+
cnt = 0;
158+
auto status = tcore::GetElementCount(shape, kTensorName, &cnt);
159+
ASSERT_FALSE(status.IsOk());
160+
ASSERT_EQ(status.StatusCode(), triton::core::Status::Code::INVALID_ARG);
161+
ASSERT_TRUE(
162+
std::string(status.Message())
163+
.find(
164+
error_code == ErrorCode::kInvalidDim
165+
? "invalid dimension"
166+
: "exceeds maximum size") != std::string::npos);
126167
}
127168

128169
void
129170
assert_get_byte_size_success(
130171
TRITONSERVER_DataType dtype, std::vector<int64_t>& shape,
131-
int64_t expected_size)
172+
int64_t expected_size, bool test_core = true)
132173
{
133174
int64_t size;
134175
TRITONSERVER_Error* err;
135176

136-
// assert old API
177+
// Backend (old API)
137178
ASSERT_EQ(expected_size, tb::GetByteSize(dtype, shape));
138179

139-
// assert new API
180+
// Backend (new API)
140181
err = tb::GetByteSize(dtype, shape, &size);
141182
ASSERT_EQ(err, nullptr);
142183
ASSERT_EQ(expected_size, size);
184+
185+
// Common
186+
inference::DataType core_dtype = tcore::TritonToDataType(dtype);
187+
ASSERT_EQ(tc::GetByteSize(core_dtype, shape), expected_size);
188+
189+
// Core
190+
if (test_core) {
191+
size = 0;
192+
auto status = tcore::GetByteSize(core_dtype, shape, kTensorName, &size);
193+
ASSERT_TRUE(status.IsOk()) << status.Message();
194+
ASSERT_EQ(size, expected_size);
195+
}
143196
}
144197

145198
void
@@ -150,14 +203,33 @@ assert_get_byte_size_error(
150203
int64_t size;
151204
TRITONSERVER_Error* err;
152205

153-
// assert old API
206+
// Backend (old API)
154207
ASSERT_EQ(static_cast<int>(error_code), tb::GetByteSize(dtype, shape));
155208

156-
// assert new API
209+
// Backend (new API)
157210
err = tb::GetByteSize(dtype, shape, &size);
158211
ASSERT_NE(err, nullptr);
159212
ASSERT_EQ(TRITONSERVER_ERROR_INVALID_ARG, TRITONSERVER_ErrorCode(err));
160213
ASSERT_EQ(error_msg, TRITONSERVER_ErrorMessage(err));
214+
215+
// Common
216+
inference::DataType core_dtype = tcore::TritonToDataType(dtype);
217+
ASSERT_EQ(
218+
tc::GetByteSize(core_dtype, shape), error_code == ErrorCode::kInvalidDim
219+
? tc::INVALID_SIZE
220+
: tc::OVERFLOW_SIZE);
221+
222+
// Core
223+
size = 0;
224+
auto status = tcore::GetByteSize(core_dtype, shape, kTensorName, &size);
225+
ASSERT_FALSE(status.IsOk());
226+
ASSERT_EQ(status.StatusCode(), triton::core::Status::Code::INVALID_ARG);
227+
ASSERT_TRUE(
228+
std::string(status.Message())
229+
.find(
230+
error_code == ErrorCode::kInvalidDim
231+
? "invalid dimension"
232+
: "exceeds maximum size") != std::string::npos);
161233
}
162234

163235
class GetElementCountTest : public ::testing::Test {
@@ -186,10 +258,10 @@ TEST_F(GetElementCountTest, GetElementCount)
186258
assert_get_element_count_success(shape, expected_cnt);
187259
}
188260

189-
TEST_F(GetElementCountTest, GetElementCountNegative)
261+
TEST_F(GetElementCountTest, GetElementCountWildcard)
190262
{
191263
std::vector<int64_t> shape;
192-
int64_t expected_cnt = -1;
264+
int64_t expected_cnt = tc::WILDCARD_SIZE;
193265

194266
// Test 1: -1 dim
195267
shape = {-1};
@@ -221,7 +293,6 @@ TEST_F(GetElementCountTest, GetElementCountZero)
221293
shape = {1, 8, 0};
222294
assert_get_element_count_success(shape, expected_cnt);
223295

224-
// Test 2: one 0 dim
225296
shape = {0, 1, 8};
226297
assert_get_element_count_success(shape, expected_cnt);
227298

@@ -307,11 +378,11 @@ TEST_F(GetByteSizeTest, GetByteSize)
307378
assert_get_byte_size_success(dtype, shape, expected_size);
308379
}
309380

310-
TEST_F(GetByteSizeTest, GetByteSizeNegative)
381+
TEST_F(GetByteSizeTest, GetByteSizeWildcard)
311382
{
312383
TRITONSERVER_DataType dtype;
313384
std::vector<int64_t> shape;
314-
int64_t expected_size = -1;
385+
int64_t expected_size = tc::WILDCARD_SIZE;
315386

316387
// Test 1: invalid dtype
317388
dtype = TRITONSERVER_TYPE_INVALID;
@@ -321,7 +392,14 @@ TEST_F(GetByteSizeTest, GetByteSizeNegative)
321392
// Test 2: bytes dtype
322393
dtype = TRITONSERVER_TYPE_BYTES;
323394
shape = {8, 8};
324-
assert_get_byte_size_success(dtype, shape, expected_size);
395+
assert_get_byte_size_success(dtype, shape, expected_size, false);
396+
// test core explicitly as it treats string dtype size as 4
397+
int64_t size = 0;
398+
inference::DataType core_dtype = tcore::TritonToDataType(dtype);
399+
auto status = tcore::GetByteSize(core_dtype, shape, kTensorName, &size);
400+
ASSERT_TRUE(status.IsOk()) << status.Message();
401+
ASSERT_EQ(size, sizeof(int32_t) * 8 * 8);
402+
325403

326404
// Test 3: invalid shape and element count overflows
327405
dtype = TRITONSERVER_TYPE_INVALID;
@@ -348,7 +426,6 @@ TEST_F(GetByteSizeTest, GetByteSizeZero)
348426
shape = {1, 8, 0};
349427
assert_get_byte_size_success(dtype, shape, expected_cnt);
350428

351-
// Test 2: one 0 dim
352429
shape = {0, 1, 8};
353430
assert_get_byte_size_success(dtype, shape, expected_cnt);
354431

@@ -403,6 +480,7 @@ TEST_F(GetByteSizeTest, GetByteSizeOverflow)
403480
error_msg = "unexpected integer overflow while calculating byte size.";
404481
assert_get_byte_size_error(dtype, shape, ErrorCode::kOverflow, error_msg);
405482
}
483+
406484
} // namespace
407485

408486
int

0 commit comments

Comments
 (0)