@@ -2624,6 +2624,9 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
2624
2624
return ret .resp , ret .err
2625
2625
}).Times (3 )
2626
2626
2627
+ // There will be a call to CloseSend to close the stream
2628
+ mockReadBytesClient .EXPECT ().CloseSend ().Return (nil ).Times (1 )
2629
+
2627
2630
// Act
2628
2631
request := providers.ReadStateBytesRequest {
2629
2632
TypeName : expectedReq .TypeName ,
@@ -2772,7 +2775,7 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
2772
2775
// Define what will be returned by each call to Recv
2773
2776
mockReadBytesClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {
2774
2777
Diagnostics : []* proto.Diagnostic {
2775
- & proto. Diagnostic {
2778
+ {
2776
2779
Severity : proto .Diagnostic_ERROR ,
2777
2780
Summary : "Error from test" ,
2778
2781
Detail : "This error is forced by the test case" ,
@@ -2820,15 +2823,44 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
2820
2823
).Return (mockReadBytesClient , nil )
2821
2824
2822
2825
// Define what will be returned by each call to Recv
2823
- mockReadBytesClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {
2824
- Diagnostics : []* proto.Diagnostic {
2825
- & proto.Diagnostic {
2826
- Severity : proto .Diagnostic_WARNING ,
2827
- Summary : "Warning from test" ,
2828
- Detail : "This warning is forced by the test case" ,
2826
+ chunk := "hello world"
2827
+ totalLength := len (chunk )
2828
+ mockResp := map [int ]struct {
2829
+ resp * proto.ReadStateBytes_Response
2830
+ err error
2831
+ }{
2832
+ 0 : {
2833
+ resp : & proto.ReadStateBytes_Response {
2834
+ Bytes : []byte (chunk ),
2835
+ TotalLength : int64 (totalLength ),
2836
+ Range : & proto.StateRange {
2837
+ Start : 0 ,
2838
+ End : int64 (len (chunk )),
2839
+ },
2840
+ Diagnostics : []* proto.Diagnostic {
2841
+ {
2842
+ Severity : proto .Diagnostic_WARNING ,
2843
+ Summary : "Warning from test" ,
2844
+ Detail : "This warning is forced by the test case" ,
2845
+ },
2846
+ },
2829
2847
},
2848
+ err : nil ,
2849
+ },
2850
+ 1 : {
2851
+ resp : & proto.ReadStateBytes_Response {},
2852
+ err : io .EOF ,
2830
2853
},
2831
- }, io .EOF )
2854
+ }
2855
+ var count int
2856
+ mockReadBytesClient .EXPECT ().Recv ().DoAndReturn (func () (* proto.ReadStateBytes_Response , error ) {
2857
+ ret := mockResp [count ]
2858
+ count ++
2859
+ return ret .resp , ret .err
2860
+ }).Times (2 )
2861
+
2862
+ // There will be a call to CloseSend to close the stream
2863
+ mockReadBytesClient .EXPECT ().CloseSend ().Return (nil ).Times (1 )
2832
2864
2833
2865
// Act
2834
2866
request := providers.ReadStateBytesRequest {
@@ -2843,8 +2875,8 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
2843
2875
if resp .Diagnostics .ErrWithWarnings ().Error () != expectedWarn {
2844
2876
t .Fatalf ("expected warning diagnostic %q, but got: %q" , expectedWarn , resp .Diagnostics .ErrWithWarnings ().Error ())
2845
2877
}
2846
- if len (resp .Bytes ) ! = 0 {
2847
- t .Fatalf ("expected data to be omitted in error condition , but got: %q" , string ( resp . Bytes ) )
2878
+ if len (resp .Bytes ) = = 0 {
2879
+ t .Fatal ("expected data to included despite warnings , but got no bytes" )
2848
2880
}
2849
2881
})
2850
2882
@@ -2888,6 +2920,51 @@ func TestGRPCProvider_ReadStateBytes(t *testing.T) {
2888
2920
t .Fatalf ("expected data to be omitted in error condition, but got: %q" , string (resp .Bytes ))
2889
2921
}
2890
2922
})
2923
+
2924
+ t .Run ("when closing the stream, grpc errors are surfaced via diagnostics" , func (t * testing.T ) {
2925
+ client := mockProviderClient (t )
2926
+ p := & GRPCProvider {
2927
+ client : client ,
2928
+ ctx : context .Background (),
2929
+ }
2930
+
2931
+ // Call to ReadStateBytes
2932
+ // > Assert the arguments received
2933
+ // > Define the returned mock client
2934
+ mockClient := mockReadStateBytesClient (t )
2935
+ expectedReq := & proto.ReadStateBytes_Request {
2936
+ TypeName : "mock_store" ,
2937
+ StateId : backend .DefaultStateName ,
2938
+ }
2939
+ client .EXPECT ().ReadStateBytes (
2940
+ gomock .Any (),
2941
+ gomock .Eq (expectedReq ),
2942
+ ).Return (mockClient , nil )
2943
+
2944
+ // Sufficient mocking of Recv to get to the call to CloseSend
2945
+ mockClient .EXPECT ().Recv ().Return (& proto.ReadStateBytes_Response {}, io .EOF )
2946
+
2947
+ // Force a gRPC error from CloseSend
2948
+ mockError := errors .New ("grpc error forced in test" )
2949
+ mockClient .EXPECT ().CloseSend ().Return (mockError ).Times (1 )
2950
+
2951
+ // Act
2952
+ request := providers.ReadStateBytesRequest {
2953
+ TypeName : expectedReq .TypeName ,
2954
+ StateId : expectedReq .StateId ,
2955
+ }
2956
+ resp := p .ReadStateBytes (request )
2957
+
2958
+ // Assert returned values
2959
+ checkDiagsHasError (t , resp .Diagnostics )
2960
+ wantErr := fmt .Sprintf ("Plugin error: The plugin returned an unexpected error from plugin6.(*GRPCProvider).ReadStateBytes: %s" , mockError )
2961
+ if resp .Diagnostics .Err ().Error () != wantErr {
2962
+ t .Fatalf ("expected error diagnostic %q, but got: %q" , wantErr , resp .Diagnostics .Err ())
2963
+ }
2964
+ if len (resp .Bytes ) != 0 {
2965
+ t .Fatalf ("expected data to be omitted in error condition, but got: %q" , string (resp .Bytes ))
2966
+ }
2967
+ })
2891
2968
}
2892
2969
2893
2970
func TestGRPCProvider_WriteStateBytes (t * testing.T ) {
0 commit comments