@@ -1773,6 +1773,191 @@ var _ = Describe("Commands", func() {
17731773 Expect (get .Err ()).To (Equal (redis .Nil ))
17741774 })
17751775
1776+ It ("should DelEx when value matches" , func () {
1777+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1778+
1779+ // Set initial value
1780+ err := client .Set (ctx , "lock" , "token-123" , 0 ).Err ()
1781+ Expect (err ).NotTo (HaveOccurred ())
1782+
1783+ // Delete only if value matches
1784+ deleted := client .DelEx (ctx , "lock" , "token-123" )
1785+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1786+ Expect (deleted .Val ()).To (Equal (int64 (1 )))
1787+
1788+ // Verify key was deleted
1789+ get := client .Get (ctx , "lock" )
1790+ Expect (get .Err ()).To (Equal (redis .Nil ))
1791+ })
1792+
1793+ It ("should DelEx fail when value does not match" , func () {
1794+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1795+
1796+ // Set initial value
1797+ err := client .Set (ctx , "lock" , "token-123" , 0 ).Err ()
1798+ Expect (err ).NotTo (HaveOccurred ())
1799+
1800+ // Try to delete with wrong value
1801+ deleted := client .DelEx (ctx , "lock" , "wrong-token" )
1802+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1803+ Expect (deleted .Val ()).To (Equal (int64 (0 )))
1804+
1805+ // Verify key was NOT deleted
1806+ val , err := client .Get (ctx , "lock" ).Result ()
1807+ Expect (err ).NotTo (HaveOccurred ())
1808+ Expect (val ).To (Equal ("token-123" ))
1809+ })
1810+
1811+ It ("should DelEx on non-existent key" , func () {
1812+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1813+
1814+ // Try to delete non-existent key
1815+ deleted := client .DelEx (ctx , "nonexistent" , "any-value" )
1816+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1817+ Expect (deleted .Val ()).To (Equal (int64 (0 )))
1818+ })
1819+
1820+ It ("should DelExArgs with IFEQ" , func () {
1821+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1822+
1823+ // Set initial value
1824+ err := client .Set (ctx , "temp-key" , "temp-value" , 0 ).Err ()
1825+ Expect (err ).NotTo (HaveOccurred ())
1826+
1827+ // Delete with IFEQ
1828+ args := redis.DelExArgs {
1829+ Mode : "IFEQ" ,
1830+ MatchValue : "temp-value" ,
1831+ }
1832+ deleted := client .DelExArgs (ctx , "temp-key" , args )
1833+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1834+ Expect (deleted .Val ()).To (Equal (int64 (1 )))
1835+
1836+ // Verify key was deleted
1837+ get := client .Get (ctx , "temp-key" )
1838+ Expect (get .Err ()).To (Equal (redis .Nil ))
1839+ })
1840+
1841+ It ("should DelExArgs with IFNE" , func () {
1842+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1843+
1844+ // Set initial value
1845+ err := client .Set (ctx , "key" , "temporary" , 0 ).Err ()
1846+ Expect (err ).NotTo (HaveOccurred ())
1847+
1848+ // Delete only if value is NOT "permanent"
1849+ args := redis.DelExArgs {
1850+ Mode : "IFNE" ,
1851+ MatchValue : "permanent" ,
1852+ }
1853+ deleted := client .DelExArgs (ctx , "key" , args )
1854+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1855+ Expect (deleted .Val ()).To (Equal (int64 (1 )))
1856+
1857+ // Verify key was deleted
1858+ get := client .Get (ctx , "key" )
1859+ Expect (get .Err ()).To (Equal (redis .Nil ))
1860+ })
1861+
1862+ It ("should DelExArgs with IFNE fail when value matches" , func () {
1863+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1864+
1865+ // Set initial value
1866+ err := client .Set (ctx , "key" , "permanent" , 0 ).Err ()
1867+ Expect (err ).NotTo (HaveOccurred ())
1868+
1869+ // Try to delete but value matches (should fail)
1870+ args := redis.DelExArgs {
1871+ Mode : "IFNE" ,
1872+ MatchValue : "permanent" ,
1873+ }
1874+ deleted := client .DelExArgs (ctx , "key" , args )
1875+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1876+ Expect (deleted .Val ()).To (Equal (int64 (0 )))
1877+
1878+ // Verify key was NOT deleted
1879+ val , err := client .Get (ctx , "key" ).Result ()
1880+ Expect (err ).NotTo (HaveOccurred ())
1881+ Expect (val ).To (Equal ("permanent" ))
1882+ })
1883+
1884+ It ("should Digest" , func () {
1885+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1886+
1887+ // Set a value
1888+ err := client .Set (ctx , "my-key" , "my-value" , 0 ).Err ()
1889+ Expect (err ).NotTo (HaveOccurred ())
1890+
1891+ // Get digest
1892+ digest := client .Digest (ctx , "my-key" )
1893+ Expect (digest .Err ()).NotTo (HaveOccurred ())
1894+ Expect (digest .Val ()).NotTo (BeEmpty ())
1895+
1896+ // Digest should be consistent
1897+ digest2 := client .Digest (ctx , "my-key" )
1898+ Expect (digest2 .Err ()).NotTo (HaveOccurred ())
1899+ Expect (digest2 .Val ()).To (Equal (digest .Val ()))
1900+ })
1901+
1902+ It ("should Digest on non-existent key" , func () {
1903+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1904+
1905+ // Get digest of non-existent key
1906+ digest := client .Digest (ctx , "nonexistent" )
1907+ Expect (digest .Err ()).To (Equal (redis .Nil ))
1908+ })
1909+
1910+ It ("should use Digest with SetArgs IFDEQ" , func () {
1911+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1912+
1913+ // Set initial value
1914+ err := client .Set (ctx , "key" , "value1" , 0 ).Err ()
1915+ Expect (err ).NotTo (HaveOccurred ())
1916+
1917+ // Get digest
1918+ digest := client .Digest (ctx , "key" )
1919+ Expect (digest .Err ()).NotTo (HaveOccurred ())
1920+
1921+ // Update using digest
1922+ args := redis.SetArgs {
1923+ Mode : "IFDEQ" ,
1924+ MatchDigest : digest .Val (),
1925+ }
1926+ result := client .SetArgs (ctx , "key" , "value2" , args )
1927+ Expect (result .Err ()).NotTo (HaveOccurred ())
1928+ Expect (result .Val ()).To (Equal ("OK" ))
1929+
1930+ // Verify value was updated
1931+ val , err := client .Get (ctx , "key" ).Result ()
1932+ Expect (err ).NotTo (HaveOccurred ())
1933+ Expect (val ).To (Equal ("value2" ))
1934+ })
1935+
1936+ It ("should use Digest with DelExArgs IFDEQ" , func () {
1937+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
1938+
1939+ // Set initial value
1940+ err := client .Set (ctx , "key" , "value" , 0 ).Err ()
1941+ Expect (err ).NotTo (HaveOccurred ())
1942+
1943+ // Get digest
1944+ digest := client .Digest (ctx , "key" )
1945+ Expect (digest .Err ()).NotTo (HaveOccurred ())
1946+
1947+ // Delete using digest
1948+ args := redis.DelExArgs {
1949+ Mode : "IFDEQ" ,
1950+ MatchDigest : digest .Val (),
1951+ }
1952+ deleted := client .DelExArgs (ctx , "key" , args )
1953+ Expect (deleted .Err ()).NotTo (HaveOccurred ())
1954+ Expect (deleted .Val ()).To (Equal (int64 (1 )))
1955+
1956+ // Verify key was deleted
1957+ get := client .Get (ctx , "key" )
1958+ Expect (get .Err ()).To (Equal (redis .Nil ))
1959+ })
1960+
17761961 It ("should Incr" , func () {
17771962 set := client .Set (ctx , "key" , "10" , 0 )
17781963 Expect (set .Err ()).NotTo (HaveOccurred ())
@@ -2320,6 +2505,172 @@ var _ = Describe("Commands", func() {
23202505 Expect (ttl ).NotTo (Equal (- 1 ))
23212506 })
23222507
2508+ It ("should SetIFEQ when value matches" , func () {
2509+ if RedisVersion < 8.4 {
2510+ Skip ("CAS/CAD commands require Redis >= 8.4" )
2511+ }
2512+
2513+ // Set initial value
2514+ err := client .Set (ctx , "key" , "old-value" , 0 ).Err ()
2515+ Expect (err ).NotTo (HaveOccurred ())
2516+
2517+ // Update only if current value is "old-value"
2518+ result := client .SetIFEQ (ctx , "key" , "new-value" , "old-value" , 0 )
2519+ Expect (result .Err ()).NotTo (HaveOccurred ())
2520+ Expect (result .Val ()).To (Equal ("OK" ))
2521+
2522+ // Verify value was updated
2523+ val , err := client .Get (ctx , "key" ).Result ()
2524+ Expect (err ).NotTo (HaveOccurred ())
2525+ Expect (val ).To (Equal ("new-value" ))
2526+ })
2527+
2528+ It ("should SetIFEQ fail when value does not match" , func () {
2529+ if RedisVersion < 8.4 {
2530+ Skip ("CAS/CAD commands require Redis >= 8.4" )
2531+ }
2532+
2533+ // Set initial value
2534+ err := client .Set (ctx , "key" , "current-value" , 0 ).Err ()
2535+ Expect (err ).NotTo (HaveOccurred ())
2536+
2537+ // Try to update with wrong match value
2538+ result := client .SetIFEQ (ctx , "key" , "new-value" , "wrong-value" , 0 )
2539+ Expect (result .Err ()).To (Equal (redis .Nil ))
2540+
2541+ // Verify value was NOT updated
2542+ val , err := client .Get (ctx , "key" ).Result ()
2543+ Expect (err ).NotTo (HaveOccurred ())
2544+ Expect (val ).To (Equal ("current-value" ))
2545+ })
2546+
2547+ It ("should SetIFEQ with expiration" , func () {
2548+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2549+
2550+ // Set initial value
2551+ err := client .Set (ctx , "key" , "token-123" , 0 ).Err ()
2552+ Expect (err ).NotTo (HaveOccurred ())
2553+
2554+ // Update with expiration
2555+ result := client .SetIFEQ (ctx , "key" , "token-456" , "token-123" , 500 * time .Millisecond )
2556+ Expect (result .Err ()).NotTo (HaveOccurred ())
2557+ Expect (result .Val ()).To (Equal ("OK" ))
2558+
2559+ // Verify value was updated
2560+ val , err := client .Get (ctx , "key" ).Result ()
2561+ Expect (err ).NotTo (HaveOccurred ())
2562+ Expect (val ).To (Equal ("token-456" ))
2563+
2564+ // Wait for expiration
2565+ Eventually (func () error {
2566+ return client .Get (ctx , "key" ).Err ()
2567+ }, "1s" , "100ms" ).Should (Equal (redis .Nil ))
2568+ })
2569+
2570+ It ("should SetIFNE when value does not match" , func () {
2571+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2572+
2573+ // Set initial value
2574+ err := client .Set (ctx , "key" , "pending" , 0 ).Err ()
2575+ Expect (err ).NotTo (HaveOccurred ())
2576+
2577+ // Update only if current value is NOT "completed"
2578+ result := client .SetIFNE (ctx , "key" , "processing" , "completed" , 0 )
2579+ Expect (result .Err ()).NotTo (HaveOccurred ())
2580+ Expect (result .Val ()).To (Equal ("OK" ))
2581+
2582+ // Verify value was updated
2583+ val , err := client .Get (ctx , "key" ).Result ()
2584+ Expect (err ).NotTo (HaveOccurred ())
2585+ Expect (val ).To (Equal ("processing" ))
2586+ })
2587+
2588+ It ("should SetIFNE fail when value matches" , func () {
2589+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2590+
2591+ // Set initial value
2592+ err := client .Set (ctx , "key" , "completed" , 0 ).Err ()
2593+ Expect (err ).NotTo (HaveOccurred ())
2594+
2595+ // Try to update but value matches (should fail)
2596+ result := client .SetIFNE (ctx , "key" , "processing" , "completed" , 0 )
2597+ Expect (result .Err ()).To (Equal (redis .Nil ))
2598+
2599+ // Verify value was NOT updated
2600+ val , err := client .Get (ctx , "key" ).Result ()
2601+ Expect (err ).NotTo (HaveOccurred ())
2602+ Expect (val ).To (Equal ("completed" ))
2603+ })
2604+
2605+ It ("should SetArgs with IFEQ" , func () {
2606+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2607+
2608+ // Set initial value
2609+ err := client .Set (ctx , "counter" , "100" , 0 ).Err ()
2610+ Expect (err ).NotTo (HaveOccurred ())
2611+
2612+ // Update with IFEQ
2613+ args := redis.SetArgs {
2614+ Mode : "IFEQ" ,
2615+ MatchValue : "100" ,
2616+ TTL : 1 * time .Hour ,
2617+ }
2618+ result := client .SetArgs (ctx , "counter" , "200" , args )
2619+ Expect (result .Err ()).NotTo (HaveOccurred ())
2620+ Expect (result .Val ()).To (Equal ("OK" ))
2621+
2622+ // Verify value was updated
2623+ val , err := client .Get (ctx , "counter" ).Result ()
2624+ Expect (err ).NotTo (HaveOccurred ())
2625+ Expect (val ).To (Equal ("200" ))
2626+ })
2627+
2628+ It ("should SetArgs with IFEQ and GET" , func () {
2629+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2630+
2631+ // Set initial value
2632+ err := client .Set (ctx , "key" , "old" , 0 ).Err ()
2633+ Expect (err ).NotTo (HaveOccurred ())
2634+
2635+ // Update with IFEQ and GET old value
2636+ args := redis.SetArgs {
2637+ Mode : "IFEQ" ,
2638+ MatchValue : "old" ,
2639+ Get : true ,
2640+ }
2641+ result := client .SetArgs (ctx , "key" , "new" , args )
2642+ Expect (result .Err ()).NotTo (HaveOccurred ())
2643+ Expect (result .Val ()).To (Equal ("old" ))
2644+
2645+ // Verify value was updated
2646+ val , err := client .Get (ctx , "key" ).Result ()
2647+ Expect (err ).NotTo (HaveOccurred ())
2648+ Expect (val ).To (Equal ("new" ))
2649+ })
2650+
2651+ It ("should SetArgs with IFNE" , func () {
2652+ SkipBeforeRedisVersion (8.4 , "CAS/CAD commands require Redis >= 8.4" )
2653+
2654+ // Set initial value
2655+ err := client .Set (ctx , "status" , "pending" , 0 ).Err ()
2656+ Expect (err ).NotTo (HaveOccurred ())
2657+
2658+ // Update with IFNE
2659+ args := redis.SetArgs {
2660+ Mode : "IFNE" ,
2661+ MatchValue : "completed" ,
2662+ TTL : 30 * time .Minute ,
2663+ }
2664+ result := client .SetArgs (ctx , "status" , "processing" , args )
2665+ Expect (result .Err ()).NotTo (HaveOccurred ())
2666+ Expect (result .Val ()).To (Equal ("OK" ))
2667+
2668+ // Verify value was updated
2669+ val , err := client .Get (ctx , "status" ).Result ()
2670+ Expect (err ).NotTo (HaveOccurred ())
2671+ Expect (val ).To (Equal ("processing" ))
2672+ })
2673+
23232674 It ("should SetRange" , func () {
23242675 set := client .Set (ctx , "key" , "Hello World" , 0 )
23252676 Expect (set .Err ()).NotTo (HaveOccurred ())
0 commit comments