github.com/opentofu/opentofu@v1.7.1/internal/cloudplugin/cloudplugin1/grpc_client_test.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package cloudplugin1 7 8 import ( 9 "bytes" 10 "context" 11 "errors" 12 "fmt" 13 "io" 14 "testing" 15 16 "github.com/golang/mock/gomock" 17 "github.com/opentofu/opentofu/internal/cloudplugin/cloudproto1" 18 "github.com/opentofu/opentofu/internal/cloudplugin/mock_cloudproto1" 19 ) 20 21 var mockError = "this is a mock error" 22 23 func testGRPCloudClient(t *testing.T, ctrl *gomock.Controller, client *mock_cloudproto1.MockCommandService_ExecuteClient, executeError error) *GRPCCloudClient { 24 t.Helper() 25 26 if client != nil && executeError != nil { 27 t.Fatal("one of client or executeError must be nil") 28 } 29 30 result := mock_cloudproto1.NewMockCommandServiceClient(ctrl) 31 32 result.EXPECT().Execute( 33 gomock.Any(), 34 gomock.Any(), 35 gomock.Any(), 36 ).Return(client, executeError) 37 38 return &GRPCCloudClient{ 39 client: result, 40 context: context.Background(), 41 } 42 } 43 44 func Test_GRPCCloudClient_ExecuteError(t *testing.T) { 45 ctrl := gomock.NewController(t) 46 gRPCClient := testGRPCloudClient(t, ctrl, nil, errors.New(mockError)) 47 48 buffer := bytes.Buffer{} 49 exitCode := gRPCClient.Execute([]string{"example"}, io.Discard, &buffer) 50 51 if exitCode != 1 { 52 t.Fatalf("expected exit %d, got %d", 1, exitCode) 53 } 54 55 if buffer.String() != mockError { 56 t.Errorf("expected error %q, got %q", mockError, buffer.String()) 57 } 58 } 59 60 func Test_GRPCCloudClient_Execute_RecvError(t *testing.T) { 61 ctrl := gomock.NewController(t) 62 executeClient := mock_cloudproto1.NewMockCommandService_ExecuteClient(ctrl) 63 executeClient.EXPECT().Recv().Return(nil, errors.New(mockError)) 64 65 gRPCClient := testGRPCloudClient(t, ctrl, executeClient, nil) 66 67 buffer := bytes.Buffer{} 68 exitCode := gRPCClient.Execute([]string{"example"}, io.Discard, &buffer) 69 70 if exitCode != 1 { 71 t.Fatalf("expected exit %d, got %d", 1, exitCode) 72 } 73 74 mockRecvError := fmt.Sprintf("Failed to receive command response from cloudplugin: %s", mockError) 75 76 if buffer.String() != mockRecvError { 77 t.Errorf("expected error %q, got %q", mockRecvError, buffer.String()) 78 } 79 } 80 81 func Test_GRPCCloudClient_Execute_Invalid_Exit(t *testing.T) { 82 ctrl := gomock.NewController(t) 83 executeClient := mock_cloudproto1.NewMockCommandService_ExecuteClient(ctrl) 84 85 executeClient.EXPECT().Recv().Return( 86 &cloudproto1.CommandResponse{ 87 Data: &cloudproto1.CommandResponse_ExitCode{ 88 ExitCode: 3_000, 89 }, 90 }, nil, 91 ) 92 93 gRPCClient := testGRPCloudClient(t, ctrl, executeClient, nil) 94 95 exitCode := gRPCClient.Execute([]string{"example"}, io.Discard, io.Discard) 96 97 if exitCode != 255 { 98 t.Fatalf("expected exit %q, got %q", 255, exitCode) 99 } 100 } 101 102 func Test_GRPCCloudClient_Execute(t *testing.T) { 103 ctrl := gomock.NewController(t) 104 executeClient := mock_cloudproto1.NewMockCommandService_ExecuteClient(ctrl) 105 106 gomock.InOrder( 107 executeClient.EXPECT().Recv().Return( 108 &cloudproto1.CommandResponse{ 109 Data: &cloudproto1.CommandResponse_Stdout{ 110 Stdout: []byte("firstcall\n"), 111 }, 112 }, nil, 113 ), 114 executeClient.EXPECT().Recv().Return( 115 &cloudproto1.CommandResponse{ 116 Data: &cloudproto1.CommandResponse_Stdout{ 117 Stdout: []byte("secondcall\n"), 118 }, 119 }, nil, 120 ), 121 executeClient.EXPECT().Recv().Return( 122 &cloudproto1.CommandResponse{ 123 Data: &cloudproto1.CommandResponse_ExitCode{ 124 ExitCode: 99, 125 }, 126 }, nil, 127 ), 128 ) 129 130 gRPCClient := testGRPCloudClient(t, ctrl, executeClient, nil) 131 132 stdoutBuffer := bytes.Buffer{} 133 exitCode := gRPCClient.Execute([]string{"example"}, &stdoutBuffer, io.Discard) 134 135 if exitCode != 99 { 136 t.Fatalf("expected exit %q, got %q", 99, exitCode) 137 } 138 139 if stdoutBuffer.String() != "firstcall\nsecondcall\n" { 140 t.Errorf("expected output %q, got %q", "firstcall\nsecondcall\n", stdoutBuffer.String()) 141 } 142 }