Skip to content

Commit dcbc28c

Browse files
committed
Add input byte validation tests for shape tensor, reformat free tensor
1 parent 3183f8f commit dcbc28c

File tree

4 files changed

+155
-1
lines changed

4 files changed

+155
-1
lines changed

qa/L0_input_validation/input_validation_test.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import numpy as np
3636
import tritonclient.grpc as tritongrpcclient
3737
from tritonclient.utils import InferenceServerException, np_to_triton_dtype
38+
import tritonclient.utils.shared_memory as shm
3839

3940

4041
class InputValTest(unittest.TestCase):
@@ -211,6 +212,77 @@ def get_input_array(input_size, np_dtype):
211212
err_str,
212213
)
213214

215+
def test_wrong_input_shape_tensor_size(self):
216+
def inference_helper(model_name, batch_size=1):
217+
triton_client = tritongrpcclient.InferenceServerClient("localhost:8001")
218+
if batch_size > 1:
219+
dummy_input_data = np.random.rand(batch_size, 32, 32).astype(np.float32)
220+
else:
221+
dummy_input_data = np.random.rand(32, 32).astype(np.float32)
222+
shape_tensor_data = np.asarray([4, 4], dtype=np.int32)
223+
224+
# Pass incorrect input byte size date for shape tensor
225+
# Use shared memory to bypass the shape check in client library
226+
input_byte_size = (shape_tensor_data.size - 1) * np.dtype(np.int32).itemsize
227+
228+
input_shm_handle = shm.create_shared_memory_region(
229+
"INPUT0_SHM",
230+
"/INPUT0_SHM",
231+
input_byte_size,
232+
)
233+
shm.set_shared_memory_region(
234+
input_shm_handle,
235+
[
236+
shape_tensor_data,
237+
],
238+
)
239+
triton_client.register_system_shared_memory(
240+
"INPUT0_SHM",
241+
"/INPUT0_SHM",
242+
input_byte_size,
243+
)
244+
245+
inputs = [
246+
tritongrpcclient.InferInput(
247+
"DUMMY_INPUT0",
248+
dummy_input_data.shape,
249+
np_to_triton_dtype(np.float32),
250+
),
251+
tritongrpcclient.InferInput(
252+
"INPUT0",
253+
shape_tensor_data.shape,
254+
np_to_triton_dtype(np.int32),
255+
),
256+
]
257+
inputs[0].set_data_from_numpy(dummy_input_data)
258+
inputs[1].set_shared_memory("INPUT0_SHM", input_byte_size)
259+
260+
outputs = [
261+
tritongrpcclient.InferRequestedOutput("DUMMY_OUTPUT0"),
262+
tritongrpcclient.InferRequestedOutput("OUTPUT0"),
263+
]
264+
265+
try:
266+
# Perform inference
267+
with self.assertRaises(InferenceServerException) as e:
268+
triton_client.infer(
269+
model_name=model_name, inputs=inputs, outputs=outputs
270+
)
271+
err_str = str(e.exception)
272+
correct_input_byte_size = (
273+
shape_tensor_data.size * np.dtype(np.int32).itemsize
274+
)
275+
self.assertIn(
276+
f"input byte size mismatch for input 'INPUT0' for model '{model_name}'. Expected {correct_input_byte_size}, got {input_byte_size}",
277+
err_str,
278+
)
279+
finally:
280+
shm.destroy_shared_memory_region(input_shm_handle)
281+
triton_client.unregister_system_shared_memory("INPUT0_SHM")
282+
283+
inference_helper(model_name="plan_nobatch_zero_1_float32_int32")
284+
inference_helper(model_name="plan_zero_1_float32_int32", batch_size=8)
285+
214286

215287
if __name__ == "__main__":
216288
unittest.main()

qa/L0_input_validation/test.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ dynamic_batching {
123123
EOL
124124

125125
cp -r $DATADIR/qa_model_repository/graphdef_object_int32_int32 models/.
126+
cp -r $DATADIR/qa_shapetensor_model_repository/plan_nobatch_zero_1_float32_int32 models/.
127+
cp -r $DATADIR/qa_shapetensor_model_repository/plan_zero_1_float32_int32 models/.
126128

127129
SERVER_ARGS="--model-repository=`pwd`/models"
128130
run_server

qa/L0_trt_reformat_free/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ if [ $? -ne 0 ]; then
7575
cat $CLIENT_LOG
7676
RET=1
7777
else
78-
check_test_results $TEST_RESULT_FILE 4
78+
check_test_results $TEST_RESULT_FILE 6
7979
if [ $? -ne 0 ]; then
8080
cat $CLIENT_LOG
8181
echo -e "\n***\n*** Test Result Verification Failed\n***"

qa/L0_trt_reformat_free/trt_reformat_free_test.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import test_util as tu
3838
import tritonclient.http as tritonhttpclient
3939
import tritonclient.utils.shared_memory as shm
40+
from tritonclient.utils import InferenceServerException
4041

4142

4243
def div_up(a, b):
@@ -141,6 +142,41 @@ def test_nobatch_chw2_input(self):
141142
"OUTPUT0 expected: {}, got {}".format(expected_output1_np, output1_np),
142143
)
143144

145+
def test_wrong_nobatch_chw2_input(self):
146+
model_name = "plan_nobatch_CHW2_LINEAR_float16_float16_float16"
147+
input_np = np.arange(26, dtype=np.float16).reshape((13, 2, 1))
148+
149+
# Use shared memory to bypass the shape check in client library, because
150+
# for non-linear format tensor, the data buffer is padded and thus the
151+
# data byte size may not match what is calculated from tensor shape
152+
inputs = []
153+
inputs.append(tritonhttpclient.InferInput("INPUT0", [13, 2, 1], "FP16"))
154+
# Send the original size input instead of the reformatted size input.
155+
self.add_reformat_free_data_as_shared_memory("input0", inputs[-1], input_np)
156+
157+
inputs.append(tritonhttpclient.InferInput("INPUT1", [13, 2, 1], "FP16"))
158+
# Send the original size input instead of the reformatted size input.
159+
self.add_reformat_free_data_as_shared_memory("input1", inputs[-1], input_np)
160+
161+
outputs = []
162+
outputs.append(
163+
tritonhttpclient.InferRequestedOutput("OUTPUT0", binary_data=True)
164+
)
165+
outputs.append(
166+
tritonhttpclient.InferRequestedOutput("OUTPUT1", binary_data=True)
167+
)
168+
169+
with self.assertRaises(InferenceServerException) as e:
170+
results = self.triton_client.infer(
171+
model_name=model_name, inputs=inputs, outputs=outputs
172+
)
173+
174+
err_str = str(e.exception)
175+
self.assertIn(
176+
"input byte size mismatch for input 'INPUT0' for model 'plan_nobatch_CHW2_LINEAR_float16_float16_float16'. Expected 56, got 52",
177+
err_str,
178+
)
179+
144180
def test_chw2_input(self):
145181
model_name = "plan_CHW2_LINEAR_float16_float16_float16"
146182
for bs in [1, 8]:
@@ -186,6 +222,50 @@ def test_chw2_input(self):
186222
"OUTPUT0 expected: {}, got {}".format(expected_output1_np, output1_np),
187223
)
188224

225+
def test_wrong_chw2_input(self):
226+
model_name = "plan_CHW2_LINEAR_float16_float16_float16"
227+
for bs in [1, 8]:
228+
input_np = np.arange(26 * bs, dtype=np.float16).reshape((bs, 13, 2, 1))
229+
230+
# Use shared memory to bypass the shape check in client library,
231+
# because for non-linear format tensor, the data buffer is padded
232+
# and thus the data byte size may not match what is calculated from
233+
# tensor shape
234+
inputs = []
235+
inputs.append(tritonhttpclient.InferInput("INPUT0", [bs, 13, 2, 1], "FP16"))
236+
# Send the original size input instead of the reformatted size input.
237+
self.add_reformat_free_data_as_shared_memory(
238+
"input0" + str(bs), inputs[-1], input_np
239+
)
240+
241+
inputs.append(tritonhttpclient.InferInput("INPUT1", [bs, 13, 2, 1], "FP16"))
242+
# Send the original size input instead of the reformatted size input.
243+
self.add_reformat_free_data_as_shared_memory(
244+
"input1" + str(bs), inputs[-1], input_np
245+
)
246+
247+
outputs = []
248+
outputs.append(
249+
tritonhttpclient.InferRequestedOutput("OUTPUT0", binary_data=True)
250+
)
251+
outputs.append(
252+
tritonhttpclient.InferRequestedOutput("OUTPUT1", binary_data=True)
253+
)
254+
255+
with self.assertRaises(InferenceServerException) as e:
256+
results = self.triton_client.infer(
257+
model_name=model_name, inputs=inputs, outputs=outputs
258+
)
259+
err_str = str(e.exception)
260+
# reformatted input size - (bs, 14, 2, 1) * size(float16)
261+
expected_size = bs * 28 * 2
262+
# original input size - (bs, 13, 2, 1) * size(float16)
263+
received_size = bs * 26 * 2
264+
self.assertIn(
265+
f"input byte size mismatch for input 'INPUT0' for model 'plan_CHW2_LINEAR_float16_float16_float16'. Expected {expected_size}, got {received_size}",
266+
err_str,
267+
)
268+
189269
def test_nobatch_chw32_input(self):
190270
model_name = "plan_nobatch_CHW32_LINEAR_float32_float32_float32"
191271
input_np = np.arange(26, dtype=np.float32).reshape((13, 2, 1))

0 commit comments

Comments
 (0)