Skip to content

Commit 4e615d7

Browse files
committed
test: add unit tests for SyncSuspend and RunSuspendSyncPlugins
Signed-off-by: Jeet <113221510+JEETDESAI25@users.noreply.github.com>
1 parent 544c181 commit 4e615d7

2 files changed

Lines changed: 214 additions & 0 deletions

File tree

pkg/runtime/framework/core/framework_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"k8s.io/klog/v2/ktesting"
3636
"k8s.io/utils/ptr"
3737
"sigs.k8s.io/controller-runtime/pkg/client"
38+
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
3839
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
3940
jobsetv1alpha2 "sigs.k8s.io/jobset/api/jobset/v1alpha2"
4041
jobsetv1alpha2ac "sigs.k8s.io/jobset/client-go/applyconfiguration/jobset/v1alpha2"
@@ -2626,3 +2627,76 @@ func TestPodNetworkPlugins(t *testing.T) {
26262627
})
26272628
}
26282629
}
2630+
2631+
func TestRunSuspendSyncPlugins(t *testing.T) {
2632+
errClientGet := fmt.Errorf("client error")
2633+
2634+
cases := map[string]struct {
2635+
registry fwkplugins.Registry
2636+
trainJob *trainer.TrainJob
2637+
existingJobSet *jobsetv1alpha2.JobSet
2638+
clientGetErr error
2639+
wantError error
2640+
}{
2641+
"success with JobSet plugin registered": {
2642+
registry: fwkplugins.NewRegistry(),
2643+
trainJob: testingutil.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
2644+
Suspend(true).
2645+
Obj(),
2646+
existingJobSet: testingutil.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
2647+
Suspend(false).
2648+
Obj(),
2649+
wantError: nil,
2650+
},
2651+
"no plugins run with empty registry": {
2652+
registry: fwkplugins.Registry{},
2653+
trainJob: testingutil.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
2654+
Suspend(true).
2655+
Obj(),
2656+
wantError: nil,
2657+
},
2658+
"error propagation when plugin returns error": {
2659+
registry: fwkplugins.NewRegistry(),
2660+
trainJob: testingutil.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
2661+
Suspend(true).
2662+
Obj(),
2663+
existingJobSet: testingutil.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
2664+
Suspend(false).
2665+
Obj(),
2666+
clientGetErr: errClientGet,
2667+
wantError: errClientGet,
2668+
},
2669+
}
2670+
2671+
for name, tc := range cases {
2672+
t.Run(name, func(t *testing.T) {
2673+
ctx, cancel := context.WithCancel(context.Background())
2674+
t.Cleanup(cancel)
2675+
2676+
clientBuilder := testingutil.NewClientBuilder()
2677+
if tc.existingJobSet != nil {
2678+
clientBuilder = clientBuilder.WithObjects(tc.existingJobSet)
2679+
}
2680+
if tc.clientGetErr != nil {
2681+
clientBuilder = clientBuilder.WithInterceptorFuncs(interceptor.Funcs{
2682+
Get: func(ctx context.Context, cli client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
2683+
if _, ok := obj.(*jobsetv1alpha2.JobSet); ok {
2684+
return tc.clientGetErr
2685+
}
2686+
return cli.Get(ctx, key, obj, opts...)
2687+
},
2688+
})
2689+
}
2690+
2691+
fwk, err := New(ctx, clientBuilder.Build(), tc.registry, testingutil.AsIndex(clientBuilder))
2692+
if err != nil {
2693+
t.Fatal(err)
2694+
}
2695+
2696+
err = fwk.RunSuspendSyncPlugins(ctx, tc.trainJob)
2697+
if diff := cmp.Diff(tc.wantError, err, cmpopts.EquateErrors()); len(diff) != 0 {
2698+
t.Errorf("Unexpected error (-want,+got):\n%s", diff)
2699+
}
2700+
})
2701+
}
2702+
}

pkg/runtime/framework/plugins/jobset/jobset_test.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,3 +1325,143 @@ func TestValidate(t *testing.T) {
13251325
})
13261326
}
13271327
}
1328+
1329+
func TestSyncSuspend(t *testing.T) {
1330+
errClientGet := fmt.Errorf("connection refused")
1331+
errClientPatch := fmt.Errorf("patch failed")
1332+
1333+
cases := map[string]struct {
1334+
trainJob *trainer.TrainJob
1335+
existingJobSet *jobsetv1alpha2.JobSet
1336+
clientGetErr error
1337+
clientPatchErr error
1338+
wantError error
1339+
wantSuspend *bool
1340+
}{
1341+
"patch JobSet suspend to true when TrainJob is suspended but JobSet is not": {
1342+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1343+
Suspend(true).
1344+
Obj(),
1345+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1346+
Suspend(false).
1347+
Obj(),
1348+
wantSuspend: ptr.To(true),
1349+
},
1350+
"patch JobSet suspend to false when TrainJob is not suspended but JobSet is": {
1351+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1352+
Suspend(false).
1353+
Obj(),
1354+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1355+
Suspend(true).
1356+
Obj(),
1357+
wantSuspend: ptr.To(false),
1358+
},
1359+
"no patch when both TrainJob and JobSet are suspended": {
1360+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1361+
Suspend(true).
1362+
Obj(),
1363+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1364+
Suspend(true).
1365+
Obj(),
1366+
wantSuspend: ptr.To(true),
1367+
},
1368+
"no patch when both TrainJob and JobSet are not suspended": {
1369+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1370+
Suspend(false).
1371+
Obj(),
1372+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1373+
Suspend(false).
1374+
Obj(),
1375+
wantSuspend: ptr.To(false),
1376+
},
1377+
"patch JobSet suspend to false when TrainJob suspend is nil and JobSet is suspended": {
1378+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1379+
Obj(),
1380+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1381+
Suspend(true).
1382+
Obj(),
1383+
wantSuspend: ptr.To(false),
1384+
},
1385+
"return nil when JobSet is not found": {
1386+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1387+
Suspend(true).
1388+
Obj(),
1389+
existingJobSet: nil,
1390+
wantError: nil,
1391+
},
1392+
"return error when client Get fails": {
1393+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1394+
Suspend(true).
1395+
Obj(),
1396+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1397+
Suspend(false).
1398+
Obj(),
1399+
clientGetErr: errClientGet,
1400+
wantError: errClientGet,
1401+
},
1402+
"return wrapped error when client Patch fails": {
1403+
trainJob: utiltesting.MakeTrainJobWrapper(metav1.NamespaceDefault, "test").
1404+
Suspend(true).
1405+
Obj(),
1406+
existingJobSet: utiltesting.MakeJobSetWrapper(metav1.NamespaceDefault, "test").
1407+
Suspend(false).
1408+
Obj(),
1409+
clientPatchErr: errClientPatch,
1410+
wantError: errClientPatch,
1411+
},
1412+
}
1413+
1414+
for name, tc := range cases {
1415+
t.Run(name, func(t *testing.T) {
1416+
_, ctx := ktesting.NewTestContext(t)
1417+
var cancel func()
1418+
ctx, cancel = context.WithCancel(ctx)
1419+
t.Cleanup(cancel)
1420+
1421+
clientBuilder := utiltesting.NewClientBuilder()
1422+
if tc.existingJobSet != nil {
1423+
clientBuilder = clientBuilder.WithObjects(tc.existingJobSet)
1424+
}
1425+
if tc.clientGetErr != nil || tc.clientPatchErr != nil {
1426+
clientBuilder = clientBuilder.WithInterceptorFuncs(interceptor.Funcs{
1427+
Get: func(ctx context.Context, cli client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
1428+
if tc.clientGetErr != nil {
1429+
if _, ok := obj.(*jobsetv1alpha2.JobSet); ok {
1430+
return tc.clientGetErr
1431+
}
1432+
}
1433+
return cli.Get(ctx, key, obj, opts...)
1434+
},
1435+
Patch: func(ctx context.Context, cli client.WithWatch, obj client.Object, patch client.Patch, opts ...client.PatchOption) error {
1436+
if tc.clientPatchErr != nil {
1437+
if _, ok := obj.(*jobsetv1alpha2.JobSet); ok {
1438+
return tc.clientPatchErr
1439+
}
1440+
}
1441+
return cli.Patch(ctx, obj, patch, opts...)
1442+
},
1443+
})
1444+
}
1445+
cli := clientBuilder.Build()
1446+
1447+
p, err := New(ctx, cli, nil)
1448+
if err != nil {
1449+
t.Fatalf("Failed to initialize JobSet plugin: %v", err)
1450+
}
1451+
1452+
err = p.(*JobSet).SyncSuspend(ctx, tc.trainJob)
1453+
if diff := cmp.Diff(tc.wantError, err, cmpopts.EquateErrors()); len(diff) != 0 {
1454+
t.Errorf("Unexpected error (-want,+got):\n%s", diff)
1455+
}
1456+
if tc.wantError == nil && tc.existingJobSet != nil && tc.wantSuspend != nil {
1457+
jobSet := &jobsetv1alpha2.JobSet{}
1458+
if err := cli.Get(ctx, client.ObjectKeyFromObject(tc.trainJob), jobSet); err != nil {
1459+
t.Fatalf("Failed to get JobSet: %v", err)
1460+
}
1461+
if diff := cmp.Diff(tc.wantSuspend, jobSet.Spec.Suspend); len(diff) != 0 {
1462+
t.Errorf("Unexpected JobSet suspend state (-want,+got):\n%s", diff)
1463+
}
1464+
}
1465+
})
1466+
}
1467+
}

0 commit comments

Comments
 (0)