@@ -14,6 +14,7 @@ import (
1414 "golang.org/x/xerrors"
1515
1616 "cdr.dev/slog"
17+ "cdr.dev/slog/sloggers/sloghuman"
1718 "github.com/coder/quartz"
1819
1920 "github.com/coder/coder/v2/codersdk"
@@ -57,6 +58,12 @@ func (m *fakeClient) createExternalWorkspace(ctx context.Context, req codersdk.C
5758 }, nil
5859}
5960
61+ func (m * fakeClient ) deleteWorkspace (ctx context.Context , workspaceID uuid.UUID ) error {
62+ m .logger .Debug (ctx , "called fake DeleteWorkspace" , slog .F ("workspace_id" , workspaceID .String ()))
63+ // Simulate successful deletion in tests
64+ return nil
65+ }
66+
6067// fakeAppStatusPatcher implements the appStatusPatcher interface for testing
6168type fakeAppStatusPatcher struct {
6269 t * testing.T
@@ -480,3 +487,68 @@ func TestParseStatusMessage(t *testing.T) {
480487 })
481488 }
482489}
490+
491+ func TestRunner_Cleanup (t * testing.T ) {
492+ t .Parallel ()
493+
494+ ctx := testutil .Context (t , testutil .WaitMedium )
495+
496+ fakeClient := & fakeClientWithCleanupTracking {
497+ fakeClient : newFakeClient (t ),
498+ deleteWorkspaceCalls : make ([]uuid.UUID , 0 ),
499+ }
500+ fakeClient .initialize (slog .Make (sloghuman .Sink (testutil .NewTestLogWriter (t ))).Leveled (slog .LevelDebug ))
501+
502+ cfg := Config {
503+ AppSlug : "test-app" ,
504+ TemplateID : uuid.UUID {5 , 6 , 7 , 8 },
505+ WorkspaceName : "test-workspace" ,
506+ MetricLabelValues : []string {"test" },
507+ Metrics : NewMetrics (prometheus .NewRegistry (), "test" ),
508+ ReportStatusPeriod : 100 * time .Millisecond ,
509+ ReportStatusDuration : 200 * time .Millisecond ,
510+ StartReporting : make (chan struct {}),
511+ ConnectedWaitGroup : & sync.WaitGroup {},
512+ }
513+
514+ runner := & Runner {
515+ client : fakeClient ,
516+ patcher : newFakeAppStatusPatcher (t ),
517+ cfg : cfg ,
518+ clock : quartz .NewMock (t ),
519+ }
520+
521+ logWriter := testutil .NewTestLogWriter (t )
522+
523+ // Case 1: No workspace created - Cleanup should do nothing
524+ err := runner .Cleanup (ctx , "test-runner" , logWriter )
525+ require .NoError (t , err )
526+ require .Len (t , fakeClient .deleteWorkspaceCalls , 0 , "deleteWorkspace should not be called when no workspace was created" )
527+
528+ // Case 2: Workspace created - Cleanup should delete it
529+ runner .workspaceID = uuid.UUID {1 , 2 , 3 , 4 }
530+ err = runner .Cleanup (ctx , "test-runner" , logWriter )
531+ require .NoError (t , err )
532+ require .Len (t , fakeClient .deleteWorkspaceCalls , 1 , "deleteWorkspace should be called once" )
533+ require .Equal (t , runner .workspaceID , fakeClient .deleteWorkspaceCalls [0 ], "deleteWorkspace should be called with correct workspace ID" )
534+
535+ // Case 3: Cleanup with error
536+ fakeClient .deleteError = xerrors .New ("delete failed" )
537+ runner .workspaceID = uuid.UUID {5 , 6 , 7 , 8 }
538+ err = runner .Cleanup (ctx , "test-runner" , logWriter )
539+ require .Error (t , err )
540+ require .Contains (t , err .Error (), "delete external workspace" )
541+ }
542+
543+ // fakeClientWithCleanupTracking extends fakeClient to track deleteWorkspace calls
544+ type fakeClientWithCleanupTracking struct {
545+ * fakeClient
546+ deleteWorkspaceCalls []uuid.UUID
547+ deleteError error
548+ }
549+
550+ func (c * fakeClientWithCleanupTracking ) deleteWorkspace (ctx context.Context , workspaceID uuid.UUID ) error {
551+ c .deleteWorkspaceCalls = append (c .deleteWorkspaceCalls , workspaceID )
552+ c .logger .Debug (ctx , "called fake DeleteWorkspace with tracking" , slog .F ("workspace_id" , workspaceID .String ()))
553+ return c .deleteError
554+ }
0 commit comments