Skip to content

Commit

Permalink
CAS command supports EXAT and PXAT options
Browse files Browse the repository at this point in the history
Since we have already implemented these options
in SET / GETEX, the change is very simple.

Some ref links:
- CAS was added in apache#415
- SET EXAP / PXAT options was added in apache#901
- GETEX was added in apache#961
  • Loading branch information
enjoy-binbin committed Aug 7, 2023
1 parent 0e73fec commit 763b6c1
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 5 deletions.
6 changes: 2 additions & 4 deletions src/commands/cmd_string.cc
Original file line number Diff line number Diff line change
Expand Up @@ -559,10 +559,8 @@ class CommandCAS : public Commander {
CommandParser parser(args, 4);
std::string_view flag;
while (parser.Good()) {
if (parser.EatEqICaseFlag("EX", flag)) {
ttl_ = GET_OR_RET(parser.TakeInt<int64_t>(TTL_RANGE<int64_t>)) * 1000;
} else if (parser.EatEqICaseFlag("PX", flag)) {
ttl_ = GET_OR_RET(parser.TakeInt<int64_t>(TTL_RANGE<int64_t>));
if (auto v = GET_OR_RET(ParseTTL(parser, flag))) {
ttl_ = *v;
} else {
return parser.InvalidSyntax();
}
Expand Down
49 changes: 48 additions & 1 deletion tests/gocase/unit/type/strings/strings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -718,26 +718,73 @@ func TestString(t *testing.T) {
require.Equal(t, "", rdb.Get(ctx, "cas_key").Val())
})

t.Run("CAS expire EX option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.EqualValues(t, 1, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 10).Val())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire Duplicate EX option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.EqualValues(t, 1, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 100, "ex", 10).Val())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire PX option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.EqualValues(t, 1, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "px", 10000).Val())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire Duplicate PX option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.EqualValues(t, 1, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "px", 1000, "px", 10000).Val())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire PX option and EX option exist at the same time", func(t *testing.T) {
t.Run("CAS expire EXAT option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.NoError(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "exat", time.Now().Add(10*time.Second).Unix()).Err())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS Duplicate EXAT option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.NoError(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "exat", time.Now().Add(100*time.Second).Unix(), "exat", time.Now().Add(10*time.Second).Unix()).Err())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire PXAT option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.NoError(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "pxat", time.Now().Add(10*time.Second).UnixMilli()).Err())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS Duplicate PXAT option", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.NoError(t, rdb.Do(ctx, "cas", "cas_key", "123", "234", "pxat", time.Now().Add(100*time.Second).UnixMilli(), "pxat", time.Now().Add(10*time.Second).UnixMilli()).Err())
util.BetweenValues(t, rdb.TTL(ctx, "cas_key").Val(), 5*time.Second, 10*time.Second)
})

t.Run("CAS expire mutually exclusive options exist at the same time", func(t *testing.T) {
require.NoError(t, rdb.Del(ctx, "cas_key").Err())
require.NoError(t, rdb.Set(ctx, "cas_key", "123", 0).Err())
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 100, "px", 100000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 100, "ex", 10, "px", 10000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "px", 10000, "ex", 100, "ex", 10, "px", 10000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 100, "exat", 100000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "ex", 100, "pxat", 100000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "px", 100, "exat", 100000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "px", 100, "pxat", 100000).Err(), "syntax error")
require.ErrorContains(t, rdb.Do(ctx, "CAS", "cas_key", "123", "234", "exat", 100, "pxat", 100000).Err(), "syntax error")
})

t.Run("CAD normal case", func(t *testing.T) {
Expand Down

0 comments on commit 763b6c1

Please sign in to comment.