Skip to content

Commit 5aa3578

Browse files
committed
test: ACLList, ACLCat, ACLSetUser, FunctionStats, and LCS etc in rueidiscompat
Signed-off-by: Rueian <[email protected]>
1 parent ecd3800 commit 5aa3578

File tree

5 files changed

+343
-10
lines changed

5 files changed

+343
-10
lines changed

rueidiscompat/adapter.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ type CoreCmdable interface {
343343
ShutdownNoSave(ctx context.Context) *StatusCmd
344344
SlaveOf(ctx context.Context, host, port string) *StatusCmd
345345
SlowLogGet(ctx context.Context, num int64) *SlowLogCmd
346+
SlowLogReset(ctx context.Context) *StatusCmd
346347
Time(ctx context.Context) *TimeCmd
347348
DebugObject(ctx context.Context, key string) *StringCmd
348349
ReadOnly(ctx context.Context) *StatusCmd
@@ -2776,6 +2777,12 @@ func (c *Compat) SlowLogGet(ctx context.Context, num int64) *SlowLogCmd {
27762777
return newSlowLogCmd(resp)
27772778
}
27782779

2780+
func (c *Compat) SlowLogReset(ctx context.Context) *StatusCmd {
2781+
cmd := c.client.B().SlowlogReset().Build()
2782+
resp := c.client.Do(ctx, cmd)
2783+
return newStatusCmd(resp)
2784+
}
2785+
27792786
func (c *Compat) Time(ctx context.Context) *TimeCmd {
27802787
cmd := c.client.B().Time().Build()
27812788
resp := c.client.Do(ctx, cmd)
@@ -2899,9 +2906,7 @@ func (c *Compat) FunctionFlush(ctx context.Context) *StringCmd {
28992906
}
29002907

29012908
func (c *Compat) FunctionKill(ctx context.Context) *StringCmd {
2902-
return c.doStringCmdPrimaries(ctx, func(c rueidis.Client) rueidis.Completed {
2903-
return c.B().FunctionKill().Build()
2904-
})
2909+
return newStringCmd(c.client.Do(ctx, c.client.B().FunctionKill().Build()))
29052910
}
29062911

29072912
func (c *Compat) FunctionFlushAsync(ctx context.Context) *StringCmd {

rueidiscompat/adapter_test.go

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,12 +2136,128 @@ func testAdapter(resp3 bool) {
21362136
replace := adapter.Copy(ctx, "newKey", "key", 0, true)
21372137
Expect(replace.Val()).To(Equal(int64(1)))
21382138
})
2139+
}
2140+
})
2141+
2142+
Describe("ACL", func() {
2143+
if resp3 {
2144+
TestUserName := "test"
2145+
It("should ACL LOG", func() {
2146+
Expect(adapter.ACLLogReset(ctx).Err()).NotTo(HaveOccurred())
2147+
err := adapter.ACLSetUser(ctx, "test", ">test", "on", "allkeys", "+get").Err()
2148+
Expect(err).NotTo(HaveOccurred())
2149+
2150+
for addr := range clientresp3.Nodes() {
2151+
clientAcl, err := rueidis.NewClient(rueidis.ClientOption{
2152+
InitAddress: []string{addr},
2153+
Username: "test",
2154+
Password: "test",
2155+
DisableCache: true,
2156+
})
2157+
Expect(err).NotTo(HaveOccurred())
2158+
adapterACL := NewAdapter(clientAcl)
2159+
_ = adapterACL.Set(ctx, "mystring", "foo", 0).Err()
2160+
_ = adapterACL.HSet(ctx, "myhash", "foo", "bar").Err()
2161+
_ = adapterACL.SAdd(ctx, "myset", "foo", "bar").Err()
2162+
clientAcl.Close()
2163+
break
2164+
}
2165+
2166+
logEntries, err := adapter.ACLLog(ctx, 10).Result()
2167+
Expect(err).NotTo(HaveOccurred())
2168+
Expect(len(logEntries)).To(Equal(6))
2169+
2170+
for _, entry := range logEntries {
2171+
Expect(entry.Reason).To(Equal("command"))
2172+
Expect(entry.Context).To(Equal("toplevel"))
2173+
Expect(entry.Object).NotTo(BeEmpty())
2174+
Expect(entry.Username).To(Equal("test"))
2175+
Expect(entry.AgeSeconds).To(BeNumerically(">=", 0))
2176+
Expect(entry.ClientInfo).NotTo(BeNil())
2177+
Expect(entry.EntryID).To(BeNumerically(">=", 0))
2178+
Expect(entry.TimestampCreated).To(BeNumerically(">=", 0))
2179+
Expect(entry.TimestampLastUpdated).To(BeNumerically(">=", 0))
2180+
}
2181+
2182+
limitedLogEntries, err := adapter.ACLLog(ctx, 2).Result()
2183+
Expect(err).NotTo(HaveOccurred())
2184+
Expect(len(limitedLogEntries)).To(Equal(2))
2185+
2186+
// cleanup after creating the user
2187+
err = adapter.ACLDelUser(ctx, "test").Err()
2188+
Expect(err).NotTo(HaveOccurred())
2189+
})
2190+
2191+
It("should ACL LOG RESET", func() {
2192+
// Call ACL LOG RESET
2193+
resetCmd := adapter.ACLLogReset(ctx)
2194+
Expect(resetCmd.Err()).NotTo(HaveOccurred())
2195+
Expect(resetCmd.Val()).To(Equal("OK"))
2196+
2197+
// Verify that the log is empty after the reset
2198+
logEntries, err := adapter.ACLLog(ctx, 10).Result()
2199+
Expect(err).NotTo(HaveOccurred())
2200+
Expect(len(logEntries)).To(Equal(0))
2201+
})
2202+
2203+
It("list only default user", func() {
2204+
res, err := adapter.ACLList(ctx).Result()
2205+
Expect(err).NotTo(HaveOccurred())
2206+
Expect(res).To(HaveLen(1))
2207+
Expect(res[0]).To(ContainSubstring("default"))
2208+
})
2209+
2210+
It("setuser and deluser", func() {
2211+
res, err := adapter.ACLList(ctx).Result()
2212+
Expect(err).NotTo(HaveOccurred())
2213+
Expect(res).To(HaveLen(1))
2214+
Expect(res[0]).To(ContainSubstring("default"))
2215+
2216+
add, err := adapter.ACLSetUser(ctx, TestUserName, "nopass", "on", "allkeys", "+set", "+get").Result()
2217+
Expect(err).NotTo(HaveOccurred())
2218+
Expect(add).To(Equal("OK"))
2219+
2220+
resAfter, err := adapter.ACLList(ctx).Result()
2221+
Expect(err).NotTo(HaveOccurred())
2222+
Expect(resAfter).To(HaveLen(2))
2223+
Expect(resAfter[1]).To(ContainSubstring(TestUserName))
2224+
2225+
deletedN, err := adapter.ACLDelUser(ctx, TestUserName).Result()
2226+
Expect(err).NotTo(HaveOccurred())
2227+
Expect(deletedN).To(BeNumerically("==", 1))
2228+
2229+
resAfterDeletion, err := adapter.ACLList(ctx).Result()
2230+
Expect(err).NotTo(HaveOccurred())
2231+
Expect(resAfterDeletion).To(HaveLen(1))
2232+
Expect(resAfterDeletion[0]).To(BeEquivalentTo(res[0]))
2233+
})
21392234

21402235
It("should acl dryrun", func() {
21412236
dryRun := adapter.ACLDryRun(ctx, "default", "get", "randomKey")
21422237
Expect(dryRun.Err()).NotTo(HaveOccurred())
21432238
Expect(dryRun.Val()).To(Equal("OK"))
21442239
})
2240+
2241+
It("lists acl categories and subcategories", func() {
2242+
res, err := adapter.ACLCat(ctx).Result()
2243+
Expect(err).NotTo(HaveOccurred())
2244+
Expect(len(res)).To(BeNumerically(">", 20))
2245+
Expect(res).To(ContainElements(
2246+
"read",
2247+
"write",
2248+
"keyspace",
2249+
"dangerous",
2250+
"slow",
2251+
"set",
2252+
"sortedset",
2253+
"list",
2254+
"hash",
2255+
))
2256+
2257+
res, err = adapter.ACLCatArgs(ctx, &ACLCatArgs{Category: "read"}).Result()
2258+
Expect(err).NotTo(HaveOccurred())
2259+
Expect(res).To(ContainElement("get"))
2260+
})
21452261
}
21462262
})
21472263

@@ -2738,6 +2854,88 @@ func testAdapter(resp3 bool) {
27382854
Expect(v).To(Equal("c"))
27392855
})
27402856

2857+
if resp3 {
2858+
It("should LCS", func() {
2859+
err := adapter.MSet(ctx, "LCSkey1{1}", "ohmytext", "LCSkey2{1}", "mynewtext").Err()
2860+
Expect(err).NotTo(HaveOccurred())
2861+
2862+
lcs, err := adapter.LCS(ctx, &LCSQuery{
2863+
Key1: "LCSkey1{1}",
2864+
Key2: "LCSkey2{1}",
2865+
}).Result()
2866+
2867+
Expect(err).NotTo(HaveOccurred())
2868+
Expect(lcs.MatchString).To(Equal("mytext"))
2869+
2870+
lcs, err = adapter.LCS(ctx, &LCSQuery{
2871+
Key1: "LCSnonexistent_key1{1}",
2872+
Key2: "LCSkey2{1}",
2873+
}).Result()
2874+
2875+
Expect(err).NotTo(HaveOccurred())
2876+
Expect(lcs.MatchString).To(Equal(""))
2877+
2878+
lcs, err = adapter.LCS(ctx, &LCSQuery{
2879+
Key1: "LCSkey1{1}",
2880+
Key2: "LCSkey2{1}",
2881+
Len: true,
2882+
}).Result()
2883+
Expect(err).NotTo(HaveOccurred())
2884+
Expect(lcs.MatchString).To(Equal(""))
2885+
Expect(lcs.Len).To(Equal(int64(6)))
2886+
2887+
lcs, err = adapter.LCS(ctx, &LCSQuery{
2888+
Key1: "LCSkey1{1}",
2889+
Key2: "LCSkey2{1}",
2890+
Idx: true,
2891+
}).Result()
2892+
Expect(err).NotTo(HaveOccurred())
2893+
Expect(lcs.MatchString).To(Equal(""))
2894+
Expect(lcs.Len).To(Equal(int64(6)))
2895+
Expect(lcs.Matches).To(Equal([]LCSMatchedPosition{
2896+
{
2897+
Key1: LCSPosition{Start: 4, End: 7},
2898+
Key2: LCSPosition{Start: 5, End: 8},
2899+
MatchLen: 0,
2900+
},
2901+
{
2902+
Key1: LCSPosition{Start: 2, End: 3},
2903+
Key2: LCSPosition{Start: 0, End: 1},
2904+
MatchLen: 0,
2905+
},
2906+
}))
2907+
2908+
lcs, err = adapter.LCS(ctx, &LCSQuery{
2909+
Key1: "LCSkey1{1}",
2910+
Key2: "LCSkey2{1}",
2911+
Idx: true,
2912+
MinMatchLen: 3,
2913+
WithMatchLen: true,
2914+
}).Result()
2915+
Expect(err).NotTo(HaveOccurred())
2916+
Expect(lcs.MatchString).To(Equal(""))
2917+
Expect(lcs.Len).To(Equal(int64(6)))
2918+
Expect(lcs.Matches).To(Equal([]LCSMatchedPosition{
2919+
{
2920+
Key1: LCSPosition{Start: 4, End: 7},
2921+
Key2: LCSPosition{Start: 5, End: 8},
2922+
MatchLen: 4,
2923+
},
2924+
}))
2925+
2926+
_, err = adapter.Set(ctx, "keywithstringvalue{1}", "golang", 0).Result()
2927+
Expect(err).NotTo(HaveOccurred())
2928+
_, err = adapter.LPush(ctx, "keywithnonstringvalue{1}", "somevalue").Result()
2929+
Expect(err).NotTo(HaveOccurred())
2930+
_, err = adapter.LCS(ctx, &LCSQuery{
2931+
Key1: "keywithstringvalue{1}",
2932+
Key2: "keywithnonstringvalue{1}",
2933+
}).Result()
2934+
Expect(err).To(HaveOccurred())
2935+
Expect(err.Error()).To(Equal("The specified keys must contain string values"))
2936+
})
2937+
}
2938+
27412939
It("should LIndex", func() {
27422940
lPush := adapter.LPush(ctx, "list", "World")
27432941
Expect(lPush.Err()).NotTo(HaveOccurred())
@@ -7108,6 +7306,98 @@ func testAdapterCache(resp3 bool) {
71087306
Expect(x.Err()).NotTo(HaveOccurred())
71097307
Expect(x.Text()).To(Equal("Function 2"))
71107308
})
7309+
7310+
It("Shows function stats", func() {
7311+
defer func() {
7312+
for i := 0; i < 30; i++ {
7313+
adapter.FunctionKill(ctx)
7314+
}
7315+
}()
7316+
7317+
// We can not run blocking commands in Redis functions, so we're using an infinite loop,
7318+
// but we're killing the function after calling FUNCTION STATS
7319+
lib := Library{
7320+
Name: "mylib1",
7321+
Engine: "LUA",
7322+
Functions: []Function{
7323+
{
7324+
Name: "lib1_func1",
7325+
Description: "This is the func-1 of lib 1",
7326+
Flags: []string{"no-writes"},
7327+
},
7328+
},
7329+
Code: `#!lua name=%s
7330+
local function f1(keys, args)
7331+
local i = 0
7332+
while true do
7333+
i = i + 1
7334+
end
7335+
end
7336+
7337+
redis.register_function{
7338+
function_name='%s',
7339+
description ='%s',
7340+
callback=f1,
7341+
flags={'%s'}
7342+
}`,
7343+
}
7344+
libCode := fmt.Sprintf(lib.Code, lib.Name, lib.Functions[0].Name,
7345+
lib.Functions[0].Description, lib.Functions[0].Flags[0])
7346+
err := adapter.FunctionLoad(ctx, libCode).Err()
7347+
7348+
Expect(err).NotTo(HaveOccurred())
7349+
7350+
r, err := adapter.FunctionStats(ctx).Result()
7351+
Expect(err).NotTo(HaveOccurred())
7352+
Expect(len(r.Engines)).To(Equal(1))
7353+
Expect(r.Running()).To(BeFalse())
7354+
7355+
started := make(chan bool, 1)
7356+
go func() {
7357+
defer GinkgoRecover()
7358+
7359+
for addr := range clientresp3.Nodes() {
7360+
client2, err := rueidis.NewClient(rueidis.ClientOption{InitAddress: []string{addr}})
7361+
Expect(err).NotTo(HaveOccurred())
7362+
adapter2 := NewAdapter(client2)
7363+
started <- true
7364+
adapter2.FCall(ctx, lib.Functions[0].Name, nil).Result()
7365+
break
7366+
}
7367+
}()
7368+
7369+
<-started
7370+
time.Sleep(1 * time.Second)
7371+
r, err = adapter.FunctionStats(ctx).Result()
7372+
7373+
Expect(err).NotTo(HaveOccurred())
7374+
Expect(len(r.Engines)).To(Equal(1))
7375+
rs, isRunning := r.RunningScript()
7376+
Expect(isRunning).To(BeTrue())
7377+
Expect(rs.Name).To(Equal(lib.Functions[0].Name))
7378+
Expect(rs.Duration > 0).To(BeTrue())
7379+
7380+
close(started)
7381+
})
7382+
})
7383+
7384+
Describe("SlowLogGet", func() {
7385+
It("returns slow query result", func() {
7386+
const key = "slowlog-log-slower-than"
7387+
7388+
old := adapter.ConfigGet(ctx, key).Val()
7389+
adapter.ConfigSet(ctx, key, "0")
7390+
defer adapter.ConfigSet(ctx, key, old[key])
7391+
7392+
err := adapter.SlowLogReset(ctx).Err()
7393+
Expect(err).NotTo(HaveOccurred())
7394+
7395+
adapter.Set(ctx, "test", "true", 0)
7396+
7397+
result, err := adapter.SlowLogGet(ctx, -1).Result()
7398+
Expect(err).NotTo(HaveOccurred())
7399+
Expect(len(result)).NotTo(BeZero())
7400+
})
71117401
})
71127402
}
71137403

rueidiscompat/command.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5301,9 +5301,21 @@ func (cmd *LCSCmd) readPosition(res rueidis.RedisMessage) (LCSPosition, error) {
53015301

53025302
type FunctionStats struct {
53035303
Engines []Engine
5304-
IsRunning bool
5305-
Rs RunningScript
5306-
Allrs []RunningScript
5304+
isRunning bool
5305+
rs RunningScript
5306+
allrs []RunningScript
5307+
}
5308+
5309+
func (fs *FunctionStats) Running() bool {
5310+
return fs.isRunning
5311+
}
5312+
5313+
func (fs *FunctionStats) RunningScript() (RunningScript, bool) {
5314+
return fs.rs, fs.isRunning
5315+
}
5316+
5317+
func (fs *FunctionStats) AllRunningScripts() []RunningScript {
5318+
return fs.allrs
53075319
}
53085320

53095321
type FunctionStatsCmd struct {
@@ -5326,7 +5338,7 @@ func (cmd *FunctionStatsCmd) from(res rueidis.RedisResult) {
53265338
for key, val := range mp {
53275339
switch key {
53285340
case "running_script":
5329-
fstats.Rs, fstats.IsRunning, err = cmd.parseRunningScript(val)
5341+
fstats.rs, fstats.isRunning, err = cmd.parseRunningScript(val)
53305342
if err != nil {
53315343
cmd.SetErr(err)
53325344
return
@@ -5338,7 +5350,7 @@ func (cmd *FunctionStatsCmd) from(res rueidis.RedisResult) {
53385350
return
53395351
}
53405352
case "all_running_scripts":
5341-
fstats.Allrs, err = cmd.parseRunningScripts(val)
5353+
fstats.allrs, err = cmd.parseRunningScripts(val)
53425354
if err != nil {
53435355
cmd.SetErr(err)
53445356
return

0 commit comments

Comments
 (0)