github.com/release-engineering/exodus-rsync@v1.11.2/internal/cmd/cmd_gw_errors_test.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 "github.com/release-engineering/exodus-rsync/internal/gw" 9 "github.com/release-engineering/exodus-rsync/internal/walk" 10 ) 11 12 type mockClientConfigurator func(*gomock.Controller, *gw.MockClient) 13 14 func setupFailedUpload(ctrl *gomock.Controller, client *gw.MockClient) { 15 // Creating a publish succeeds 16 publish := gw.NewMockPublish(ctrl) 17 client.EXPECT().NewPublish(gomock.Any()).Return(publish, nil) 18 19 publish.EXPECT().ID().Return("3e0a4539-be4a-437e-a45f-6d72f7192f17").AnyTimes() 20 21 client.EXPECT().EnsureUploaded(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 22 Return(fmt.Errorf("simulated error")) 23 } 24 25 func setupFailedNewPublish(_ *gomock.Controller, client *gw.MockClient) { 26 client.EXPECT().NewPublish(gomock.Any()).Return(nil, fmt.Errorf("simulated error")) 27 } 28 29 func setupFailedAddItems(ctrl *gomock.Controller, client *gw.MockClient) { 30 // EnsureUploaded succeeds, and (importantly) must add some items 31 client.EXPECT().EnsureUploaded(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 32 Do(func(_ interface{}, _ interface{}, onUploaded func(walk.SyncItem) error, onPresent func(walk.SyncItem) error, onDuplicate func(walk.SyncItem) error) { 33 // Simulate that a couple of items were uploaded. 34 onUploaded(walk.SyncItem{SrcPath: "file1", Key: "abc123"}) 35 onUploaded(walk.SyncItem{SrcPath: "file2", Key: "aabbcc"}) 36 onDuplicate(walk.SyncItem{SrcPath: "file3", Key: "abc123"}) 37 onPresent(walk.SyncItem{SrcPath: "file4", Key: "a1b2c3"}) 38 }). 39 Return(nil) 40 41 // Creating a publish succeeds 42 publish := gw.NewMockPublish(ctrl) 43 client.EXPECT().NewPublish(gomock.Any()).Return(publish, nil) 44 45 publish.EXPECT().ID().Return("3e0a4539-be4a-437e-a45f-6d72f7192f17").AnyTimes() 46 47 // Publish can't have items added 48 publish.EXPECT().AddItems(gomock.Any(), gomock.Any()).Return(fmt.Errorf("simulated error")) 49 } 50 51 func setupFailedCommit(ctrl *gomock.Controller, client *gw.MockClient) { 52 // EnsureUploaded succeeds, and (importantly) must add some items 53 client.EXPECT().EnsureUploaded(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 54 Do(func(_ interface{}, _ interface{}, onUploaded func(walk.SyncItem) error, _ interface{}, _ interface{}) { 55 // Simulate that a couple of items were uploaded. 56 onUploaded(walk.SyncItem{SrcPath: "file1", Key: "abc123"}) 57 onUploaded(walk.SyncItem{SrcPath: "file2", Key: "aabbcc"}) 58 }). 59 Return(nil) 60 61 // Creating a publish succeeds 62 publish := gw.NewMockPublish(ctrl) 63 client.EXPECT().NewPublish(gomock.Any()).Return(publish, nil) 64 65 publish.EXPECT().ID().Return("3e0a4539-be4a-437e-a45f-6d72f7192f17").AnyTimes() 66 67 // Adding items succeeds 68 publish.EXPECT().AddItems(gomock.Any(), gomock.Any()).Return(nil) 69 70 // Committing fails 71 publish.EXPECT().Commit(gomock.Any(), gomock.Any()).Return(fmt.Errorf("simulated error")) 72 } 73 74 func setupFailedJoinPublish(ctrl *gomock.Controller, client *gw.MockClient) { 75 publish := gw.NewMockPublish(ctrl) 76 77 client.EXPECT().GetPublish(gomock.Any(), gomock.Any()).Return(publish, fmt.Errorf("simulated error")) 78 } 79 80 func TestMainUploadFailed(t *testing.T) { 81 tests := []struct { 82 message string 83 setupMock mockClientConfigurator 84 exitCode int 85 }{ 86 {"can't upload files", setupFailedUpload, 25}, 87 {"can't create publish", setupFailedNewPublish, 62}, 88 {"can't add items to publish", setupFailedAddItems, 51}, 89 {"can't commit publish", setupFailedCommit, 71}, 90 } 91 for _, tt := range tests { 92 t.Run(tt.message, func(t *testing.T) { 93 94 logs := CaptureLogger(t) 95 ctrl := MockController(t) 96 97 mockGw := gw.NewMockInterface(ctrl) 98 ext.gw = mockGw 99 100 mockClient := gw.NewMockClient(ctrl) 101 102 SetConfig(t, ` 103 gwcert: $HOME/certs/$USER.crt 104 gwkey: $HOME/certs/$USER.key 105 gwurl: https://exodus-gw.example.com/ 106 107 environments: 108 - prefix: some-dest 109 gwenv: test 110 `) 111 112 mockGw.EXPECT().NewClient(gomock.Any(), gomock.Any()).Return(mockClient, nil) 113 114 tt.setupMock(ctrl, mockClient) 115 116 exitCode := Main([]string{ 117 "exodus-rsync", ".", "some-dest:/foo/bar", 118 }) 119 120 // It should exit with error. 121 if exitCode != tt.exitCode { 122 t.Error("returned incorrect exit code", exitCode) 123 } 124 125 entry := FindEntry(logs, tt.message) 126 if entry == nil { 127 t.Fatal("missing expected log message") 128 } 129 130 if fmt.Sprint(entry.Fields["error"]) != "simulated error" { 131 t.Errorf("unexpected error %v", entry.Fields["error"]) 132 } 133 }) 134 } 135 } 136 137 func TestMainJoinPublishFailed(t *testing.T) { 138 test := struct { 139 message string 140 setupMock mockClientConfigurator 141 exitCode int 142 }{"can't join publish", setupFailedJoinPublish, 67} 143 144 t.Run(test.message, func(t *testing.T) { 145 146 logs := CaptureLogger(t) 147 ctrl := MockController(t) 148 149 mockGw := gw.NewMockInterface(ctrl) 150 ext.gw = mockGw 151 152 mockClient := gw.NewMockClient(ctrl) 153 154 SetConfig(t, ` 155 gwcert: $HOME/certs/$USER.crt 156 gwkey: $HOME/certs/$USER.key 157 gwurl: https://exodus-gw.example.com/ 158 environments: 159 - prefix: some-dest 160 gwenv: test 161 `) 162 163 mockGw.EXPECT().NewClient(gomock.Any(), gomock.Any()).Return(mockClient, nil) 164 165 test.setupMock(ctrl, mockClient) 166 167 exitCode := Main([]string{ 168 "exodus-rsync", ".", "some-dest:/foo/bar", "--exodus-publish", "3e0a4539-be4a-437e-a45f-6d72f7192f17", 169 }) 170 171 // It should exit with error. 172 if exitCode != test.exitCode { 173 t.Error("returned incorrect exit code", exitCode) 174 } 175 176 entry := FindEntry(logs, test.message) 177 if entry == nil { 178 t.Fatal("missing expected log message") 179 } 180 181 if fmt.Sprint(entry.Fields["error"]) != "simulated error" { 182 t.Errorf("unexpected error %v", entry.Fields["error"]) 183 } 184 }) 185 }