@@ -54,6 +54,7 @@ public class SpecializationE2ETests
54
54
private static readonly string _dotnetIsolated60Path = Path . GetFullPath ( $@ "..\..\DotNetIsolated60\{ TestHelpers . BuildConfig } ") ;
55
55
private static readonly string _dotnetIsolatedUnsuppportedPath = Path . GetFullPath ( $@ "..\..\DotNetIsolatedUnsupportedWorker\{ TestHelpers . BuildConfig } ") ;
56
56
private static readonly string _dotnetIsolatedEmptyScriptRoot = Path . GetFullPath ( @"..\..\..\..\EmptyScriptRoot" ) ;
57
+ private static readonly string _dotnetCustomHandlerPath = Path . GetFullPath ( $@ "..\..\DotNetCustomHandler\{ TestHelpers . BuildConfig } ") ;
57
58
58
59
private static Action < IServiceCollection > _customizeScriptHostServices ;
59
60
@@ -800,6 +801,57 @@ public async Task Specialization_JobHostInternalStorageOptionsUpdatesWithActiveH
800
801
}
801
802
}
802
803
804
+ [ Theory ]
805
+ [ InlineData ( ScriptConstants . FlexConsumptionSku , ScriptConstants . FeatureFlagEnableMcpCustomHandlerPreview , true ) ]
806
+ [ InlineData ( ScriptConstants . FlexConsumptionSku , $ "Feature1,{ ScriptConstants . FeatureFlagEnableMcpCustomHandlerPreview } ", true ) ]
807
+ [ InlineData ( ScriptConstants . FlexConsumptionSku , "Feature1" , false ) ]
808
+ [ InlineData ( ScriptConstants . FlexConsumptionSku , null , false ) ]
809
+ [ InlineData ( ScriptConstants . DynamicSku , null , false ) ]
810
+ [ InlineData ( ScriptConstants . DynamicSku , ScriptConstants . FeatureFlagEnableMcpCustomHandlerPreview , false ) ]
811
+ [ InlineData ( ScriptConstants . DynamicSku , $ "Feature1,{ ScriptConstants . FeatureFlagEnableMcpCustomHandlerPreview } ", false ) ]
812
+ [ InlineData ( ScriptConstants . ElasticPremiumSku , null , false ) ]
813
+ [ InlineData ( ScriptConstants . ElasticPremiumSku , $ "Feature1,{ ScriptConstants . FeatureFlagEnableMcpCustomHandlerPreview } ", false ) ]
814
+ [ InlineData ( "" , null , false ) ]
815
+ public async Task Specialization_FlexSku_McpPreview_SetsWorkerRuntimeToCustom ( string websiteSku , string featureFlags , bool isExpectedToResetWorkerRuntime )
816
+ {
817
+ var environmentVariables = new Dictionary < string , string >
818
+ {
819
+ { EnvironmentSettingNames . AzureWebsiteSku , websiteSku }
820
+ } ;
821
+ var builder = InitializeDotNetIsolatedPlaceholderBuilder ( _dotnetCustomHandlerPath , environmentVariables , "SimpleHttpTrigger" ) ;
822
+
823
+ using var testServer = new TestServer ( builder ) ;
824
+ var client = testServer . CreateClient ( ) ;
825
+ var response = await client . GetAsync ( "api/warmup" ) ;
826
+ response . EnsureSuccessStatusCode ( ) ;
827
+
828
+ // Validate that the channel is set up with native worker
829
+ var webChannelManager = testServer . Services . GetService < IWebHostRpcWorkerChannelManager > ( ) ;
830
+ var placeholderChannel = await webChannelManager . GetChannels ( "dotnet-isolated" ) . Single ( ) . Value . Task ;
831
+ Assert . Contains ( "FunctionsNetHost.exe" , placeholderChannel . WorkerProcess . Process . StartInfo . FileName ) ;
832
+ Assert . NotNull ( placeholderChannel . WorkerProcess . Process . Id ) ;
833
+
834
+ _environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebJobsFeatureFlags , featureFlags ) ;
835
+ _environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteContainerReady , "1" ) ;
836
+ _environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsitePlaceholderMode , "0" ) ;
837
+
838
+ response = await client . GetAsync ( "api/SimpleHttpTrigger" ) ;
839
+ response . EnsureSuccessStatusCode ( ) ;
840
+
841
+ var log = _loggerProvider . GetLog ( ) ;
842
+
843
+ if ( isExpectedToResetWorkerRuntime )
844
+ {
845
+ // Verify expected logs when running the custom handler executable.
846
+ Assert . Contains ( "MCP custom handler preview is enabled. Setting FUNCTIONS_WORKER_RUNTIME to 'custom'" , log ) ;
847
+ Assert . Contains ( "Mapped function route 'api/SimpleHttpTrigger'" , log ) ;
848
+ }
849
+ else
850
+ {
851
+ Assert . DoesNotContain ( "MCP custom handler preview is enabled. Setting FUNCTIONS_WORKER_RUNTIME to 'custom'" , log ) ;
852
+ }
853
+ }
854
+
803
855
[ Fact ]
804
856
public async Task DotNetIsolated_PlaceholderHit ( )
805
857
{
@@ -865,7 +917,7 @@ public async Task ResponseCompressionWorksAfterSpecialization(string acceptEncod
865
917
866
918
_environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteContainerReady , "1" ) ;
867
919
_environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsitePlaceholderMode , "0" ) ;
868
- _environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebJobsFeatureFlags , ScriptConstants . FeatureFlagEnableResponseCompression ) ;
920
+ _environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebJobsFeatureFlags , ScriptConstants . FeatureFlagEnableResponseCompression ) ;
869
921
870
922
response = await client . GetAsync ( "api/HttpRequestDataFunction" ) ;
871
923
response . EnsureSuccessStatusCode ( ) ;
@@ -1216,12 +1268,25 @@ private async Task DotNetIsolatedPlaceholderMiss(string scriptRootPath, Action a
1216
1268
}
1217
1269
1218
1270
private IWebHostBuilder InitializeDotNetIsolatedPlaceholderBuilder ( string scriptRootPath , params string [ ] functions )
1271
+ {
1272
+ return InitializeDotNetIsolatedPlaceholderBuilder ( scriptRootPath , null , functions ) ;
1273
+ }
1274
+
1275
+ private IWebHostBuilder InitializeDotNetIsolatedPlaceholderBuilder ( string scriptRootPath , Dictionary < string , string > environmentVariables , params string [ ] functions )
1219
1276
{
1220
1277
_environment . SetEnvironmentVariable ( EnvironmentSettingNames . FunctionWorkerRuntime , "dotnet-isolated" ) ;
1221
1278
_environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebsiteUsePlaceholderDotNetIsolated , "1" ) ;
1222
1279
_environment . SetEnvironmentVariable ( EnvironmentSettingNames . AzureWebJobsFeatureFlags , ScriptConstants . FeatureFlagEnableWorkerIndexing ) ;
1223
1280
_environment . SetEnvironmentVariable ( RpcWorkerConstants . FunctionWorkerRuntimeVersionSettingName , "6.0" ) ;
1224
1281
1282
+ if ( environmentVariables is not null )
1283
+ {
1284
+ foreach ( var ( key , value ) in environmentVariables )
1285
+ {
1286
+ _environment . SetEnvironmentVariable ( key , value ) ;
1287
+ }
1288
+ }
1289
+
1225
1290
var builder = CreateStandbyHostBuilder ( functions ) ;
1226
1291
1227
1292
builder . ConfigureAppConfiguration ( config =>
0 commit comments