From eaf76597f63c6986d48f1d6b0fed54b7873da14f Mon Sep 17 00:00:00 2001 From: Rini Gupta Date: Tue, 6 Oct 2026 15:36:58 -0700 Subject: [PATCH] test: Add RHEL tutorial validation tests qa/L0_rhel_tutorial_cpu and qa/L0_rhel_tutorial_gpu are the RHEL/manylinux tutorial's Step 4 checks: each test.sh builds its models, serves them from the image the tutorial built, and runs a pytest suite. --- qa/L0_rhel_tutorial_cpu/gen_onnx.py | 50 +++++++++++++ .../models/add_onnx/config.pbtxt | 35 +++++++++ .../models/add_py/1/model.py | 39 ++++++++++ .../models/add_py/config.pbtxt | 35 +++++++++ qa/L0_rhel_tutorial_cpu/rhel_tutorial_test.py | 66 +++++++++++++++++ qa/L0_rhel_tutorial_cpu/test.sh | 70 ++++++++++++++++++ qa/L0_rhel_tutorial_gpu/gen_pt.py | 43 +++++++++++ .../models/add_torch/config.pbtxt | 35 +++++++++ qa/L0_rhel_tutorial_gpu/rhel_tutorial_test.py | 65 +++++++++++++++++ qa/L0_rhel_tutorial_gpu/test.sh | 71 +++++++++++++++++++ 10 files changed, 509 insertions(+) create mode 100755 qa/L0_rhel_tutorial_cpu/gen_onnx.py create mode 100644 qa/L0_rhel_tutorial_cpu/models/add_onnx/config.pbtxt create mode 100644 qa/L0_rhel_tutorial_cpu/models/add_py/1/model.py create mode 100644 qa/L0_rhel_tutorial_cpu/models/add_py/config.pbtxt create mode 100755 qa/L0_rhel_tutorial_cpu/rhel_tutorial_test.py create mode 100755 qa/L0_rhel_tutorial_cpu/test.sh create mode 100755 qa/L0_rhel_tutorial_gpu/gen_pt.py create mode 100644 qa/L0_rhel_tutorial_gpu/models/add_torch/config.pbtxt create mode 100755 qa/L0_rhel_tutorial_gpu/rhel_tutorial_test.py create mode 100755 qa/L0_rhel_tutorial_gpu/test.sh diff --git a/qa/L0_rhel_tutorial_cpu/gen_onnx.py b/qa/L0_rhel_tutorial_cpu/gen_onnx.py new file mode 100755 index 0000000000..1e9192a439 --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/gen_onnx.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Writes models/add_onnx/1/model.onnx, an Add graph: OUTPUT0 = INPUT0 + INPUT1. + +import os + +import onnx +from onnx import TensorProto, helper + +graph = helper.make_graph( + [helper.make_node("Add", ["INPUT0", "INPUT1"], ["OUTPUT0"])], + "add", + [ + helper.make_tensor_value_info("INPUT0", TensorProto.FLOAT, [4]), + helper.make_tensor_value_info("INPUT1", TensorProto.FLOAT, [4]), + ], + [helper.make_tensor_value_info("OUTPUT0", TensorProto.FLOAT, [4])], +) +# ir_version 7 pairs with opset 13; onnx's default (its newest IR) can exceed +# what ORT accepts. +model = helper.make_model( + graph, ir_version=7, opset_imports=[helper.make_opsetid("", 13)] +) +os.makedirs("models/add_onnx/1", exist_ok=True) +onnx.save(model, "models/add_onnx/1/model.onnx") diff --git a/qa/L0_rhel_tutorial_cpu/models/add_onnx/config.pbtxt b/qa/L0_rhel_tutorial_cpu/models/add_onnx/config.pbtxt new file mode 100644 index 0000000000..aa4bd1713f --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/models/add_onnx/config.pbtxt @@ -0,0 +1,35 @@ +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +name: "add_onnx" +backend: "onnxruntime" +max_batch_size: 0 +input [ + { name: "INPUT0", data_type: TYPE_FP32, dims: [4] }, + { name: "INPUT1", data_type: TYPE_FP32, dims: [4] } +] +output [ { name: "OUTPUT0", data_type: TYPE_FP32, dims: [4] } ] +instance_group [ { kind: KIND_CPU } ] diff --git a/qa/L0_rhel_tutorial_cpu/models/add_py/1/model.py b/qa/L0_rhel_tutorial_cpu/models/add_py/1/model.py new file mode 100644 index 0000000000..a32b5a33ac --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/models/add_py/1/model.py @@ -0,0 +1,39 @@ +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import numpy as np +import triton_python_backend_utils as pb_utils + + +class TritonPythonModel: + def execute(self, requests): + responses = [] + for request in requests: + a = pb_utils.get_input_tensor_by_name(request, "INPUT0").as_numpy() + b = pb_utils.get_input_tensor_by_name(request, "INPUT1").as_numpy() + output = pb_utils.Tensor("OUTPUT0", (a + b).astype(np.float32)) + responses.append(pb_utils.InferenceResponse(output_tensors=[output])) + return responses diff --git a/qa/L0_rhel_tutorial_cpu/models/add_py/config.pbtxt b/qa/L0_rhel_tutorial_cpu/models/add_py/config.pbtxt new file mode 100644 index 0000000000..e4cd17b7a3 --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/models/add_py/config.pbtxt @@ -0,0 +1,35 @@ +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +name: "add_py" +backend: "python" +max_batch_size: 0 +input [ + { name: "INPUT0", data_type: TYPE_FP32, dims: [4] }, + { name: "INPUT1", data_type: TYPE_FP32, dims: [4] } +] +output [ { name: "OUTPUT0", data_type: TYPE_FP32, dims: [4] } ] +instance_group [ { kind: KIND_CPU } ] diff --git a/qa/L0_rhel_tutorial_cpu/rhel_tutorial_test.py b/qa/L0_rhel_tutorial_cpu/rhel_tutorial_test.py new file mode 100755 index 0000000000..b8fa8f9c25 --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/rhel_tutorial_test.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Inference checks for the RHEL/manylinux tutorial's CPU models, served by test.sh: +# add_py (python backend) and add_onnx (onnxruntime backend) both compute +# OUTPUT0 = INPUT0 + INPUT1. + +import os + +import numpy as np +import pytest +import tritonclient.http as httpclient + +# By default, find tritonserver on "localhost", but for windows tests +# we overwrite the IP address with the TRITONSERVER_IPADDR envvar +_tritonserver_ipaddr = os.environ.get("TRITONSERVER_IPADDR", "localhost") + +INPUT0 = np.array([1, 2, 3, 4], dtype=np.float32) +INPUT1 = np.array([10, 20, 30, 40], dtype=np.float32) + + +@pytest.fixture(scope="module") +def client(): + with httpclient.InferenceServerClient(f"{_tritonserver_ipaddr}:8000") as c: + yield c + + +def test_server_ready(client): + assert client.is_server_ready() + + +@pytest.mark.parametrize("model", ["add_py", "add_onnx"]) +def test_add(client, model): + assert client.is_model_ready(model) + inputs = [ + httpclient.InferInput("INPUT0", INPUT0.shape, "FP32"), + httpclient.InferInput("INPUT1", INPUT1.shape, "FP32"), + ] + inputs[0].set_data_from_numpy(INPUT0) + inputs[1].set_data_from_numpy(INPUT1) + result = client.infer(model, inputs) + np.testing.assert_array_equal(result.as_numpy("OUTPUT0"), INPUT0 + INPUT1) diff --git a/qa/L0_rhel_tutorial_cpu/test.sh b/qa/L0_rhel_tutorial_cpu/test.sh new file mode 100755 index 0000000000..ce37444edf --- /dev/null +++ b/qa/L0_rhel_tutorial_cpu/test.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Check for the RHEL/manylinux build tutorial (tutorials repo, +# Build_Guide/RHEL_Manylinux): serves its Step 4 CPU models, add_py and add_onnx, +# from the image the tutorial built and runs rhel_tutorial_test.py against them. +# Needs no model repository from /data. + +SERVER=/opt/tritonserver/bin/tritonserver +SERVER_ARGS="--model-repository=`pwd`/models" +SERVER_LOG="./inference_server.log" +CLIENT_LOG="./client.log" +source ../common/util.sh + +rm -f *.log *.report.xml + +# The tutorial image ships neither onnx (to write the model) nor the test's client deps. +python3 -m pip install --quiet onnx pytest "tritonclient[http]" || exit 1 +python3 gen_onnx.py || exit 1 + +run_server +if [ "$SERVER_PID" == "0" ]; then + echo -e "\n***\n*** Failed to start $SERVER\n***" + cat $SERVER_LOG + exit 1 +fi + +RET=0 +set +e +python3 -m pytest --junitxml=rhel_tutorial_cpu.report.xml rhel_tutorial_test.py >> $CLIENT_LOG 2>&1 +if [ $? -ne 0 ]; then + cat $CLIENT_LOG + RET=1 +fi +set -e + +kill_server + +if [ $RET -eq 0 ]; then + echo -e "\n***\n*** Test Passed\n***" +else + cat $SERVER_LOG + echo -e "\n***\n*** Test FAILED\n***" +fi + +exit $RET diff --git a/qa/L0_rhel_tutorial_gpu/gen_pt.py b/qa/L0_rhel_tutorial_gpu/gen_pt.py new file mode 100755 index 0000000000..339d6a2b6d --- /dev/null +++ b/qa/L0_rhel_tutorial_gpu/gen_pt.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Writes models/add_torch/1/model.pt, a TorchScript OUTPUT__0 = INPUT__0 + INPUT__1, +# traced with the torch the tutorial installed into the serving image. + +import os + +import torch + + +class Add(torch.nn.Module): + def forward(self, a, b): + return a + b + + +example = (torch.zeros(4), torch.zeros(4)) +os.makedirs("models/add_torch/1", exist_ok=True) +torch.jit.trace(Add().eval(), example).save("models/add_torch/1/model.pt") diff --git a/qa/L0_rhel_tutorial_gpu/models/add_torch/config.pbtxt b/qa/L0_rhel_tutorial_gpu/models/add_torch/config.pbtxt new file mode 100644 index 0000000000..7d7b95b3fd --- /dev/null +++ b/qa/L0_rhel_tutorial_gpu/models/add_torch/config.pbtxt @@ -0,0 +1,35 @@ +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +name: "add_torch" +backend: "pytorch" +max_batch_size: 0 +input [ + { name: "INPUT__0", data_type: TYPE_FP32, dims: [4] }, + { name: "INPUT__1", data_type: TYPE_FP32, dims: [4] } +] +output [ { name: "OUTPUT__0", data_type: TYPE_FP32, dims: [4] } ] +instance_group [ { kind: KIND_GPU } ] diff --git a/qa/L0_rhel_tutorial_gpu/rhel_tutorial_test.py b/qa/L0_rhel_tutorial_gpu/rhel_tutorial_test.py new file mode 100755 index 0000000000..3156f7ef94 --- /dev/null +++ b/qa/L0_rhel_tutorial_gpu/rhel_tutorial_test.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Inference check for the RHEL/manylinux tutorial's PyTorch model, served by +# test.sh: add_torch (pytorch backend, KIND_GPU) computes OUTPUT__0 = INPUT__0 + +# INPUT__1. + +import os + +import numpy as np +import pytest +import tritonclient.http as httpclient + +# By default, find tritonserver on "localhost", but for windows tests +# we overwrite the IP address with the TRITONSERVER_IPADDR envvar +_tritonserver_ipaddr = os.environ.get("TRITONSERVER_IPADDR", "localhost") + +INPUT0 = np.array([1, 2, 3, 4], dtype=np.float32) +INPUT1 = np.array([10, 20, 30, 40], dtype=np.float32) + + +@pytest.fixture(scope="module") +def client(): + with httpclient.InferenceServerClient(f"{_tritonserver_ipaddr}:8000") as c: + yield c + + +def test_server_ready(client): + assert client.is_server_ready() + + +def test_add_torch(client): + assert client.is_model_ready("add_torch") + inputs = [ + httpclient.InferInput("INPUT__0", INPUT0.shape, "FP32"), + httpclient.InferInput("INPUT__1", INPUT1.shape, "FP32"), + ] + inputs[0].set_data_from_numpy(INPUT0) + inputs[1].set_data_from_numpy(INPUT1) + result = client.infer("add_torch", inputs) + np.testing.assert_array_equal(result.as_numpy("OUTPUT__0"), INPUT0 + INPUT1) diff --git a/qa/L0_rhel_tutorial_gpu/test.sh b/qa/L0_rhel_tutorial_gpu/test.sh new file mode 100755 index 0000000000..ea71b075ad --- /dev/null +++ b/qa/L0_rhel_tutorial_gpu/test.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# Copyright 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Check for the RHEL/manylinux build tutorial (tutorials repo, +# Build_Guide/RHEL_Manylinux): serves its Step 4 PyTorch model, add_torch, on GPU +# from the tutorial's PyTorch serving image and runs rhel_tutorial_test.py against +# it. Needs no model repository from /data. + +export CUDA_VISIBLE_DEVICES=0 +SERVER=/opt/tritonserver/bin/tritonserver +SERVER_ARGS="--model-repository=`pwd`/models" +SERVER_LOG="./inference_server.log" +CLIENT_LOG="./client.log" +source ../common/util.sh + +rm -f *.log *.report.xml + +# The tutorial image ships torch (to write the model) but not the test's client deps. +python3 -m pip install --quiet pytest "tritonclient[http]" || exit 1 +python3 gen_pt.py || exit 1 + +run_server +if [ "$SERVER_PID" == "0" ]; then + echo -e "\n***\n*** Failed to start $SERVER\n***" + cat $SERVER_LOG + exit 1 +fi + +RET=0 +set +e +python3 -m pytest --junitxml=rhel_tutorial_gpu.report.xml rhel_tutorial_test.py >> $CLIENT_LOG 2>&1 +if [ $? -ne 0 ]; then + cat $CLIENT_LOG + RET=1 +fi +set -e + +kill_server + +if [ $RET -eq 0 ]; then + echo -e "\n***\n*** Test Passed\n***" +else + cat $SERVER_LOG + echo -e "\n***\n*** Test FAILED\n***" +fi + +exit $RET