|
1 | | -# Copyright 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
| 1 | +# Copyright 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. |
2 | 2 | # |
3 | 3 | # Redistribution and use in source and binary forms, with or without |
4 | 4 | # modification, are permitted provided that the following conditions |
|
35 | 35 | from openai_frontend.engine.utils.triton import ( |
36 | 36 | _parse_lora_configs as parse_lora_configs, |
37 | 37 | ) |
| 38 | +from openai_frontend.engine.utils.triton import ( |
| 39 | + _validate_lora_path_trtllm as validate_lora_path_trtllm, |
| 40 | +) |
38 | 41 |
|
39 | 42 | from .utils import OpenAIServer |
40 | 43 |
|
41 | 44 |
|
| 45 | +def is_vllm_installed(): |
| 46 | + try: |
| 47 | + import vllm as _ |
| 48 | + |
| 49 | + return True |
| 50 | + except ImportError: |
| 51 | + return False |
| 52 | + |
| 53 | + |
42 | 54 | @pytest.mark.parametrize( |
43 | 55 | "model_repository,model_name,expect_error", |
44 | 56 | [ |
@@ -74,13 +86,62 @@ def test_parse_lora_configs(model_repository: str, model_name: str, expect_error |
74 | 86 | ) |
75 | 87 |
|
76 | 88 |
|
77 | | -def is_vllm_installed(): |
| 89 | +@pytest.mark.skipif( |
| 90 | + is_vllm_installed(), |
| 91 | + reason="VLLM backend does not validate LoRA paths", |
| 92 | +) |
| 93 | +@pytest.mark.parametrize( |
| 94 | + "lora_path,expect_error,error_message", |
| 95 | + [ |
| 96 | + # Valid relative path inside repo (requires .npy files to exist at runtime). |
| 97 | + ("tensorrt_llm_bls/1/luotuo-lora-7b-0.1-weights", False, None), |
| 98 | + ("tensorrt_llm_bls/1/Japanese-Alpaca-LoRA-7b-v0-weights", False, None), |
| 99 | + # Absolute path not allowed. |
| 100 | + ( |
| 101 | + os.path.join( |
| 102 | + os.path.abspath(os.curdir), |
| 103 | + "tests/tensorrtllm_models", |
| 104 | + "tensorrt_llm_bls/1/luotuo-lora-7b-0.1-weights", |
| 105 | + ), |
| 106 | + True, |
| 107 | + f"must be a relative path inside its model repository", |
| 108 | + ), |
| 109 | + ("/etc/passwd", True, "must be a relative path inside its model repository"), |
| 110 | + # Path outside repo (traversal). |
| 111 | + ("tensorrt_llm_bls/1//../1/luotuo-lora-7b-0.1-weights", False, None), |
| 112 | + ("../outside/lora", True, "must be inside its model repository"), |
| 113 | + ("subdir/../../etc/passwd", True, "must be inside its model repository"), |
| 114 | + # LoRA directory not found. |
| 115 | + ("tensorrt_llm_bls/10", True, "LoRA directory 'tensorrt_llm_bls/10' not found"), |
| 116 | + ( |
| 117 | + "tensorrt_llm_bls/1/non_exist", |
| 118 | + True, |
| 119 | + "LoRA directory 'tensorrt_llm_bls/1/non_exist' not found", |
| 120 | + ), |
| 121 | + # LoRA file not found. |
| 122 | + ("tensorrt_llm_bls/1", True, "LoRA file 'model.lora_weights.npy' not found"), |
| 123 | + ], |
| 124 | +) |
| 125 | +def test_validate_lora_path_trtllm( |
| 126 | + lora_path: str, |
| 127 | + expect_error: bool, |
| 128 | + error_message: str, |
| 129 | +): |
| 130 | + lora_name = "" |
| 131 | + repo_path = "tests/tensorrtllm_models" |
78 | 132 | try: |
79 | | - import vllm as _ |
80 | | - |
81 | | - return True |
82 | | - except ImportError: |
83 | | - return False |
| 133 | + validate_lora_path_trtllm(repo_path, lora_path, lora_name) |
| 134 | + except Exception as e: |
| 135 | + if not expect_error: |
| 136 | + raise pytest.fail( |
| 137 | + f"repo_path='{repo_path}' raised exception unexpectedly: {e}" |
| 138 | + ) |
| 139 | + assert error_message in str(e) |
| 140 | + else: |
| 141 | + if expect_error: |
| 142 | + raise pytest.fail( |
| 143 | + f"lora_path='{repo_path}' did not raise exception as expected." |
| 144 | + ) |
84 | 145 |
|
85 | 146 |
|
86 | 147 | class LoRATest(unittest.TestCase): |
|
0 commit comments