@@ -182,6 +182,7 @@ public async Task GetExtensionsStartupTypes_AcceptsRequiredBundleVersions(string
182182 Assert . True ( traces . Any ( m => m . FormattedMessage . Contains ( $ "Loading extension bundle") ) ) ;
183183 }
184184 Assert . True ( traces . Any ( m => m . FormattedMessage . Contains ( $ "Loading startup extension 'Storage") ) ) ;
185+ AssertNoErrors ( traces ) ;
185186 }
186187 }
187188
@@ -310,6 +311,7 @@ public async Task GetExtensionsStartupTypes_AcceptsRequiredExtensionVersions(str
310311 {
311312 Assert . True ( traces . Any ( m => m . FormattedMessage . Contains ( $ "Loading startup extension 'Storage") ) ) ;
312313 }
314+ AssertNoErrors ( traces ) ;
313315 }
314316 }
315317
@@ -423,6 +425,7 @@ void CopyToBin(string path)
423425 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . Single ( ) . FullName ) ;
424426 Assert . True ( traces . Any ( m => string . Equals ( m . FormattedMessage , $ "The extension startup type '{ references [ 0 ] . TypeName } ' belongs to a builtin extension") ) ) ;
425427 Assert . True ( traces . Any ( m => string . Equals ( m . FormattedMessage , $ "The extension startup type '{ references [ 1 ] . TypeName } ' belongs to a builtin extension") ) ) ;
428+ AssertNoErrors ( traces ) ;
426429 }
427430 }
428431
@@ -516,6 +519,7 @@ void CopyToBin(string path)
516519 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . Single ( ) . FullName ) ;
517520 Assert . True ( traces . Any ( m => string . Equals ( m . FormattedMessage , $ "The extension startup type '{ references [ 0 ] . TypeName } ' belongs to a builtin extension") ) ) ;
518521 Assert . True ( traces . Any ( m => string . Equals ( m . FormattedMessage , $ "The extension startup type '{ references [ 1 ] . TypeName } ' belongs to a builtin extension") ) ) ;
522+ AssertNoErrors ( traces ) ;
519523 }
520524 }
521525
@@ -592,11 +596,13 @@ void CopyToBin(string path)
592596
593597 // Act
594598 var types = await discoverer . GetExtensionsStartupTypesAsync ( ) ;
599+ var traces = testLoggerProvider . GetAllLogMessages ( ) ;
595600
596601 // Assert
597602 AreExpectedMetricsGenerated ( testMetricsLogger ) ;
598603 Assert . Equal ( types . Count ( ) , 2 ) ;
599604 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . FirstOrDefault ( ) . FullName ) ;
605+ AssertNoErrors ( traces ) ;
600606 }
601607 }
602608
@@ -644,11 +650,13 @@ void CopyToBin(string path)
644650
645651 // Act
646652 var types = await discoverer . GetExtensionsStartupTypesAsync ( ) ;
653+ var traces = testLoggerProvider . GetAllLogMessages ( ) ;
647654
648655 // Assert
649656 AreExpectedMetricsGenerated ( testMetricsLogger ) ;
650657 Assert . Single ( types ) ;
651658 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . Single ( ) . FullName ) ;
659+ AssertNoErrors ( traces ) ;
652660 }
653661 }
654662
@@ -698,11 +706,13 @@ void CopyToBin(string path)
698706
699707 // Act
700708 var types = await discoverer . GetExtensionsStartupTypesAsync ( ) ;
709+ var traces = testLoggerProvider . GetAllLogMessages ( ) ;
701710
702711 //Assert
703712 AreExpectedMetricsGenerated ( testMetricsLogger ) ;
704713 Assert . Single ( types ) ;
705714 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . Single ( ) . FullName ) ;
715+ AssertNoErrors ( traces ) ;
706716 }
707717 }
708718
@@ -1144,13 +1154,55 @@ void CopyToBin(string path)
11441154
11451155 // Act
11461156 var types = await discoverer . GetExtensionsStartupTypesAsync ( ) ;
1157+ var traces = testLoggerProvider . GetAllLogMessages ( ) ;
11471158 Environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebJobsFeatureFlags , null ) ;
11481159 Environment . SetEnvironmentVariable ( EnvironmentSettingNames . FunctionWorkerRuntime , null ) ;
11491160
11501161 //Assert that filtering did not take place because of worker indexing
11511162 Assert . True ( types . Count ( ) == 1 ) ;
11521163 Assert . Equal ( typeof ( AzureStorageWebJobsStartup ) . FullName , types . ElementAt ( 0 ) . FullName ) ;
1164+ AssertNoErrors ( traces ) ;
1165+ }
1166+ }
1167+
1168+ [ Fact ]
1169+ public async Task GetExtensionsStartupTypes_EmptyExtensionsArray ( )
1170+ {
1171+ TestMetricsLogger testMetricsLogger = new TestMetricsLogger ( ) ;
1172+
1173+ using var directory = new TempDirectory ( ) ;
1174+ var binPath = Path . Combine ( directory . Path , "bin" ) ;
1175+ Directory . CreateDirectory ( binPath ) ;
1176+
1177+ // extensions.json file with an empty extensions array (simulating extensions.json produced by in-proc app)
1178+ string extensionJson = """
1179+ {
1180+ "extensions": []
11531181 }
1182+ """ ;
1183+ File . WriteAllText ( Path . Combine ( binPath , "extensions.json" ) , extensionJson ) ;
1184+
1185+ TestLoggerProvider testLoggerProvider = new TestLoggerProvider ( ) ;
1186+ LoggerFactory factory = new LoggerFactory ( ) ;
1187+ factory . AddProvider ( testLoggerProvider ) ;
1188+ var testLogger = factory . CreateLogger < ScriptStartupTypeLocator > ( ) ;
1189+
1190+ var mockExtensionBundleManager = new Mock < IExtensionBundleManager > ( ) ;
1191+ mockExtensionBundleManager . Setup ( e => e . IsExtensionBundleConfigured ( ) ) . Returns ( true ) ;
1192+ mockExtensionBundleManager . Setup ( e => e . GetExtensionBundleDetails ( ) ) . Returns ( Task . FromResult ( new ExtensionBundleDetails ( ) { Id = "bundleID" , Version = "1.0.0" } ) ) ;
1193+ mockExtensionBundleManager . Setup ( e => e . GetExtensionBundleBinPathAsync ( ) ) . Returns ( Task . FromResult ( binPath ) ) ;
1194+
1195+ var languageWorkerOptions = new TestOptionsMonitor < LanguageWorkerOptions > ( new LanguageWorkerOptions ( ) ) ;
1196+ var mockFunctionMetadataManager = GetTestFunctionMetadataManager ( languageWorkerOptions ) ;
1197+ OptionsWrapper < ExtensionRequirementOptions > optionsWrapper = new ( new ExtensionRequirementOptions ( ) ) ;
1198+ var discoverer = new ScriptStartupTypeLocator ( directory . Path , testLogger , mockExtensionBundleManager . Object , mockFunctionMetadataManager , testMetricsLogger , optionsWrapper ) ;
1199+
1200+ var types = await discoverer . GetExtensionsStartupTypesAsync ( ) ;
1201+ var traces = testLoggerProvider . GetAllLogMessages ( ) ;
1202+
1203+ AreExpectedMetricsGenerated ( testMetricsLogger ) ;
1204+ Assert . Empty ( types ) ; // Ensure no types are loaded because the extensions array is empty
1205+ AssertNoErrors ( traces ) ;
11541206 }
11551207
11561208 private IFunctionMetadataManager GetTestFunctionMetadataManager ( IOptionsMonitor < LanguageWorkerOptions > options , ICollection < FunctionMetadata > metadataCollection = null , bool hasPrecompiledFunction = false , bool hasNodeFunctions = false , bool hasDotnetIsolatedFunctions = false )
@@ -1234,5 +1286,10 @@ private ILogger<ScriptStartupTypeLocator> GetTestLogger()
12341286 var testLogger = factory . CreateLogger < ScriptStartupTypeLocator > ( ) ;
12351287 return testLogger ;
12361288 }
1289+
1290+ private static void AssertNoErrors ( IList < LogMessage > traces )
1291+ {
1292+ Assert . False ( traces . Any ( m => m . Level == LogLevel . Error || m . Level == LogLevel . Critical ) ) ;
1293+ }
12371294 }
12381295}
0 commit comments