@@ -3556,6 +3556,9 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
3556
3556
return ret .resp , ret .err
3557
3557
}).Times (3 )
3558
3558
3559
+ // There will be a call to CloseSend to close the stream
3560
+ mockReadBytesClient .EXPECT ().CloseSend ().Return (nil ).Times (1 )
3561
+
3559
3562
// Act
3560
3563
request := providers.ReadStateBytesRequest {
3561
3564
TypeName : expectedReq .TypeName ,
@@ -3704,7 +3707,7 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
3704
3707
// Define what will be returned by each call to Recv
3705
3708
mockReadBytesClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {
3706
3709
Diagnostics : []* proto.Diagnostic {
3707
- & proto. Diagnostic {
3710
+ {
3708
3711
Severity : proto .Diagnostic_ERROR ,
3709
3712
Summary : "Error from test" ,
3710
3713
Detail : "This error is forced by the test case" ,
@@ -3752,15 +3755,44 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
3752
3755
).Return (mockReadBytesClient , nil )
3753
3756
3754
3757
// Define what will be returned by each call to Recv
3755
- mockReadBytesClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {
3756
- Diagnostics : []* proto.Diagnostic {
3757
- & proto.Diagnostic {
3758
- Severity : proto .Diagnostic_WARNING ,
3759
- Summary : "Warning from test" ,
3760
- Detail : "This warning is forced by the test case" ,
3758
+ chunk := "hello world"
3759
+ totalLength := len (chunk )
3760
+ mockResp := map [int ]struct {
3761
+ resp * proto.ReadStateBytes_Response
3762
+ err error
3763
+ }{
3764
+ 0 : {
3765
+ resp : & proto.ReadStateBytes_Response {
3766
+ Bytes : []byte (chunk ),
3767
+ TotalLength : int64 (totalLength ),
3768
+ Range : & proto.StateRange {
3769
+ Start : 0 ,
3770
+ End : int64 (len (chunk )),
3771
+ },
3772
+ Diagnostics : []* proto.Diagnostic {
3773
+ {
3774
+ Severity : proto .Diagnostic_WARNING ,
3775
+ Summary : "Warning from test" ,
3776
+ Detail : "This warning is forced by the test case" ,
3777
+ },
3778
+ },
3761
3779
},
3780
+ err : nil ,
3781
+ },
3782
+ 1 : {
3783
+ resp : & proto.ReadStateBytes_Response {},
3784
+ err : io .EOF ,
3762
3785
},
3763
- }, io .EOF )
3786
+ }
3787
+ var count int
3788
+ mockReadBytesClient .EXPECT ().Recv ().DoAndReturn (func () (* proto.ReadStateBytes_Response , error ) {
3789
+ ret := mockResp [count ]
3790
+ count ++
3791
+ return ret .resp , ret .err
3792
+ }).Times (2 )
3793
+
3794
+ // There will be a call to CloseSend to close the stream
3795
+ mockReadBytesClient .EXPECT ().CloseSend ().Return (nil ).Times (1 )
3764
3796
3765
3797
// Act
3766
3798
request := providers.ReadStateBytesRequest {
@@ -3775,8 +3807,8 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
3775
3807
if resp .Diagnostics .ErrWithWarnings ().Error () != expectedWarn {
3776
3808
t .Fatalf ("expected warning diagnostic %q, but got: %q" , expectedWarn , resp .Diagnostics .ErrWithWarnings ().Error ())
3777
3809
}
3778
- if len (resp .Bytes ) ! = 0 {
3779
- t .Fatalf ("expected data to be omitted in error condition , but got: %q" , string ( resp . Bytes ) )
3810
+ if len (resp .Bytes ) = = 0 {
3811
+ t .Fatal ("expected data to included despite warnings , but got no bytes" )
3780
3812
}
3781
3813
})
3782
3814
@@ -3820,6 +3852,51 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
3820
3852
t .Fatalf ("expected data to be omitted in error condition, but got: %q" , string (resp .Bytes ))
3821
3853
}
3822
3854
})
3855
+
3856
+ t .Run ("when closing the stream, grpc errors are surfaced via diagnostics" , func (t * testing.T ) {
3857
+ client := mockProviderClient (t )
3858
+ p := & GRPCProvider {
3859
+ client : client ,
3860
+ ctx : context .Background (),
3861
+ }
3862
+
3863
+ // Call to ReadStateBytes
3864
+ // > Assert the arguments received
3865
+ // > Define the returned mock client
3866
+ mockClient := mockReadStateBytesClient (t )
3867
+ expectedReq := & proto.ReadStateBytes_Request {
3868
+ TypeName : "mock_store" ,
3869
+ StateId : backend .DefaultStateName ,
3870
+ }
3871
+ client .EXPECT ().ReadStateBytes (
3872
+ gomock .Any (),
3873
+ gomock .Eq (expectedReq ),
3874
+ ).Return (mockClient , nil )
3875
+
3876
+ // Sufficient mocking of Recv to get to the call to CloseSend
3877
+ mockClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {}, io .EOF )
3878
+
3879
+ // Force a gRPC error from CloseSend
3880
+ mockError := errors .New ("grpc error forced in test" )
3881
+ mockClient .EXPECT ().CloseSend ().Return (mockError ).Times (1 )
3882
+
3883
+ // Act
3884
+ request := providers.ReadStateBytesRequest {
3885
+ TypeName : expectedReq .TypeName ,
3886
+ StateId : expectedReq .StateId ,
3887
+ }
3888
+ resp := p .ReadStateBytes (request )
3889
+
3890
+ // Assert returned values
3891
+ checkDiagsHasError (t , resp .Diagnostics )
3892
+ wantErr := fmt .Sprintf ("Plugin error: The plugin returned an unexpected error from plugin6.(*GRPCProvider).ReadStateBytes: %s" , mockError )
3893
+ if resp .Diagnostics .Err ().Error () != wantErr {
3894
+ t .Fatalf ("expected error diagnostic %q, but got: %q" , wantErr , resp .Diagnostics .Err ())
3895
+ }
3896
+ if len (resp .Bytes ) != 0 {
3897
+ t .Fatalf ("expected data to be omitted in error condition, but got: %q" , string (resp .Bytes ))
3898
+ }
3899
+ })
3823
3900
}
3824
3901
3825
3902
func TestGRPCProvider_WriteStateBytes (t * testing.T ) {
0 commit comments