func startTestAppAuth(password string) { f := func() { newTestLedisClientAuth() cfg := config.NewConfigDefault() cfg.DataDir = "/tmp/testdb_auth" os.RemoveAll(cfg.DataDir) cfg.Addr = "127.0.0.1:20000" cfg.HttpAddr = "127.0.0.1:20001" cfg.AuthPassword = password os.RemoveAll(cfg.DataDir) var err error testApp, err = NewApp(cfg) if err != nil { println(err.Error()) panic(err) } go testApp.Run() } testAppAuthOnce.Do(f) }
func startTestApp() { f := func() { newTestLedisClient() cfg := config.NewConfigDefault() cfg.DataDir = "/tmp/testdb" os.RemoveAll(cfg.DataDir) cfg.Addr = "127.0.0.1:16380" cfg.HttpAddr = "127.0.0.1:21181" os.RemoveAll(cfg.DataDir) var err error testApp, err = NewApp(cfg) if err != nil { println(err.Error()) panic(err) } go testApp.Run() } testAppOnce.Do(f) }
func TestScan(t *testing.T) { cfg := config.NewConfigDefault() cfg.DataDir = "/tmp/test_scan" cfg.Addr = "127.0.0.1:11185" os.RemoveAll(cfg.DataDir) s, err := NewApp(cfg) if err != nil { t.Fatal(err) } go s.Run() defer s.Close() c := goredis.NewClient(cfg.Addr, "") c.SetMaxIdleConns(1) defer c.Close() testKVScan(t, c) testHashKeyScan(t, c) testListKeyScan(t, c) testZSetKeyScan(t, c) testSetKeyScan(t, c) }
func TestReplication(t *testing.T) { dir, err := ioutil.TempDir("", "rpl") if err != nil { t.Fatalf("err: %v ", err) } defer os.RemoveAll(dir) c := config.NewConfigDefault() c.Replication.Path = dir r, err := NewReplication(c) if err != nil { t.Fatal(err) } if l1, err := r.Log([]byte("hello world")); err != nil { t.Fatal(err) } else if l1.ID != 1 { t.Fatal(l1.ID) } if b, _ := r.CommitIDBehind(); !b { t.Fatal("must backward") } if err := r.UpdateCommitID(1); err != nil { t.Fatal(err) } if b, _ := r.CommitIDBehind(); b { t.Fatal("must not backward") } r.Close() }
func TestSnapshot(t *testing.T) { cfg := config.NewConfigDefault() cfg.Snapshot.MaxNum = 2 cfg.Snapshot.Path = path.Join(os.TempDir(), "snapshot") defer os.RemoveAll(cfg.Snapshot.Path) d := new(testSnapshotDumper) s, err := newSnapshotStore(cfg) if err != nil { t.Fatal(err) } if f, _, err := s.Create(d); err != nil { t.Fatal(err) } else { defer f.Close() if b, _ := ioutil.ReadAll(f); string(b) != "hello world" { t.Fatal("invalid read snapshot") } if len(s.names) != 1 { t.Fatal("must 1 snapshot") } } if f, _, err := s.Create(d); err != nil { t.Fatal(err) } else { defer f.Close() if b, _ := ioutil.ReadAll(f); string(b) != "hello world" { t.Fatal("invalid read snapshot") } if len(s.names) != 2 { t.Fatal("must 2 snapshot") } } if f, _, err := s.Create(d); err != nil { t.Fatal(err) } else { defer f.Close() if b, _ := ioutil.ReadAll(f); string(b) != "hello world" { t.Fatal("invalid read snapshot") } if len(s.names) != 2 { t.Fatal("must 2 snapshot") } } fs, _ := ioutil.ReadDir(cfg.Snapshot.Path) if len(fs) != 2 { t.Fatal("must 2 snapshot") } s.Close() }
func TestDump(t *testing.T) { cfgM := config.NewConfigDefault() cfgM.DataDir = "/tmp/test_ledis_master" os.RemoveAll(cfgM.DataDir) master, err := Open(cfgM) if err != nil { t.Fatal(err) } cfgS := config.NewConfigDefault() cfgS.DataDir = "/tmp/test_ledis_slave" os.RemoveAll(cfgS.DataDir) var slave *Ledis if slave, err = Open(cfgS); err != nil { t.Fatal(err) } db, _ := master.Select(0) db.Set([]byte("a"), []byte("1")) db.Set([]byte("b"), []byte("2")) db.Set([]byte("c"), []byte("3")) if err := master.DumpFile("/tmp/testdb.dump"); err != nil { t.Fatal(err) } if _, err := slave.LoadDumpFile("/tmp/testdb.dump"); err != nil { t.Fatal(err) } it := master.ldb.RangeLimitIterator(nil, nil, store.RangeClose, 0, -1) for ; it.Valid(); it.Next() { key := it.Key() value := it.Value() if v, err := slave.ldb.Get(key); err != nil { t.Fatal(err) } else if !bytes.Equal(v, value) { t.Fatal("load dump error") } } }
// Start in-process ledis server. Data will go in the specified directory and it will bind to the given port. // Return value is a function you can call to stop the server. func StartLedis(dataDir string, bind string) (stop func(), err error) { cfg := config.NewConfigDefault() cfg.DBName = "goleveldb" cfg.Addr = bind cfg.DataDir = dataDir app, err := server.NewApp(cfg) if err != nil { log.Fatal(err) return func() {}, err } go app.Run() return app.Close, nil }
func main() { runtime.GOMAXPROCS(runtime.NumCPU()) flag.Parse() var cfg *config.Config var err error if len(*configFile) == 0 { println("no config set, using default config") cfg = config.NewConfigDefault() } else { cfg, err = config.NewConfigWithFile(*configFile) } if err != nil { println(err.Error()) return } if len(*dbName) > 0 { cfg.DBName = *dbName } var app *server.App app, err = server.NewApp(cfg) if err != nil { println(err.Error()) return } sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) go func() { <-sc app.Close() }() go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() app.Run() }
/* New(string,bool) initializes a cache object, takes as input database name and a boolean parameter stating whether a compression is needed or not. */ func New(dataDir string) (*Cache, error) { cfg := config.NewConfigDefault() dataDir = fmt.Sprint(cfg.DataDir, "/", dataDir) cfg.DataDir = dataDir cfg.Replication.Compression = false ledis_connection, err := ledis.Open(cfg) if err != nil { panic("Resource temporary unavailable, error opening a Connection!!!") } db, err := ledis_connection.Select(0) return &Cache{ cfg, ledis_connection, db, }, err }
/* Create a backend that stores pushed events in ledisdb. */ func NewLedis(dirname string) (Backend, error) { lcfg := config.NewConfigDefault() lcfg.DataDir = dirname lcfg.Addr = "" lcfg.Databases = 1 ledis, err := ledis.Open(lcfg) if err != nil { return nil, err } db, err := ledis.Select(0) if err != nil { return nil, err } return &ledisBackend{dirname, ledis, db, sync.Mutex{}, map[string]*ledisStreamObj{}}, nil }
func getTestDB() *DB { f := func() { cfg := config.NewConfigDefault() cfg.DataDir = "/tmp/test_ledis" os.RemoveAll(cfg.DataDir) var err error testLedis, err = Open(cfg) if err != nil { println(err.Error()) panic(err) } } testLedisOnce.Do(f) db, _ := testLedis.Select(0) return db }
func NewGoLevelDBStore(base string, syncLog int) (*GoLevelDBStore, error) { cfg := config.NewConfigDefault() cfg.DBName = "goleveldb" cfg.DBPath = base cfg.LevelDB.BlockSize = 16 * 1024 * 1024 cfg.LevelDB.CacheSize = 64 * 1024 * 1024 cfg.LevelDB.WriteBufferSize = 64 * 1024 * 1024 cfg.LevelDB.Compression = false cfg.DBSyncCommit = syncLog s := new(GoLevelDBStore) s.cfg = cfg if err := s.open(); err != nil { return nil, err } return s, nil }
func TestFileStore(t *testing.T) { // Create a test dir dir, err := ioutil.TempDir("", "ldb") if err != nil { t.Fatalf("err: %v ", err) } defer os.RemoveAll(dir) // New level cfg := config.NewConfigDefault() cfg.Replication.MaxLogFileSize = 4096 l, err := NewFileStore(dir, cfg) if err != nil { t.Fatalf("err: %v ", err) } defer l.Close() testLogs(t, l) }
// Open ledis store. func Open(path string, db int, dropDatabase bool) (data.Store, error) { if dropDatabase { if _, err := os.Stat(path); err == nil { os.RemoveAll(path) } } cfg := config.NewConfigDefault() cfg.DataDir = path l, err := ledis.Open(cfg) if err != nil { return nil, debug.Err("open", err) } d, err := l.Select(db) if err != nil { return nil, debug.Err("select", err) } return redis.New(&store{l, d}), nil }
/* New(string,bool) initializes a cache object, takes as input database name and a boolean parameter stating whether a compression is needed or not. */ func New(dbName string, Iscompression bool) *Cache { cfg := config.NewConfigDefault() cfg.DBName = dbName cfg.Replication.Compression = Iscompression ledis_connection, err := ledis.Open(cfg) if err != nil { panic("Resource temporary unavailable, problem in opening a Connection!!!") } db, err := ledis_connection.Select(0) if err != nil { panic("Problem selecting a Database Connection!!!") } return &Cache{ cfg, ledis_connection, db, } }
func TestStore(t *testing.T) { cfg := config.NewConfigDefault() cfg.DataDir = "/tmp/testdb" cfg.LMDB.MapSize = 10 * 1024 * 1024 ns := driver.ListStores() for _, s := range ns { cfg.DBName = s os.RemoveAll(getStorePath(cfg)) db, err := Open(cfg) if err != nil { t.Fatal(err) } testStore(db, t) testClear(db, t) testTx(db, t) db.Close() } }
func TestReplication(t *testing.T) { var master *Ledis var slave *Ledis var err error cfgM := config.NewConfigDefault() cfgM.DataDir = "/tmp/test_repl/master" cfgM.UseReplication = true cfgM.Replication.Compression = true os.RemoveAll(cfgM.DataDir) master, err = Open(cfgM) if err != nil { t.Fatal(err) } defer master.Close() cfgS := config.NewConfigDefault() cfgS.DataDir = "/tmp/test_repl/slave" cfgS.UseReplication = true cfgS.Readonly = true os.RemoveAll(cfgS.DataDir) slave, err = Open(cfgS) if err != nil { t.Fatal(err) } defer slave.Close() db, _ := master.Select(0) db.Set([]byte("a"), []byte("value")) db.Set([]byte("b"), []byte("value")) db.Set([]byte("c"), []byte("value")) db.HSet([]byte("a"), []byte("1"), []byte("value")) db.HSet([]byte("b"), []byte("2"), []byte("value")) db.HSet([]byte("c"), []byte("3"), []byte("value")) // m, _ := db.Multi() // m.Set([]byte("a1"), []byte("value")) // m.Set([]byte("b1"), []byte("value")) // m.Set([]byte("c1"), []byte("value")) // m.Close() slave.FlushAll() db.Set([]byte("a1"), []byte("value")) db.Set([]byte("b1"), []byte("value")) db.Set([]byte("c1"), []byte("value")) db.HSet([]byte("a1"), []byte("1"), []byte("value")) db.HSet([]byte("b1"), []byte("2"), []byte("value")) db.HSet([]byte("c1"), []byte("3"), []byte("value")) var buf bytes.Buffer var n int var id uint64 = 1 for { buf.Reset() n, id, err = master.ReadLogsTo(id, &buf) if err != nil { t.Fatal(err) } else if n != 0 { if err = slave.StoreLogsFromReader(&buf); err != nil { t.Fatal(err) } } else if n == 0 { break } } slave.WaitReplication() if err = checkLedisEqual(master, slave); err != nil { t.Fatal(err) } }
func TestLuaCall(t *testing.T) { cfg := config.NewConfigDefault() cfg.Addr = ":11188" cfg.DataDir = "/tmp/testscript" cfg.DBName = "memory" app, e := NewApp(cfg) if e != nil { t.Fatal(e) } go app.Run() defer app.Close() db, _ := app.ldb.Select(0) luaClient := app.script.c luaClient.db = db l := app.script.l err := app.script.l.DoString(testScript1) if err != nil { t.Fatal(err) } v := luaReplyToLedisReply(l) if vv, ok := v.([]interface{}); ok { if len(vv) != 3 { t.Fatal(len(vv)) } } else { t.Fatal(fmt.Sprintf("%v %T", v, v)) } err = app.script.l.DoString(testScript2) if err != nil { t.Fatal(err) } v = luaReplyToLedisReply(l) if vv := v.(string); vv != "PONG" { t.Fatal(fmt.Sprintf("%v %T", v, v)) } err = app.script.l.DoString(testScript3) if err != nil { t.Fatal(err) } if v, err := db.Get([]byte("1")); err != nil { t.Fatal(err) } else if string(v) != "a" { t.Fatal(string(v)) } err = app.script.l.DoString(testScript4) if err != nil { t.Fatal(err) } if luaClient.db.Index() != 2 { t.Fatal(luaClient.db.Index()) } db2, _ := app.ldb.Select(2) if v, err := db2.Get([]byte("2")); err != nil { t.Fatal(err) } else if string(v) != "b" { t.Fatal(string(v)) } luaClient.db = nil }
func TestReplication(t *testing.T) { data_dir := "/tmp/test_replication" os.RemoveAll(data_dir) masterCfg := config.NewConfigDefault() masterCfg.DataDir = fmt.Sprintf("%s/master", data_dir) masterCfg.Addr = "127.0.0.1:11182" masterCfg.UseReplication = true masterCfg.Replication.Sync = true masterCfg.Replication.WaitSyncTime = 5000 var master *App var slave *App var err error master, err = NewApp(masterCfg) if err != nil { t.Fatal(err) } defer master.Close() slaveCfg := config.NewConfigDefault() slaveCfg.DataDir = fmt.Sprintf("%s/slave", data_dir) slaveCfg.Addr = "127.0.0.1:11183" slaveCfg.SlaveOf = masterCfg.Addr slaveCfg.UseReplication = true slave, err = NewApp(slaveCfg) if err != nil { t.Fatal(err) } defer slave.Close() go master.Run() time.Sleep(1 * time.Second) go slave.Run() db, _ := master.ldb.Select(0) value := make([]byte, 10) db.Set([]byte("a"), value) db.Set([]byte("b"), value) db.Set([]byte("c"), value) db.Set([]byte("d"), value) time.Sleep(1 * time.Second) if err = checkDataEqual(master, slave); err != nil { t.Fatal(err) } db.Set([]byte("a1"), value) db.Set([]byte("b1"), value) db.Set([]byte("c1"), value) db.Set([]byte("d1"), value) //time.Sleep(1 * time.Second) slave.ldb.WaitReplication() if err = checkDataEqual(master, slave); err != nil { t.Fatal(err) } slave.slaveof("", false, false) db.Set([]byte("a2"), value) db.Set([]byte("b2"), value) db.Set([]byte("c2"), value) db.Set([]byte("d2"), value) db.Set([]byte("a3"), value) db.Set([]byte("b3"), value) db.Set([]byte("c3"), value) db.Set([]byte("d3"), value) if err = checkDataEqual(master, slave); err == nil { t.Fatal("must error") } slave.slaveof(masterCfg.Addr, false, false) time.Sleep(1 * time.Second) if err = checkDataEqual(master, slave); err != nil { t.Fatal(err) } mStat, _ := master.ldb.ReplicationStat() sStat, _ := slave.ldb.ReplicationStat() if err = checkTestRole(masterCfg.Addr, []interface{}{ []byte("master"), int64(mStat.LastID), []interface{}{ []interface{}{ []byte("127.0.0.1"), []byte("11183"), []byte(fmt.Sprintf("%d", sStat.LastID)), }}, }); err != nil { t.Fatal(err) } if err = checkTestRole(slaveCfg.Addr, []interface{}{ []byte("slave"), []byte("127.0.0.1"), int64(11182), []byte("connected"), int64(sStat.LastID), }); err != nil { t.Fatal(err) } slave.tryReSlaveof() time.Sleep(1 * time.Second) slave.ldb.WaitReplication() if err = checkDataEqual(master, slave); err != nil { t.Fatal(err) } }
func TestMigrate(t *testing.T) { cfg1 := config.NewConfigDefault() cfg1.DataDir = "/tmp/test_ledisdb_migrate1" os.RemoveAll(cfg1.DataDir) defer os.RemoveAll(cfg1.DataDir) l1, _ := Open(cfg1) defer l1.Close() cfg2 := config.NewConfigDefault() cfg2.DataDir = "/tmp/test_ledisdb_migrate2" os.RemoveAll(cfg2.DataDir) defer os.RemoveAll(cfg2.DataDir) l2, _ := Open(cfg2) defer l2.Close() db1, _ := l1.Select(0) db2, _ := l2.Select(0) key := []byte("a") lkey := []byte("a") hkey := []byte("a") skey := []byte("a") zkey := []byte("a") value := []byte("1") db1.Set(key, value) if data, err := db1.Dump(key); err != nil { t.Fatal(err) } else if err := db2.Restore(key, 0, data); err != nil { t.Fatal(err) } db1.RPush(lkey, []byte("1"), []byte("2"), []byte("3")) if data, err := db1.LDump(lkey); err != nil { t.Fatal(err) } else if err := db2.Restore(lkey, 0, data); err != nil { t.Fatal(err) } db1.SAdd(skey, []byte("1"), []byte("2"), []byte("3")) if data, err := db1.SDump(skey); err != nil { t.Fatal(err) } else if err := db2.Restore(skey, 0, data); err != nil { t.Fatal(err) } db1.HMset(hkey, FVPair{[]byte("a"), []byte("1")}, FVPair{[]byte("b"), []byte("2")}, FVPair{[]byte("c"), []byte("3")}) if data, err := db1.HDump(hkey); err != nil { t.Fatal(err) } else if err := db2.Restore(hkey, 0, data); err != nil { t.Fatal(err) } db1.ZAdd(zkey, ScorePair{1, []byte("a")}, ScorePair{2, []byte("b")}, ScorePair{3, []byte("c")}) if data, err := db1.ZDump(zkey); err != nil { t.Fatal(err) } else if err := db2.Restore(zkey, 0, data); err != nil { t.Fatal(err) } if err := checkLedisEqual(l1, l2); err != nil { t.Fatal(err) } }
package auth import ( lediscfg "github.com/siddontang/ledisdb/config" "github.com/siddontang/ledisdb/ledis" ) var cfg *lediscfg.Config = lediscfg.NewConfigDefault() var l, _ = ledis.Open(cfg) var db, _ = l.Select(0) // BlacklistToken adds the token to a ledis database func BlacklistToken(token []byte, expireAt int64) error { db.Set(token, token) db.ExpireAt(token, expireAt) return nil } // IsBlackListed checks if a token is in the blacklist list func IsBlacklisted(token []byte) (bool, error) { res, err := db.Get(token) if err != nil { return false, err } if res == nil { return false, err }
func main() { runtime.GOMAXPROCS(runtime.NumCPU()) flag.Parse() var cfg *config.Config var err error if len(*configFile) == 0 { println("no config set, using default config") cfg = config.NewConfigDefault() } else { cfg, err = config.NewConfigWithFile(*configFile) } if err != nil { println(err.Error()) return } if len(*addr) > 0 { cfg.Addr = *addr } if len(*dataDir) > 0 { cfg.DataDir = *dataDir } if len(*dbName) > 0 { cfg.DBName = *dbName } if *databases > 0 { cfg.Databases = *databases } // check bool flag, use it. for _, arg := range os.Args { arg := strings.ToLower(arg) switch arg { case "-rpl", "-rpl=true", "-rpl=false": cfg.UseReplication = *rpl case "-readonly", "-readonly=true", "-readonly=false": cfg.Readonly = *readonly case "-rpl_sync", "-rpl_sync=true", "-rpl_sync=false": cfg.Replication.Sync = *rplSync } } if len(*slaveof) > 0 { cfg.SlaveOf = *slaveof cfg.Readonly = true cfg.UseReplication = true } if *ttlCheck > 0 { cfg.TTLCheckInterval = *ttlCheck } var app *server.App app, err = server.NewApp(cfg) if err != nil { println(err.Error()) return } sc := make(chan os.Signal, 1) signal.Notify(sc, os.Kill, os.Interrupt, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) if *usePprof { go func() { log.Println(http.ListenAndServe(fmt.Sprintf(":%d", *pprofPort), nil)) }() } go app.Run() <-sc println("ledis-server is closing") app.Close() println("ledis-server is closed") }
func TestMigrate(t *testing.T) { data_dir := "/tmp/test_migrate" os.RemoveAll(data_dir) s1Cfg := config.NewConfigDefault() s1Cfg.DataDir = fmt.Sprintf("%s/s1", data_dir) s1Cfg.Addr = "127.0.0.1:11185" s2Cfg := config.NewConfigDefault() s2Cfg.DataDir = fmt.Sprintf("%s/s2", data_dir) s2Cfg.Addr = "127.0.0.1:11186" s1, err := NewApp(s1Cfg) if err != nil { t.Fatal(err) } defer s1.Close() s2, err := NewApp(s2Cfg) if err != nil { t.Fatal(err) } defer s2.Close() go s1.Run() go s2.Run() time.Sleep(1 * time.Second) c1, _ := goredis.Connect(s1Cfg.Addr) defer c1.Close() c2, _ := goredis.Connect(s2Cfg.Addr) defer c2.Close() if _, err = c1.Do("set", "a", "1"); err != nil { t.Fatal(err) } timeout := 30000 if _, err = c1.Do("xmigrate", "127.0.0.1", 11186, "KV", "a", 0, timeout); err != nil { t.Fatal(err) } if s, err := goredis.String(c2.Do("get", "a")); err != nil { t.Fatal(err) } else if s != "1" { t.Fatal(s, "must 1") } if s, err := goredis.String(c1.Do("get", "a")); err != nil && err != goredis.ErrNil { t.Fatal(err) } else if s != "" { t.Fatal(s, "must empty") } if num, err := goredis.Int(c2.Do("xmigratedb", "127.0.0.1", 11185, "KV", 10, 0, timeout)); err != nil { t.Fatal(err) } else if num != 1 { t.Fatal(num, "must number 1") } if s, err := goredis.String(c1.Do("get", "a")); err != nil { t.Fatal(err) } else if s != "1" { t.Fatal(s, "must 1") } if s, err := goredis.String(c2.Do("get", "a")); err != nil && err != goredis.ErrNil { t.Fatal(err) } else if s != "" { t.Fatal(s, "must empty") } if _, err = c1.Do("xmigrate", "127.0.0.1", 11186, "ALL", "a", 0, timeout); err != nil { t.Fatal(err) } if s, err := goredis.String(c2.Do("get", "a")); err != nil { t.Fatal(err) } else if s != "1" { t.Fatal(s, "must 1") } if s, err := goredis.String(c1.Do("get", "a")); err != nil && err != goredis.ErrNil { t.Fatal(err) } else if s != "" { t.Fatal(s, "must empty") } }
func TestLuaCall(t *testing.T) { cfg := config.NewConfigDefault() cfg.Addr = ":11188" cfg.DataDir = "/tmp/testscript" cfg.DBName = "memory" app, e := NewApp(cfg) if e != nil { t.Fatal(e) } go app.Run() defer app.Close() db, _ := app.ldb.Select(0) luaClient := app.script.c luaClient.db = db l := app.script.l err := app.script.l.DoString(testScript1) if err != nil { t.Fatal(err) } v := luaReplyToLedisReply(l) if vv, ok := v.([]interface{}); ok { if len(vv) != 3 { t.Fatal(len(vv)) } } else { t.Fatal(fmt.Sprintf("%v %T", v, v)) } err = app.script.l.DoString(testScript2) if err != nil { t.Fatal(err) } v = luaReplyToLedisReply(l) if vv := v.(string); vv != "PONG" { t.Fatal(fmt.Sprintf("%v %T", v, v)) } err = app.script.l.DoString(testScript3) if err != nil { t.Fatal(err) } if v, err := db.Get([]byte("1")); err != nil { t.Fatal(err) } else if string(v) != "a" { t.Fatal(string(v)) } err = app.script.l.DoString(testScript4) if err != nil { t.Fatal(err) } if luaClient.db.Index() != 2 { t.Fatal(luaClient.db.Index()) } db2, _ := app.ldb.Select(2) if v, err := db2.Get([]byte("2")); err != nil { t.Fatal(err) } else if string(v) != "b" { t.Fatal(string(v)) } err = app.script.l.DoString(testScript5) if err != nil { t.Fatal(err) } v = luaReplyToLedisReply(l) if vv := v.(string); vv != "PONG" { t.Fatal(fmt.Sprintf("%v %T", v, v)) } err = app.script.l.DoString(testScript6) if err != nil { t.Fatal(err) } v = luaReplyToLedisReply(l) vv := v.([]interface{}) expected := []string{ "string", "boolean", "string", "boolean", "nil", } if len(expected) != len(vv) { t.Fatalf("length different: %d, %d", len(expected), len(vv)) } for i, r := range vv { s := string(r.([]byte)) if s != expected[i] { t.Errorf("reply[%d] expected: %s, actual: %s", i, expected[i], s) } } luaClient.db = nil }