1+ # Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+
115"""Candidate-tree link checks need no model runtime or network access."""
216
317import importlib .util
@@ -78,13 +92,16 @@ def test_added_target_passes_before_merge_and_missing_target_fails(repo: Path) -
7892 "url" ,
7993 [
8094 f"{ PREFIX } /blob/main/src/retired.py#L1" ,
95+ f"{ PREFIX } /blob/main/src/retired.py/" ,
8196 f"{ PREFIX } /tree/main/src/retired.py?plain=1#L1" ,
8297 f"{ PREFIX } /tree/main/src/" ,
8398 f"{ PREFIX } /blob/main/src/" ,
8499 f"{ PREFIX } /tree/main" ,
85100 f"https://raw.githubusercontent.com/{ REPOSITORY } /main/src/retired.py" ,
86101 f"https://raw.githubusercontent.com/{ REPOSITORY } /refs/heads/main/src/retired.py" ,
87102 f"http://github.com/{ REPOSITORY .lower ()} /blob/main/src/retired.py" ,
103+ f"https://github.com:443/{ REPOSITORY } /blob/main/src/retired.py" ,
104+ f"http://github.com:80/{ REPOSITORY } /blob/main/src/retired.py" ,
88105 ],
89106)
90107def test_supported_github_and_raw_urls (repo : Path , url : str ) -> None :
@@ -95,6 +112,15 @@ def test_raw_url_requires_file(repo: Path) -> None:
95112 assert len (check (repo , [f"https://raw.githubusercontent.com/{ REPOSITORY } /main/src" ])[1 ]) == 1
96113
97114
115+ @pytest .mark .parametrize ("suffix" , ["/" , "%2F" ])
116+ def test_raw_file_trailing_slash_fails (repo : Path , suffix : str ) -> None :
117+ url = f"https://raw.githubusercontent.com/{ REPOSITORY } /main/src/retired.py{ suffix } "
118+ external , errors = check (repo , [url ])
119+ assert external == []
120+ assert len (errors ) == 1
121+ assert "missing" in errors [0 ]
122+
123+
98124@pytest .mark .parametrize (
99125 "url" ,
100126 [
@@ -109,6 +135,11 @@ def test_raw_url_requires_file(repo: Path) -> None:
109135 "https://github.com/another/repo/blob/main/missing.py" ,
110136 f"https://example.com/{ REPOSITORY } /blob/main/missing.py" ,
111137 f"https://github.com.evil.example/{ REPOSITORY } /blob/main/missing.py" ,
138+ f"https://github.com:8443/{ REPOSITORY } /blob/main/src/retired.py" ,
139+ f"https://raw.githubusercontent.com:8443/{ REPOSITORY } /main/src/retired.py" ,
140+ f"https://github.com:80/{ REPOSITORY } /blob/main/src/retired.py" ,
141+ f"http://github.com:443/{ REPOSITORY } /blob/main/src/retired.py" ,
142+ f"https://user@github.com/{ REPOSITORY } /blob/main/src/retired.py" ,
112143 ],
113144)
114145def test_explicit_versions_and_external_urls_remain_online (repo : Path , url : str ) -> None :
0 commit comments