Skip to content

Commit 00b695e

Browse files
committed
Improve composite tool watch integration tests
Enhance integration tests for VirtualMCPCompositeToolDefinition watch functionality to verify reconciliation actually occurs. The original tests used Consistently to check ObservedGeneration stayed current, but this couldn't distinguish between "reconciliation occurred and completed" vs "no reconciliation was triggered". ResourceVersion changes when the controller updates status during reconciliation, providing definitive proof that the watch functionality works correctly.
1 parent 8ce0337 commit 00b695e

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

cmd/thv-operator/test-integration/mcp-server/virtualmcpserver_compositetool_watch_test.go

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,15 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
9898
})
9999

100100
It("Should trigger VirtualMCPServer reconciliation when composite tool definition is created", func() {
101+
// Capture initial ResourceVersion to detect reconciliation
102+
initialVMCP := &mcpv1alpha1.VirtualMCPServer{}
103+
Expect(k8sClient.Get(ctx, types.NamespacedName{
104+
Name: vmcpName,
105+
Namespace: namespace,
106+
}, initialVMCP)).Should(Succeed())
107+
108+
initialResourceVersion := initialVMCP.ResourceVersion
109+
101110
// Create the VirtualMCPCompositeToolDefinition
102111
compositeToolDef = &mcpv1alpha1.VirtualMCPCompositeToolDefinition{
103112
ObjectMeta: metav1.ObjectMeta{
@@ -117,9 +126,9 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
117126
}
118127
Expect(k8sClient.Create(ctx, compositeToolDef)).Should(Succeed())
119128

120-
// The VirtualMCPServer should remain reconciled after the composite tool definition is created
121-
// We verify this by checking that ObservedGeneration stays current
122-
Consistently(func() bool {
129+
// Verify that reconciliation occurred by checking ResourceVersion changes
130+
// When the controller reconciles, it updates the status, which changes ResourceVersion
131+
Eventually(func() bool {
123132
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
124133
err := k8sClient.Get(ctx, types.NamespacedName{
125134
Name: vmcpName,
@@ -129,11 +138,11 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
129138
return false
130139
}
131140

132-
// Check that ObservedGeneration stays current (indicating successful reconciliation)
133-
return updatedVMCP.Status.ObservedGeneration == updatedVMCP.Generation
134-
}, time.Second*5, interval).Should(BeTrue())
141+
// ResourceVersion changes when status is updated during reconciliation
142+
return updatedVMCP.ResourceVersion != initialResourceVersion
143+
}, timeout, interval).Should(BeTrue(), "ResourceVersion should change indicating reconciliation occurred")
135144

136-
// Verify the VirtualMCPServer is in a valid state
145+
// Verify the VirtualMCPServer is in a valid state after reconciliation
137146
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
138147
Expect(k8sClient.Get(ctx, types.NamespacedName{
139148
Name: vmcpName,
@@ -242,6 +251,15 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
242251
})
243252

244253
It("Should trigger VirtualMCPServer reconciliation when composite tool definition is updated", func() {
254+
// Capture initial ResourceVersion before update
255+
initialVMCP := &mcpv1alpha1.VirtualMCPServer{}
256+
Expect(k8sClient.Get(ctx, types.NamespacedName{
257+
Name: vmcpName,
258+
Namespace: namespace,
259+
}, initialVMCP)).Should(Succeed())
260+
261+
initialResourceVersion := initialVMCP.ResourceVersion
262+
245263
// Update the VirtualMCPCompositeToolDefinition
246264
Eventually(func() error {
247265
freshCompositeToolDef := &mcpv1alpha1.VirtualMCPCompositeToolDefinition{}
@@ -255,9 +273,8 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
255273
return k8sClient.Update(ctx, freshCompositeToolDef)
256274
}, timeout, interval).Should(Succeed())
257275

258-
// The VirtualMCPServer should remain reconciled after the update
259-
// We verify this by checking that ObservedGeneration stays current
260-
Consistently(func() bool {
276+
// Verify that reconciliation occurred by checking ResourceVersion changes
277+
Eventually(func() bool {
261278
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
262279
err := k8sClient.Get(ctx, types.NamespacedName{
263280
Name: vmcpName,
@@ -267,9 +284,9 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
267284
return false
268285
}
269286

270-
// Check that ObservedGeneration stays current (indicating successful reconciliation)
271-
return updatedVMCP.Status.ObservedGeneration == updatedVMCP.Generation
272-
}, time.Second*5, interval).Should(BeTrue())
287+
// ResourceVersion changes when status is updated during reconciliation
288+
return updatedVMCP.ResourceVersion != initialResourceVersion
289+
}, timeout, interval).Should(BeTrue(), "ResourceVersion should change indicating reconciliation occurred")
273290

274291
// Verify the VirtualMCPServer is still in a valid state
275292
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
@@ -359,13 +376,14 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
359376
})
360377

361378
It("Should NOT trigger VirtualMCPServer reconciliation when unrelated composite tool definition is created", func() {
362-
// Get initial generation and observed generation
379+
// Get initial ResourceVersion and ObservedGeneration
363380
initialVMCP := &mcpv1alpha1.VirtualMCPServer{}
364381
Expect(k8sClient.Get(ctx, types.NamespacedName{
365382
Name: vmcpName,
366383
Namespace: namespace,
367384
}, initialVMCP)).Should(Succeed())
368385

386+
initialResourceVersion := initialVMCP.ResourceVersion
369387
initialObservedGeneration := initialVMCP.Status.ObservedGeneration
370388

371389
var initialReadyTime metav1.Time
@@ -395,11 +413,26 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
395413
}
396414
Expect(k8sClient.Create(ctx, compositeToolDef)).Should(Succeed())
397415

398-
// Wait a bit to ensure any potential reconciliation would have occurred
399-
time.Sleep(2 * time.Second)
400-
401416
// Verify that the VirtualMCPServer was NOT unnecessarily reconciled
402-
// The ObservedGeneration should remain the same, and conditions shouldn't change
417+
// ResourceVersion and ObservedGeneration should remain unchanged
418+
Consistently(func() bool {
419+
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
420+
err := k8sClient.Get(ctx, types.NamespacedName{
421+
Name: vmcpName,
422+
Namespace: namespace,
423+
}, updatedVMCP)
424+
if err != nil {
425+
return false
426+
}
427+
428+
// Verify ResourceVersion and ObservedGeneration haven't changed
429+
resourceVersionUnchanged := updatedVMCP.ResourceVersion == initialResourceVersion
430+
observedGenerationUnchanged := updatedVMCP.Status.ObservedGeneration == initialObservedGeneration
431+
432+
return resourceVersionUnchanged && observedGenerationUnchanged
433+
}, time.Second*3, interval).Should(BeTrue(), "VirtualMCPServer should not be reconciled for unrelated composite tool")
434+
435+
// Final verification of state
403436
updatedVMCP := &mcpv1alpha1.VirtualMCPServer{}
404437
Expect(k8sClient.Get(ctx, types.NamespacedName{
405438
Name: vmcpName,
@@ -409,6 +442,9 @@ var _ = Describe("VirtualMCPServer CompositeToolDefinition Watch Integration Tes
409442
// ObservedGeneration should be unchanged
410443
Expect(updatedVMCP.Status.ObservedGeneration).To(Equal(initialObservedGeneration))
411444

445+
// ResourceVersion should be unchanged
446+
Expect(updatedVMCP.ResourceVersion).To(Equal(initialResourceVersion))
447+
412448
// Ready condition timestamp should be unchanged
413449
for _, cond := range updatedVMCP.Status.Conditions {
414450
if cond.Type == conditionReady {

0 commit comments

Comments
 (0)