@@ -309,7 +309,136 @@ func TestWorkspaceUpdateAutostart(t *testing.T) {
309
309
310
310
err := client .UpdateWorkspaceAutostart (ctx , wsid , req )
311
311
require .IsType (t , err , & codersdk.Error {}, "expected codersdk.Error" )
312
- coderSDKErr , _ := err .(* codersdk.Error )
312
+ coderSDKErr , _ := err .(* codersdk.Error ) //nolint:errorlint
313
+ require .Equal (t , coderSDKErr .StatusCode (), 404 , "expected status code 404" )
314
+ require .Equal (t , fmt .Sprintf ("workspace %q does not exist" , wsid ), coderSDKErr .Message , "unexpected response code" )
315
+ })
316
+ }
317
+
318
+ func TestWorkspaceUpdateAutostop (t * testing.T ) {
319
+ t .Parallel ()
320
+ var dublinLoc = mustLocation (t , "Europe/Dublin" )
321
+
322
+ testCases := []struct {
323
+ name string
324
+ schedule string
325
+ expectedError string
326
+ at time.Time
327
+ expectedNext time.Time
328
+ expectedInterval time.Duration
329
+ }{
330
+ {
331
+ name : "disable autostop" ,
332
+ schedule : "" ,
333
+ expectedError : "" ,
334
+ },
335
+ {
336
+ name : "friday to monday" ,
337
+ schedule : "CRON_TZ=Europe/Dublin 30 17 1-5" ,
338
+ expectedError : "" ,
339
+ at : time .Date (2022 , 5 , 6 , 17 , 31 , 0 , 0 , dublinLoc ),
340
+ expectedNext : time .Date (2022 , 5 , 9 , 17 , 30 , 0 , 0 , dublinLoc ),
341
+ expectedInterval : 71 * time .Hour + 59 * time .Minute ,
342
+ },
343
+ {
344
+ name : "monday to tuesday" ,
345
+ schedule : "CRON_TZ=Europe/Dublin 30 17 1-5" ,
346
+ expectedError : "" ,
347
+ at : time .Date (2022 , 5 , 9 , 17 , 31 , 0 , 0 , dublinLoc ),
348
+ expectedNext : time .Date (2022 , 5 , 10 , 17 , 30 , 0 , 0 , dublinLoc ),
349
+ expectedInterval : 23 * time .Hour + 59 * time .Minute ,
350
+ },
351
+ {
352
+ // DST in Ireland began on Mar 27 in 2022 at 0100. Forward 1 hour.
353
+ name : "DST start" ,
354
+ schedule : "CRON_TZ=Europe/Dublin 30 17 *" ,
355
+ expectedError : "" ,
356
+ at : time .Date (2022 , 3 , 26 , 17 , 31 , 0 , 0 , dublinLoc ),
357
+ expectedNext : time .Date (2022 , 3 , 27 , 17 , 30 , 0 , 0 , dublinLoc ),
358
+ expectedInterval : 22 * time .Hour + 59 * time .Minute ,
359
+ },
360
+ {
361
+ // DST in Ireland ends on Oct 30 in 2022 at 0200. Back 1 hour.
362
+ name : "DST end" ,
363
+ schedule : "CRON_TZ=Europe/Dublin 30 17 *" ,
364
+ expectedError : "" ,
365
+ at : time .Date (2022 , 10 , 29 , 17 , 31 , 0 , 0 , dublinLoc ),
366
+ expectedNext : time .Date (2022 , 10 , 30 , 17 , 30 , 0 , 0 , dublinLoc ),
367
+ expectedInterval : 24 * time .Hour + 59 * time .Minute ,
368
+ },
369
+ {
370
+ name : "invalid location" ,
371
+ schedule : "CRON_TZ=Imaginary/Place 30 17 1-5" ,
372
+ expectedError : "status code 500: invalid autostop schedule: parse schedule: provided bad location Imaginary/Place: unknown time zone Imaginary/Place" ,
373
+ },
374
+ {
375
+ name : "invalid schedule" ,
376
+ schedule : "asdf asdf asdf " ,
377
+ expectedError : `status code 500: invalid autostop schedule: parse schedule: failed to parse int from asdf: strconv.Atoi: parsing "asdf": invalid syntax` ,
378
+ },
379
+ }
380
+
381
+ for _ , testCase := range testCases {
382
+ testCase := testCase
383
+ t .Run (testCase .name , func (t * testing.T ) {
384
+ t .Parallel ()
385
+ var (
386
+ ctx = context .Background ()
387
+ client = coderdtest .New (t , nil )
388
+ _ = coderdtest .NewProvisionerDaemon (t , client )
389
+ user = coderdtest .CreateFirstUser (t , client )
390
+ version = coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , nil )
391
+ _ = coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
392
+ project = coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID )
393
+ workspace = coderdtest .CreateWorkspace (t , client , codersdk .Me , project .ID )
394
+ )
395
+
396
+ // ensure test invariant: new workspaces have no autostop schedule.
397
+ require .Empty (t , workspace .AutostopSchedule , "expected newly-minted workspace to have no autstop schedule" )
398
+
399
+ err := client .UpdateWorkspaceAutostop (ctx , workspace .ID , codersdk.UpdateWorkspaceAutostopRequest {
400
+ Schedule : testCase .schedule ,
401
+ })
402
+
403
+ if testCase .expectedError != "" {
404
+ require .EqualError (t , err , testCase .expectedError , "unexpected error when setting workspace autostop schedule" )
405
+ return
406
+ }
407
+
408
+ require .NoError (t , err , "expected no error setting workspace autostop schedule" )
409
+
410
+ updated , err := client .Workspace (ctx , workspace .ID )
411
+ require .NoError (t , err , "fetch updated workspace" )
412
+
413
+ require .Equal (t , testCase .schedule , updated .AutostopSchedule , "expected autostop schedule to equal requested" )
414
+
415
+ if testCase .schedule == "" {
416
+ return
417
+ }
418
+ sched , err := schedule .Weekly (updated .AutostopSchedule )
419
+ require .NoError (t , err , "parse returned schedule" )
420
+
421
+ next := sched .Next (testCase .at )
422
+ require .Equal (t , testCase .expectedNext , next , "unexpected next scheduled autostop time" )
423
+ interval := next .Sub (testCase .at )
424
+ require .Equal (t , testCase .expectedInterval , interval , "unexpected interval" )
425
+ })
426
+ }
427
+
428
+ t .Run ("NotFound" , func (t * testing.T ) {
429
+ var (
430
+ ctx = context .Background ()
431
+ client = coderdtest .New (t , nil )
432
+ _ = coderdtest .CreateFirstUser (t , client )
433
+ wsid = uuid .New ()
434
+ req = codersdk.UpdateWorkspaceAutostopRequest {
435
+ Schedule : "9 30 1-5" ,
436
+ }
437
+ )
438
+
439
+ err := client .UpdateWorkspaceAutostop (ctx , wsid , req )
440
+ require .IsType (t , err , & codersdk.Error {}, "expected codersdk.Error" )
441
+ coderSDKErr , _ := err .(* codersdk.Error ) //nolint:errorlint
313
442
require .Equal (t , coderSDKErr .StatusCode (), 404 , "expected status code 404" )
314
443
require .Equal (t , fmt .Sprintf ("workspace %q does not exist" , wsid ), coderSDKErr .Message , "unexpected response code" )
315
444
})
0 commit comments