@@ -284,6 +284,97 @@ func TestRealWorldModuleMapping(t *testing.T) {
284
284
}
285
285
}
286
286
287
+ func TestAddLoadedDynamicModules (t * testing.T ) {
288
+ // Test scenario: modules loaded via load_module but not in configure args
289
+ // This simulates the real-world case where external modules are installed
290
+ // and loaded dynamically without being compiled into nginx
291
+
292
+ // We can't directly test addLoadedDynamicModules since it depends on getNginxT()
293
+ // But we can test the logic by simulating the behavior
294
+
295
+ testLoadModuleOutput := `
296
+ # Configuration file /etc/nginx/modules-enabled/50-mod-stream.conf:
297
+ load_module modules/ngx_stream_module.so;
298
+ # Configuration file /etc/nginx/modules-enabled/70-mod-stream-geoip2.conf:
299
+ load_module modules/ngx_stream_geoip2_module.so;
300
+ load_module "modules/ngx_http_geoip2_module.so";
301
+ `
302
+
303
+ // Test the regex and normalization logic
304
+ loadModuleRe := GetLoadModuleRegex ()
305
+ matches := loadModuleRe .FindAllStringSubmatch (testLoadModuleOutput , - 1 )
306
+
307
+ expectedModules := map [string ]bool {
308
+ "stream" : false ,
309
+ "stream_geoip2" : false ,
310
+ "http_geoip2" : false ,
311
+ }
312
+
313
+ t .Logf ("Found %d load_module matches" , len (matches ))
314
+
315
+ for _ , match := range matches {
316
+ if len (match ) > 1 {
317
+ loadModuleName := match [1 ]
318
+ normalizedName := normalizeModuleNameFromLoadModule (loadModuleName )
319
+
320
+ t .Logf ("Load module: %s -> normalized: %s" , loadModuleName , normalizedName )
321
+
322
+ if _ , expected := expectedModules [normalizedName ]; expected {
323
+ expectedModules [normalizedName ] = true
324
+ } else {
325
+ t .Errorf ("Unexpected module found: %s (from %s)" , normalizedName , loadModuleName )
326
+ }
327
+ }
328
+ }
329
+
330
+ // Check that all expected modules were found
331
+ for moduleName , found := range expectedModules {
332
+ if ! found {
333
+ t .Errorf ("Expected module %s was not found" , moduleName )
334
+ }
335
+ }
336
+ }
337
+
338
+ func TestExternalModuleDiscovery (t * testing.T ) {
339
+ // Test the complete normalization pipeline for external modules
340
+ testCases := []struct {
341
+ name string
342
+ loadModuleName string
343
+ expectedResult string
344
+ }{
345
+ {
346
+ name : "stream_geoip2 module" ,
347
+ loadModuleName : "ngx_stream_geoip2_module" ,
348
+ expectedResult : "stream_geoip2" ,
349
+ },
350
+ {
351
+ name : "http_geoip2 module" ,
352
+ loadModuleName : "ngx_http_geoip2_module" ,
353
+ expectedResult : "http_geoip2" ,
354
+ },
355
+ {
356
+ name : "custom third-party module" ,
357
+ loadModuleName : "ngx_http_custom_module" ,
358
+ expectedResult : "http_custom" ,
359
+ },
360
+ {
361
+ name : "simple module name" ,
362
+ loadModuleName : "ngx_custom_module" ,
363
+ expectedResult : "custom" ,
364
+ },
365
+ }
366
+
367
+ for _ , tc := range testCases {
368
+ t .Run (tc .name , func (t * testing.T ) {
369
+ result := normalizeModuleNameFromLoadModule (tc .loadModuleName )
370
+ if result != tc .expectedResult {
371
+ t .Errorf ("normalizeModuleNameFromLoadModule(%s) = %s, expected %s" ,
372
+ tc .loadModuleName , result , tc .expectedResult )
373
+ }
374
+ })
375
+ }
376
+ }
377
+
287
378
func TestGetModuleMapping (t * testing.T ) {
288
379
// This test verifies that GetModuleMapping function works without errors
289
380
// Since it depends on nginx being available, we'll just test that it doesn't panic
0 commit comments