@@ -498,6 +498,140 @@ public void Constructor_WithCreateHostSecretsIfMissingSet_CreatesHostSecret()
498
498
}
499
499
}
500
500
501
+ [ Fact ]
502
+ public async Task GetHostSecretsAsync_WaitsForNewSecrets ( )
503
+ {
504
+ using ( var directory = new TempDirectory ( ) )
505
+ {
506
+ string hostSecretsJson = @"{
507
+ 'masterKey': {
508
+ 'name': 'master',
509
+ 'value': '1234',
510
+ 'encrypted': false
511
+ },
512
+ 'functionKeys': [],
513
+ 'systemKeys': []
514
+ }" ;
515
+ string filePath = Path . Combine ( directory . Path , ScriptConstants . HostMetadataFileName ) ;
516
+ File . WriteAllText ( filePath , hostSecretsJson ) ;
517
+
518
+ HostSecretsInfo hostSecrets = null ;
519
+ var traceWriter = new TestTraceWriter ( TraceLevel . Verbose ) ;
520
+ ISecretsRepository repository = new FileSystemSecretsRepository ( directory . Path ) ;
521
+
522
+ using ( var secretManager = new SecretManager ( _settingsManager , repository , traceWriter , null ) )
523
+ {
524
+ await Task . WhenAll (
525
+ Task . Run ( async ( ) =>
526
+ {
527
+ // Lock the file
528
+ using ( FileStream fs = new FileStream ( filePath , FileMode . Open , FileAccess . Write ) )
529
+ {
530
+ await Task . Delay ( 500 ) ;
531
+ }
532
+ } ) ,
533
+ Task . Run ( async ( ) =>
534
+ {
535
+ await Task . Delay ( 100 ) ;
536
+ hostSecrets = await secretManager . GetHostSecretsAsync ( ) ;
537
+ } ) ) ;
538
+
539
+ Assert . Equal ( hostSecrets . MasterKey , "1234" ) ;
540
+ }
541
+
542
+ using ( var secretManager = new SecretManager ( _settingsManager , repository , traceWriter , null ) )
543
+ {
544
+ await Assert . ThrowsAsync < IOException > ( async ( ) =>
545
+ {
546
+ await Task . WhenAll (
547
+ Task . Run ( async ( ) =>
548
+ {
549
+ // Lock the file
550
+ using ( FileStream fs = new FileStream ( filePath , FileMode . Open , FileAccess . Write ) )
551
+ {
552
+ await Task . Delay ( 3000 ) ;
553
+ }
554
+ } ) ,
555
+ Task . Run ( async ( ) =>
556
+ {
557
+ await Task . Delay ( 100 ) ;
558
+ hostSecrets = await secretManager . GetHostSecretsAsync ( ) ;
559
+ } ) ) ;
560
+ } ) ;
561
+ }
562
+ }
563
+ }
564
+
565
+ [ Fact ]
566
+ public async Task GetFunctionSecretsAsync_WaitsForNewSecrets ( )
567
+ {
568
+ using ( var directory = new TempDirectory ( ) )
569
+ {
570
+ string functionName = "testfunction" ;
571
+ string functionSecretsJson =
572
+ @"{
573
+ 'keys': [
574
+ {
575
+ 'name': 'Key1',
576
+ 'value': 'FunctionValue1',
577
+ 'encrypted': false
578
+ },
579
+ {
580
+ 'name': 'Key2',
581
+ 'value': 'FunctionValue2',
582
+ 'encrypted': false
583
+ }
584
+ ]
585
+ }" ;
586
+ string filePath = Path . Combine ( directory . Path , functionName + ".json" ) ;
587
+ File . WriteAllText ( filePath , functionSecretsJson ) ;
588
+
589
+ IDictionary < string , string > functionSecrets = null ;
590
+ var traceWriter = new TestTraceWriter ( TraceLevel . Verbose ) ;
591
+ ISecretsRepository repository = new FileSystemSecretsRepository ( directory . Path ) ;
592
+ using ( var secretManager = new SecretManager ( _settingsManager , repository , traceWriter , null ) )
593
+ {
594
+ await Task . WhenAll (
595
+ Task . Run ( async ( ) =>
596
+ {
597
+ // Lock the file
598
+ using ( FileStream fs = new FileStream ( filePath , FileMode . Open , FileAccess . Write ) )
599
+ {
600
+ await Task . Delay ( 500 ) ;
601
+ }
602
+ } ) ,
603
+ Task . Run ( async ( ) =>
604
+ {
605
+ await Task . Delay ( 100 ) ;
606
+ functionSecrets = await secretManager . GetFunctionSecretsAsync ( functionName ) ;
607
+ } ) ) ;
608
+
609
+ Assert . Equal ( functionSecrets [ "Key1" ] , "FunctionValue1" ) ;
610
+ }
611
+
612
+ using ( var secretManager = new SecretManager ( _settingsManager , repository , traceWriter , null ) )
613
+ {
614
+ await Assert . ThrowsAsync < IOException > ( async ( ) =>
615
+ {
616
+ await Task . WhenAll (
617
+ Task . Run ( async ( ) =>
618
+ {
619
+ // Lock the file
620
+ using ( FileStream fs = new FileStream ( filePath , FileMode . Open , FileAccess . Write ) )
621
+ {
622
+ await Task . Delay ( 3000 ) ;
623
+ }
624
+ } ) ,
625
+ Task . Run ( async ( ) =>
626
+ {
627
+ await Task . Delay ( 100 ) ;
628
+ functionSecrets = await secretManager . GetFunctionSecretsAsync ( functionName ) ;
629
+ } ) ) ;
630
+ } ) ;
631
+ }
632
+ }
633
+ }
634
+
501
635
private Mock < IKeyValueConverterFactory > GetConverterFactoryMock ( bool simulateWriteConversion = true , bool setStaleValue = true )
502
636
{
503
637
var mockValueReader = new Mock < IKeyValueReader > ( ) ;
0 commit comments