@@ -147,3 +147,111 @@ in the repository.\n"
147147 Ok ( warnings)
148148 }
149149}
150+
151+ #[ cfg( test) ]
152+ mod tests {
153+ use super :: * ;
154+ use crate :: compile:: parse_markdown;
155+
156+ fn ctx_from ( front_matter : & crate :: compile:: types:: FrontMatter ) -> CompileContext < ' _ > {
157+ CompileContext :: for_test ( front_matter)
158+ }
159+
160+ #[ test]
161+ fn test_validate_bash_disabled_warning ( ) {
162+ let ( fm, _) =
163+ parse_markdown ( "---\n name: test\n description: test\n tools:\n bash: []\n ---\n " )
164+ . unwrap ( ) ;
165+ let ext = DotnetExtension :: new ( DotnetRuntimeConfig :: Enabled ( true ) ) ;
166+ let warnings = ext. validate ( & ctx_from ( & fm) ) . unwrap ( ) ;
167+ assert ! ( !warnings. is_empty( ) ) ;
168+ assert ! ( warnings[ 0 ] . contains( "tools.bash is empty" ) ) ;
169+ }
170+
171+ #[ test]
172+ fn test_validate_config_and_feed_url_are_mutually_exclusive ( ) {
173+ let ( fm, _) = parse_markdown (
174+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n config: 'nuget.config'\n feed-url: 'https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json'\n ---\n " ,
175+ )
176+ . unwrap ( ) ;
177+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
178+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
179+ let err = ext. validate ( & ctx_from ( & fm) ) . unwrap_err ( ) ;
180+ assert ! ( err. to_string( ) . contains( "mutually exclusive" ) ) ;
181+ }
182+
183+ #[ test]
184+ fn test_validate_invalid_feed_url_rejected ( ) {
185+ let ( fm, _) = parse_markdown (
186+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n feed-url: 'https://example.com/$(SECRET)/nuget'\n ---\n " ,
187+ )
188+ . unwrap ( ) ;
189+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
190+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
191+ assert ! ( ext. validate( & ctx_from( & fm) ) . is_err( ) ) ;
192+ }
193+
194+ #[ test]
195+ fn test_validate_version_injection_rejected ( ) {
196+ let ( fm, _) = parse_markdown (
197+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n version: '$(SECRET)'\n ---\n " ,
198+ )
199+ . unwrap ( ) ;
200+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
201+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
202+ assert ! ( ext. validate( & ctx_from( & fm) ) . is_err( ) ) ;
203+ }
204+
205+ #[ test]
206+ fn test_validate_global_json_sentinel_skips_injection_check ( ) {
207+ let ( fm, _) = parse_markdown (
208+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n version: 'global.json'\n ---\n " ,
209+ )
210+ . unwrap ( ) ;
211+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
212+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
213+ assert ! ( ext. validate( & ctx_from( & fm) ) . is_ok( ) ) ;
214+ }
215+
216+ #[ test]
217+ fn test_validate_global_json_conflict_bails ( ) {
218+ let tmp = tempfile:: tempdir ( ) . unwrap ( ) ;
219+ std:: fs:: write ( tmp. path ( ) . join ( "global.json" ) , r#"{"sdk":{"version":"8.0.100"}}"# ) . unwrap ( ) ;
220+
221+ let ( fm, _) = parse_markdown (
222+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n version: '9.0.x'\n ---\n " ,
223+ )
224+ . unwrap ( ) ;
225+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
226+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
227+ let ctx = CompileContext :: for_test_with_compile_dir ( & fm, tmp. path ( ) ) ;
228+ let err = ext. validate ( & ctx) . unwrap_err ( ) ;
229+ assert ! ( err. to_string( ) . contains( "global.json" ) ) ;
230+ }
231+
232+ #[ test]
233+ fn test_validate_global_json_sentinel_accepted_with_file_present ( ) {
234+ let tmp = tempfile:: tempdir ( ) . unwrap ( ) ;
235+ std:: fs:: write ( tmp. path ( ) . join ( "global.json" ) , r#"{"sdk":{"version":"8.0.100"}}"# ) . unwrap ( ) ;
236+
237+ let ( fm, _) = parse_markdown (
238+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n version: 'global.json'\n ---\n " ,
239+ )
240+ . unwrap ( ) ;
241+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
242+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
243+ let ctx = CompileContext :: for_test_with_compile_dir ( & fm, tmp. path ( ) ) ;
244+ assert ! ( ext. validate( & ctx) . is_ok( ) ) ;
245+ }
246+
247+ #[ test]
248+ fn test_validate_config_injection_rejected ( ) {
249+ let ( fm, _) = parse_markdown (
250+ "---\n name: test\n description: test\n runtimes:\n dotnet:\n config: '$(SECRET)/nuget.config'\n ---\n " ,
251+ )
252+ . unwrap ( ) ;
253+ let dotnet = fm. runtimes . as_ref ( ) . unwrap ( ) . dotnet . as_ref ( ) . unwrap ( ) ;
254+ let ext = DotnetExtension :: new ( dotnet. clone ( ) ) ;
255+ assert ! ( ext. validate( & ctx_from( & fm) ) . is_err( ) ) ;
256+ }
257+ }
0 commit comments