@@ -18,6 +18,7 @@ package e2e
1818
1919import (
2020 "context"
21+ "fmt"
2122
2223 "github.com/onsi/ginkgo/v2"
2324 . "github.com/onsi/gomega"
@@ -189,5 +190,84 @@ var _ = ginkgo.Describe("nvmeof", func() {
189190 validateRBDImageCount (f , 0 , nvmeofPool )
190191 validateOmapCount (f , 0 , rbdType , nvmeofPool , volumesType )
191192 })
193+
194+ ginkgo .It ("Test GroupLock: Concurrent Create/Delete PVCs and Pods" , func () {
195+ // This test validates the GroupLock implementation in the NVMeoF NodeServer
196+ // by creating and deleting multiple PVCs and Pods concurrently.
197+ //
198+ // Test flow:
199+ // 1. Create 3 PVCs + Pods concurrently (triggers NodeStage -> Group A lock)
200+ // 2. Wait for all to be ready
201+ // 3. Delete all PVCs + Pods concurrently (triggers NodeUnstage -> Group B lock)
202+ // 4. Verify no timeouts/deadlocks
203+ // 5. Verify all operations succeed
204+ totalCount := 3
205+
206+ ginkgo .By ("Creating multiple PVCs and Pods concurrently" )
207+ createResult := createConcurrentPVCsAndApps (totalCount , pvcPath , appPath , f )
208+
209+ // Log any errors
210+ if createResult .HasErrors () {
211+ createResult .LogErrors ()
212+ }
213+
214+ // Verify all creations succeeded
215+ Expect (createResult .failed ).To (Equal (0 ),
216+ "Expected all %d create operations to succeed, but %d failed" ,
217+ totalCount , createResult .failed )
218+
219+ ginkgo .By ("Validating backend RBD images were created" )
220+ validateRBDImageCount (f , totalCount , nvmeofPool )
221+ validateOmapCount (f , totalCount , rbdType , nvmeofPool , volumesType )
222+
223+ ginkgo .By ("Deleting multiple PVCs and Pods concurrently" )
224+ deleteResult := deleteConcurrentPVCsAndApps (createResult , pvcPath , appPath , f )
225+
226+ // Log any errors
227+ if deleteResult .HasErrors () {
228+ deleteResult .LogErrors ()
229+ }
230+
231+ // Verify all deletions succeeded
232+ Expect (deleteResult .failed ).To (Equal (0 ),
233+ "Expected all %d delete operations to succeed, but %d failed" ,
234+ totalCount , deleteResult .failed )
235+
236+ ginkgo .By ("Validating all backend RBD images were deleted" )
237+ validateRBDImageCount (f , 0 , nvmeofPool )
238+ validateOmapCount (f , 0 , rbdType , nvmeofPool , volumesType )
239+
240+ framework .Logf ("GroupLock test passed: %d concurrent create and %d concurrent delete operations completed successfully" ,
241+ totalCount , totalCount )
242+ })
243+
244+ ginkgo .It ("Test GroupLock: Mixed Create/Delete with Rapid Switching" , func () {
245+ // This test validates the GroupLock implementation under rapid switching
246+ // between Group A (NodeStage) and Group B (NodeUnstage) operations.
247+ //
248+ // Test flow:
249+ // 1. Create 5 PVCs + Pods (Group A)
250+ // 2. Concurrently start creating next 5 PVCs + Pods (Group A) while deleting previous 5 (Group B)
251+ // 3. Repeat for total of 15 PVCs + Pods with rapid switching between Group A and B
252+ //
253+ // This creates 15 total PVCs and forces rapid GroupLock switching,
254+ // simulating "real-world" scenarios for catching potential deadlocks/starvation.
255+ totalCount := 15
256+ batchSize := 5
257+
258+ ginkgo .By (fmt .Sprintf ("Running mixed create/delete test: %d total PVCs in batches of %d" ,
259+ totalCount , batchSize ))
260+
261+ err := mixedCreateDeletePVCsAndApps (totalCount , batchSize , pvcPath , appPath , f )
262+ Expect (err ).ShouldNot (HaveOccurred (),
263+ "Mixed create/delete operations should complete without errors" )
264+
265+ ginkgo .By ("Validating all backend RBD images were cleaned up" )
266+ validateRBDImageCount (f , 0 , nvmeofPool )
267+ validateOmapCount (f , 0 , rbdType , nvmeofPool , volumesType )
268+
269+ framework .Logf ("GroupLock mixed test passed: %d PVCs created and deleted with rapid Group A/B switching" ,
270+ totalCount )
271+ })
192272 })
193273})
0 commit comments