2121using System . Text ;
2222using System . Threading ;
2323using System . Threading . Tasks ;
24+ using FirebirdSql . Data . Common ;
2425using FirebirdSql . Data . TestsBase ;
2526using NUnit . Framework ;
2627
@@ -30,6 +31,16 @@ namespace FirebirdSql.Data.FirebirdClient.Tests
3031 [ TestFixtureSource ( typeof ( FbServerTypeTestFixtureSource ) , nameof ( FbServerTypeTestFixtureSource . Embedded ) ) ]
3132 public class FbCommandTests : FbTestsBase
3233 {
34+ const string FiniteInfiniteLoopCommand =
35+ @"execute block as
36+ declare variable start_time timestamp;
37+ begin
38+ start_time = cast('now' as timestamp);
39+ while (datediff(second from start_time to cast('now' as timestamp)) <= 10) do
40+ begin
41+ end
42+ end" ;
43+
3344 public FbCommandTests ( FbServerType serverType , bool compression , FbWireCrypt wireCrypt )
3445 : base ( serverType , compression , wireCrypt )
3546 { }
@@ -559,45 +570,6 @@ public async Task ReadingCharOctetsTest()
559570 }
560571 }
561572
562- [ Test ]
563- public async Task CommandCancellationTest ( )
564- {
565- if ( ! await EnsureVersion ( new Version ( 2 , 5 , 0 , 0 ) ) )
566- return ;
567-
568- var cancelled = false ;
569- await using ( var cmd = Connection . CreateCommand ( ) )
570- {
571- cmd . CommandText =
572- @"execute block as
573- declare variable start_time timestamp;
574- begin
575- start_time = cast('now' as timestamp);
576- while (datediff(second from start_time to cast('now' as timestamp)) <= 10) do
577- begin
578- end
579- end" ;
580- async Task Execute ( )
581- {
582- await Task . Yield ( ) ;
583- try
584- {
585- await cmd . ExecuteNonQueryAsync ( ) ;
586- }
587- catch ( FbException ex )
588- {
589- cancelled = "HY008" == ex . SQLSTATE ;
590- }
591- }
592- var executeTask = Execute ( ) ;
593- Thread . Sleep ( 2000 ) ;
594- cmd . Cancel ( ) ;
595- Thread . Sleep ( 2000 ) ;
596- await executeTask ;
597- }
598- Assert . IsTrue ( cancelled ) ;
599- }
600-
601573 [ Test ]
602574 public async Task GetCommandPlanTest ( )
603575 {
@@ -714,5 +686,92 @@ public async Task ExecuteNonQueryReturnsMinusOneOnNonInsertUpdateDelete()
714686 Assert . AreEqual ( - 1 , ra ) ;
715687 }
716688 }
689+
690+ [ Test ]
691+ public async Task CommandCancellationDirectTest ( )
692+ {
693+ if ( ! await EnsureVersion ( new Version ( 2 , 5 , 0 , 0 ) ) )
694+ return ;
695+
696+ await using ( var cmd = Connection . CreateCommand ( ) )
697+ {
698+ cmd . CommandText = FiniteInfiniteLoopCommand ;
699+ async Task Execute ( )
700+ {
701+ await Task . Yield ( ) ;
702+ await cmd . ExecuteNonQueryAsync ( ) ;
703+ }
704+ var executeTask = Execute ( ) ;
705+ Thread . Sleep ( 2000 ) ;
706+ cmd . Cancel ( ) ;
707+ Thread . Sleep ( 2000 ) ;
708+ Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await executeTask ) ;
709+ }
710+ }
711+
712+ [ Test ]
713+ public async Task CommandCancellationCancellationTokenTest ( )
714+ {
715+ if ( ! await EnsureVersion ( new Version ( 2 , 5 , 0 , 0 ) ) )
716+ return ;
717+
718+ using ( var cts = new CancellationTokenSource ( ) )
719+ {
720+ await using ( var cmd = Connection . CreateCommand ( ) )
721+ {
722+ cmd . CommandText = FiniteInfiniteLoopCommand ;
723+ async Task Execute ( CancellationToken cancellationToken )
724+ {
725+ await Task . Yield ( ) ;
726+ await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
727+ }
728+ var executeTask = Execute ( cts . Token ) ;
729+ Thread . Sleep ( 2000 ) ;
730+ cts . Cancel ( ) ;
731+ Thread . Sleep ( 2000 ) ;
732+ Assert . ThrowsAsync < OperationCanceledException > ( async ( ) => await executeTask ) ;
733+ }
734+ }
735+ }
736+
737+ [ Test ]
738+ public async Task CommandUsableAfterCancellationTest ( )
739+ {
740+ if ( ! await EnsureVersion ( new Version ( 2 , 5 , 0 , 0 ) ) )
741+ return ;
742+
743+ using ( var cts = new CancellationTokenSource ( ) )
744+ {
745+ await using ( var cmd = Connection . CreateCommand ( ) )
746+ {
747+ cmd . CommandText = FiniteInfiniteLoopCommand ;
748+ async Task Execute ( CancellationToken cancellationToken )
749+ {
750+ await Task . Yield ( ) ;
751+ await cmd . ExecuteNonQueryAsync ( cancellationToken ) ;
752+ }
753+ var executeTask = Execute ( cts . Token ) ;
754+ Thread . Sleep ( 2000 ) ;
755+ cts . Cancel ( ) ;
756+ Thread . Sleep ( 2000 ) ;
757+ try
758+ {
759+ await executeTask ;
760+ }
761+ catch ( OperationCanceledException )
762+ { }
763+ cmd . CommandText = "select 1 from rdb$database union all select 6 from rdb$database" ;
764+ await using ( var reader = await cmd . ExecuteReaderAsync ( ) )
765+ {
766+ var result = new List < int > ( ) ;
767+ while ( await reader . ReadAsync ( ) )
768+ {
769+ result . Add ( reader . GetInt32 ( 0 ) ) ;
770+ }
771+ CollectionAssert . AreEqual ( new [ ] { 1 , 6 } , result ) ;
772+ }
773+ }
774+ }
775+ }
717776 }
718777}
0 commit comments