@@ -2427,3 +2427,125 @@ func TestAnalyze_headers_more(t *testing.T) {
24272427 })
24282428 }
24292429}
2430+
2431+ //nolint:funlen
2432+ func TestAnalyze_directiveSources (t * testing.T ) {
2433+ t .Parallel ()
2434+ // two self defined maps and matchFn to ensure it is a separate test
2435+ testDirectiveMap1 := map [string ][]uint {
2436+ "common_dir" : {ngxAnyConf | ngxConfTake1 },
2437+ "test_dir1" : {ngxAnyConf | ngxConfTake1 },
2438+ }
2439+ testSource1 := func (directive string ) ([]uint , bool ) {
2440+ masks , matched := testDirectiveMap1 [directive ]
2441+ return masks , matched
2442+ }
2443+
2444+ testDirectiveMap2 := map [string ][]uint {
2445+ "common_dir" : {ngxAnyConf | ngxConfTake2 },
2446+ "test_dir2" : {ngxAnyConf | ngxConfTake2 },
2447+ }
2448+ testSource2 := func (directive string ) ([]uint , bool ) {
2449+ masks , matched := testDirectiveMap2 [directive ]
2450+ return masks , matched
2451+ }
2452+
2453+ testcases := map [string ]struct {
2454+ stmt * Directive
2455+ ctx blockCtx
2456+ wantErr bool
2457+ }{
2458+ // The directive only found in source1 and satisfies the bitmask in it
2459+ "DirectiveFoundOnlyInSource1_pass" : {
2460+ & Directive {
2461+ Directive : "test_dir1" ,
2462+ Args : []string {"arg1" },
2463+ Line : 5 ,
2464+ },
2465+ blockCtx {"http" , "upstream" },
2466+ false ,
2467+ },
2468+ // The directive only found in source2 and satisfies the bitmask in it
2469+ "DirectiveFoundOnlyInSource2_pass" : {
2470+ & Directive {
2471+ Directive : "test_dir2" ,
2472+ Args : []string {"arg1" , "arg2" },
2473+ Line : 5 ,
2474+ },
2475+ blockCtx {"http" , "upstream" },
2476+ false ,
2477+ },
2478+ // The directive only found in source2 but not satisfies the bitmask in it
2479+ "DirectiveFoundOnlyInsource2_fail" : {
2480+ & Directive {
2481+ Directive : "test_dir2" ,
2482+ Args : []string {"arg1" },
2483+ Line : 5 ,
2484+ },
2485+ blockCtx {"http" , "upstream" },
2486+ true ,
2487+ },
2488+ // The directive found in both sources,
2489+ // but only satisfies bitmasks in source1 it should still pass validation
2490+ "DirectiveFoundInBothSources_pass_case1" : {
2491+ & Directive {
2492+ Directive : "common_dir" ,
2493+ Args : []string {"arg1" },
2494+ Line : 5 ,
2495+ },
2496+ blockCtx {"http" , "upstream" },
2497+ false ,
2498+ },
2499+ // The directive found in both Sources,
2500+ // but only satisfies bitmasks in source2 it should still pass validation
2501+ "DirectiveFoundInBothSources_pass_case2" : {
2502+ & Directive {
2503+ Directive : "common_dir" ,
2504+ Args : []string {"arg1" , "arg2" },
2505+ Line : 5 ,
2506+ },
2507+ blockCtx {"http" , "upstream" },
2508+ false ,
2509+ },
2510+ // The directive found in both sources,
2511+ // but doesn't satisfy bitmask in any of them
2512+ "DirectiveFoundInBothSources_fail" : {
2513+ & Directive {
2514+ Directive : "common_dir" ,
2515+ Args : []string {"arg1" , "arg2" , "arg3" },
2516+ Line : 5 ,
2517+ },
2518+ blockCtx {"http" , "upstream" },
2519+ true ,
2520+ },
2521+ // The directive not found in any source
2522+ "DirectiveNotFoundInAnySource_fail" : {
2523+ & Directive {
2524+ Directive : "no_exist" ,
2525+ Args : []string {},
2526+ Line : 5 ,
2527+ },
2528+ blockCtx {"http" , "location" },
2529+ true ,
2530+ },
2531+ }
2532+
2533+ for name , tc := range testcases {
2534+ tc := tc
2535+ t .Run (name , func (t * testing.T ) {
2536+ t .Parallel ()
2537+ err := analyze ("nginx.conf" , tc .stmt , ";" , tc .ctx , & ParseOptions {
2538+ DirectiveSources : []MatchFunc {testSource1 , testSource2 },
2539+ ErrorOnUnknownDirectives : true ,
2540+ })
2541+
2542+ if ! tc .wantErr && err != nil {
2543+ t .Fatal (err )
2544+ }
2545+
2546+ if tc .wantErr && err == nil {
2547+ t .Fatal ("expected error, got nil" )
2548+ }
2549+ })
2550+ }
2551+ }
0 commit comments