@@ -13,6 +13,7 @@ import (
1313 "time"
1414
1515 "github.com/wakatime/wakatime-cli/cmd"
16+ "github.com/wakatime/wakatime-cli/pkg/api"
1617 "github.com/wakatime/wakatime-cli/pkg/exitcode"
1718 "github.com/wakatime/wakatime-cli/pkg/log"
1819 "github.com/wakatime/wakatime-cli/pkg/offline"
@@ -77,6 +78,73 @@ func TestRunCmd_Err(t *testing.T) {
7778 assert .Eventually (t , func () bool { return numCalls == 0 }, time .Second , 50 * time .Millisecond )
7879}
7980
81+ func TestRunCmd_ErrBackoff (t * testing.T ) {
82+ testServerURL , router , tearDown := setupTestServer ()
83+ defer tearDown ()
84+
85+ ctx := context .Background ()
86+
87+ var numCalls int
88+
89+ router .HandleFunc ("/plugins/errors" , func (_ http.ResponseWriter , _ * http.Request ) {
90+ numCalls ++
91+ })
92+
93+ version .OS = "some os"
94+ version .Arch = "some architecture"
95+ version .Version = "some version"
96+
97+ tmpDir := t .TempDir ()
98+
99+ offlineQueueFile , err := os .CreateTemp (tmpDir , "" )
100+ require .NoError (t , err )
101+
102+ defer offlineQueueFile .Close ()
103+
104+ logFile , err := os .CreateTemp (tmpDir , "" )
105+ require .NoError (t , err )
106+
107+ defer logFile .Close ()
108+
109+ v := viper .New ()
110+ v .Set ("api-url" , testServerURL )
111+ v .Set ("entity" , "/path/to/file" )
112+ v .Set ("key" , "00000000-0000-4000-8000-000000000000" )
113+ v .Set ("log-file" , logFile .Name ())
114+ v .Set ("offline-queue-file" , offlineQueueFile .Name ())
115+ v .Set ("plugin" , "vim" )
116+
117+ logger , err := cmd .SetupLogging (ctx , v )
118+ require .NoError (t , err )
119+
120+ defer logger .Flush ()
121+
122+ ctx = log .ToContext (ctx , logger )
123+
124+ var cmdNumCalls int
125+
126+ cmdFn := func (_ context.Context , _ * viper.Viper ) (int , error ) {
127+ cmdNumCalls ++
128+ return 42 , api.ErrBackoff {Err : errors .New ("fail" )}
129+ }
130+
131+ err = cmd .RunCmd (ctx , v , false , false , cmdFn )
132+ require .Error (t , err )
133+
134+ var errexitcode exitcode.Err
135+
136+ require .ErrorAs (t , err , & errexitcode )
137+
138+ assert .Equal (t , 42 , err .(exitcode.Err ).Code )
139+ assert .Equal (t , 1 , cmdNumCalls )
140+ assert .Eventually (t , func () bool { return numCalls == 0 }, time .Second , 50 * time .Millisecond )
141+
142+ output , err := io .ReadAll (logFile )
143+ require .NoError (t , err )
144+
145+ assert .Empty (t , string (output ))
146+ }
147+
80148func TestRunCmd_Verbose_Err (t * testing.T ) {
81149 testServerURL , router , tearDown := setupTestServer ()
82150 defer tearDown ()
@@ -104,6 +172,7 @@ func TestRunCmd_Verbose_Err(t *testing.T) {
104172 v .Set ("key" , "00000000-0000-4000-8000-000000000000" )
105173 v .Set ("offline-queue-file" , offlineQueueFile .Name ())
106174 v .Set ("plugin" , "vim" )
175+ v .Set ("verbose" , true )
107176
108177 var cmdNumCalls int
109178
@@ -123,6 +192,73 @@ func TestRunCmd_Verbose_Err(t *testing.T) {
123192 assert .Eventually (t , func () bool { return numCalls == 0 }, time .Second , 50 * time .Millisecond )
124193}
125194
195+ func TestRunCmd_Verbose_ErrBackoff (t * testing.T ) {
196+ testServerURL , router , tearDown := setupTestServer ()
197+ defer tearDown ()
198+
199+ ctx := context .Background ()
200+
201+ var numCalls int
202+
203+ router .HandleFunc ("/plugins/errors" , func (_ http.ResponseWriter , _ * http.Request ) {
204+ numCalls ++
205+ })
206+
207+ version .OS = "some os"
208+ version .Arch = "some architecture"
209+ version .Version = "some version"
210+
211+ tmpDir := t .TempDir ()
212+
213+ offlineQueueFile , err := os .CreateTemp (tmpDir , "" )
214+ require .NoError (t , err )
215+
216+ defer offlineQueueFile .Close ()
217+
218+ logFile , err := os .CreateTemp (tmpDir , "" )
219+ require .NoError (t , err )
220+
221+ defer logFile .Close ()
222+
223+ v := viper .New ()
224+ v .Set ("api-url" , testServerURL )
225+ v .Set ("entity" , "/path/to/file" )
226+ v .Set ("key" , "00000000-0000-4000-8000-000000000000" )
227+ v .Set ("offline-queue-file" , offlineQueueFile .Name ())
228+ v .Set ("plugin" , "vim" )
229+ v .Set ("log-file" , logFile .Name ())
230+ v .Set ("verbose" , true )
231+
232+ logger , err := cmd .SetupLogging (ctx , v )
233+ require .NoError (t , err )
234+
235+ defer logger .Flush ()
236+
237+ ctx = log .ToContext (ctx , logger )
238+
239+ var cmdNumCalls int
240+
241+ cmdFn := func (_ context.Context , _ * viper.Viper ) (int , error ) {
242+ cmdNumCalls ++
243+ return 42 , api.ErrBackoff {Err : errors .New ("fail" )}
244+ }
245+
246+ err = cmd .RunCmd (ctx , v , true , false , cmdFn )
247+
248+ var errexitcode exitcode.Err
249+
250+ require .ErrorAs (t , err , & errexitcode )
251+
252+ assert .Equal (t , 42 , err .(exitcode.Err ).Code )
253+ assert .Equal (t , 1 , cmdNumCalls )
254+ assert .Eventually (t , func () bool { return numCalls == 0 }, time .Second , 50 * time .Millisecond )
255+
256+ output , err := io .ReadAll (logFile )
257+ require .NoError (t , err )
258+
259+ assert .Contains (t , string (output ), "failed to run command: fail" )
260+ }
261+
126262func TestRunCmd_SendDiagnostics_Err (t * testing.T ) {
127263 testServerURL , router , tearDown := setupTestServer ()
128264 defer tearDown ()
0 commit comments