postgres backend (#48)

This commit is contained in:
Anton Zhiyanov
2025-07-13 13:05:18 +05:00
committed by GitHub
parent 7c532df931
commit 2178c81fca
179 changed files with 8084 additions and 7408 deletions

View File

@@ -13,6 +13,20 @@ on:
jobs:
build:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17-alpine
env:
POSTGRES_USER: redka
POSTGRES_PASSWORD: redka
POSTGRES_DB: redka
options: >-
--health-cmd "pg_isready --username=redka --dbname=redka --quiet"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -20,7 +34,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "stable"
go-version-file: "go.mod"
- name: Install dependencies
run: |
@@ -28,8 +42,15 @@ jobs:
sudo apt-get install -y libsqlite3-dev
go get .
- name: Test and build
run: make test build
- name: Install linter
uses: golangci/golangci-lint-action@v8
- name: Build and test
run: |
make build
make vet lint
make test-sqlite
make test-postgres
- name: Upload artifact
uses: actions/upload-artifact@v4

View File

@@ -3,7 +3,7 @@ name: docker
on:
push:
tags:
- "*"
- "v*.*.*"
workflow_dispatch:
jobs:

View File

@@ -3,7 +3,7 @@ name: publish
on:
push:
tags:
- "*"
- "v*.*.*"
workflow_dispatch:
permissions:
@@ -33,7 +33,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "stable"
go-version-file: "go.mod"
- name: Build binary
run: GOOS=${{ matrix.goos }} make build
@@ -85,3 +85,4 @@ jobs:
file: release/*
file_glob: true
tag: ${{ github.ref }}
draft: true

View File

@@ -1,4 +1,4 @@
.PHONY: setup lint vet test build run
.PHONY: build
has_git := $(shell command -v git 2>/dev/null)
@@ -20,21 +20,60 @@ build_date := $(shell date -u '+%Y-%m-%dT%H:%M:%S')
setup:
@go mod download
lint:
@golangci-lint run --print-issued-lines=false --out-format=colored-line-number ./...
vet:
@echo "> running vet..."
@go vet ./...
@echo "✓ finished vet"
lint:
@echo "> running lint..."
@golangci-lint run ./...
@echo "✓ finished lint"
test:
@go test ./... -v
@echo "> running tests with $(driver) driver..."
@go test -tags=$(driver) ./...
@echo "✓ finished tests"
test-sqlite:
@echo "> running tests with sqlite driver..."
@go test -tags=sqlite3 ./...
@echo "✓ finished tests"
test-postgres:
@echo "> running tests with postgres driver..."
@go test -tags=postgres -p=1 ./...
@echo "✓ finished tests"
build:
@echo "> running build..."
@CGO_ENABLED=1 go build -ldflags "-s -w -X main.version=$(build_ver) -X main.commit=$(build_rev) -X main.date=$(build_date)" -trimpath -o build/redka -v cmd/redka/main.go
@echo "✓ finished build"
build-cli:
@CGO_ENABLED=1 go build -ldflags "-s -w" -trimpath -o build/redka-cli -v cmd/cli/main.go
run:
@./build/redka
postgres-start:
@echo "> starting postgres..."
@docker run --rm --detach --name=redka-postgres \
--env=POSTGRES_DB=redka \
--env=POSTGRES_USER=redka \
--env=POSTGRES_PASSWORD=redka \
--publish=5432:5432 \
--tmpfs /var/lib/postgresql/data \
postgres:17-alpine
@until docker exec redka-postgres \
pg_isready --username=redka --dbname=redka --quiet --quiet; \
do sleep 1; done
@echo "✓ started postgres"
postgres-stop:
@echo "> stopping postgres..."
@docker stop redka-postgres
@echo "✓ stopped postgres"
postgres-shell:
@docker exec -it redka-postgres psql --username=redka --dbname=redka

View File

@@ -1,17 +1,28 @@
<img alt="Redka" src="logo.svg" height="80" align="center">
Redka aims to reimplement the core parts of Redis with SQLite, while remaining compatible with Redis API.
Redka aims to reimplement the core parts of Redis with SQL, while remaining compatible with Redis API.
Notable features:
- Data does not have to fit in RAM.
- ACID transactions.
- SQL views for better introspection and reporting.
- Both in-process (Go API) and standalone (RESP) servers.
- Redis-compatible commands and wire protocol.
- Data doesn't have to fit in RAM.
- Supports ACID transactions.
- SQL views for easier analysis and reporting.
- Works with both SQLite and PostgreSQL (coming v0.6.0) backends.
- Runs in-process (Go API) or as a standalone server.
- Redis-compatible commands and wire protocol (RESP).
Redka is [functionally ready](docs/roadmap.md) for 1.0. Feel free to try it in non-critical production scenarios and provide feedback in the issues.
## Use cases
Here are some situations where Redka might be helpful:
_Embedded cache for Go applications_. If your Go app already uses SQLite or just needs a simple, built-in key-value store, Redka is a natural fit. It gives you Redis-like features without the hassle of running a separate server. The cache persists across application restarts, and backup is as easy as copying a file.
_Lightweight testing environment_. Your app uses Redis in production, but setting up a Redis server for local development or integration tests can be a hassle. Redka, when used with an in-memory SQLite database, gives you a fast alternative with complete isolation for each test run.
_Postgres-first data structures_. If you prefer to use PostgreSQL for everything but need Redis-like data structures (like lists and sorted sets), Redka can use your existing database as the backend. This way, you can manage both relational data and specialized data structures with the same tools and transactional guarantees.
## Commands
Redka supports five core Redis data types:
@@ -31,17 +42,21 @@ Redka comes in two flavors:
- Standalone Redis-compatible server: [installation](docs/install-standalone.md), [usage](docs/usage-standalone.md).
- Go module for in-process use: [installation](docs/install-module.md), [usage](docs/usage-module.md).
## Storage
Redka can use either SQLite or PostgreSQL as its backend. It stores data in a [SQL database](docs/persistence.md) with a simple schema and provides views for better introspection.
## Performance
According to the [benchmarks](docs/performance.md), Redka is several times slower than Redis. Still, it can do up to 100K op/sec on a Macbook Air, which is pretty good if you ask me (and probably 10x more than most applications will ever need).
Redka is not about raw performance. You can't beat a specialized data store like Redis with a general-purpose relational backend like SQLite. However, Redka can still handle tens of thousands of operations per second, which should be more than enough for many apps.
Redka stores data in a [SQLite database](docs/persistence.md) with a simple schema and provides views for better introspection.
See the [benchmarks](docs/performance.md) for more details.
## Contributing
Contributions are welcome. For anything other than bugfixes, please first open an issue to discuss what you want to change.
Be sure to add or update tests as appropriate.
Make sure to add or update tests as needed.
## Acknowledgements

View File

@@ -17,7 +17,7 @@ const dbURI = "file:/data.db?vfs=memdb"
func init() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: redka-cli <filename>\n")
_, _ = fmt.Fprintf(flag.CommandLine.Output(), "Usage: redka-cli <filename>\n")
flag.PrintDefaults()
}
}

View File

@@ -1,24 +1,29 @@
// Redka server.
// Example usage:
//
// Example usage (SQLite):
//
// ./redka -h localhost -p 6379 redka.db
//
// Example usage (client):
// Example usage (PostgreSQL):
//
// docker run --rm -it redis redis-cli -h host.docker.internal -p 6379
// ./redka -h localhost -p 6379 "postgres://redka:redka@localhost:5432/redka?sslmode=disable"
package main
import (
"cmp"
"context"
"database/sql"
"flag"
"fmt"
"log/slog"
"net"
"net/url"
"os"
"os/signal"
"strings"
"syscall"
_ "github.com/lib/pq"
"github.com/mattn/go-sqlite3"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/server"
@@ -31,9 +36,10 @@ var (
date = "unknown"
)
const driverName = "redka"
const memoryURI = "file:/data.db?vfs=memdb"
const pragma = `
const debugPort = 6060
const sqliteDriverName = "sqlite-redka"
const sqliteMemoryURI = "file:/redka.db?vfs=memdb"
const sqlitePragma = `
pragma journal_mode = wal;
pragma synchronous = normal;
pragma temp_store = memory;
@@ -53,100 +59,41 @@ func (c *Config) Addr() string {
return net.JoinHostPort(c.Host, c.Port)
}
var config Config
func init() {
// Set up command line flags.
// Set up flag usage message.
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage: redka [options] <data-source>\n")
_, _ = fmt.Fprintf(flag.CommandLine.Output(), "Usage: redka [options] <data-source>\n")
flag.PrintDefaults()
}
flag.StringVar(&config.Host, "h", "localhost", "server host")
flag.StringVar(&config.Port, "p", "6379", "server port")
flag.StringVar(&config.Sock, "s", "", "server socket (overrides host and port)")
flag.BoolVar(&config.Verbose, "v", false, "verbose logging")
// Register an SQLite driver with custom pragmas.
// Ensures that the PRAGMA settings apply to
// all connections opened by the driver.
sql.Register(driverName, &sqlite3.SQLiteDriver{
sql.Register(sqliteDriverName, &sqlite3.SQLiteDriver{
ConnectHook: func(conn *sqlite3.SQLiteConn) error {
_, err := conn.Exec(pragma, nil)
_, err := conn.Exec(sqlitePragma, nil)
return err
},
})
}
func main() {
// Parse command line arguments.
flag.Parse()
if len(flag.Args()) > 1 {
flag.Usage()
os.Exit(1)
}
config := mustReadConfig()
logger := setupLogger(config)
// Set the data source.
if len(flag.Args()) == 0 {
config.Path = memoryURI
} else {
config.Path = flag.Arg(0)
}
slog.Info("starting redka", "version", version, "commit", commit, "built_at", date)
// Prepare a context to handle shutdown signals.
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
// Set up logging.
logLevel := new(slog.LevelVar)
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel})
logger := slog.New(logHandler)
slog.SetDefault(logger)
if config.Verbose {
logLevel.Set(slog.LevelDebug)
}
// Print version information.
slog.Info("starting redka", "version", version, "commit", commit, "built_at", date)
// Open the database.
opts := redka.Options{
DriverName: driverName,
Logger: logger,
Pragma: map[string]string{},
}
db, err := redka.Open(config.Path, &opts)
if err != nil {
slog.Error("data source", "error", err)
os.Exit(1)
}
slog.Info("data source", "path", config.Path)
db := mustOpenDB(config, logger)
// Create the server.
var srv *server.Server
if config.Sock != "" {
srv = server.New("unix", config.Sock, db)
} else {
srv = server.New("tcp", config.Addr(), db)
}
// Start the server.
var errCh = make(chan error, 1)
go func() {
if err := srv.Start(); err != nil {
errCh <- fmt.Errorf("start server: %w", err)
}
}()
// Start the debug server.
var debugSrv *server.DebugServer
if config.Verbose {
debugSrv = server.NewDebug("localhost", 6060)
go func() {
if err := debugSrv.Start(); err != nil {
errCh <- fmt.Errorf("start debug server: %w", err)
}
}()
}
// Start application and debug servers.
errCh := make(chan error, 1)
srv := startServer(config, db, errCh)
debugSrv := startDebugServer(config, errCh)
// Wait for a shutdown signal or a startup error.
select {
@@ -159,6 +106,120 @@ func main() {
}
}
// mustReadConfig reads the configuration from
// command line arguments and environment variables.
func mustReadConfig() Config {
if len(flag.Args()) > 1 {
flag.Usage()
os.Exit(1)
}
var config Config
flag.StringVar(
&config.Host, "h",
cmp.Or(os.Getenv("REDKA_HOST"), "localhost"),
"server host",
)
flag.StringVar(
&config.Port, "p",
cmp.Or(os.Getenv("REDKA_PORT"), "6379"),
"server port",
)
flag.StringVar(
&config.Sock, "s",
cmp.Or(os.Getenv("REDKA_SOCK"), ""),
"server socket (overrides host and port)",
)
flag.BoolVar(&config.Verbose, "v", false, "verbose logging")
flag.Parse()
config.Path = cmp.Or(flag.Arg(0), os.Getenv("REDKA_DB_URL"), sqliteMemoryURI)
return config
}
// setupLogger setups a logger for the application.
func setupLogger(config Config) *slog.Logger {
logLevel := new(slog.LevelVar)
logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel})
logger := slog.New(logHandler)
slog.SetDefault(logger)
if config.Verbose {
logLevel.Set(slog.LevelDebug)
}
return logger
}
// mustOpenDB connects to the database.
func mustOpenDB(config Config, logger *slog.Logger) *redka.DB {
// Connect to the database using the inferred driver.
driverName := inferDriverName(config.Path)
opts := redka.Options{
DriverName: driverName,
Logger: logger,
// Using nil for pragma sets the default options.
// We don't want any options, so pass an empty map instead.
Pragma: map[string]string{},
}
db, err := redka.Open(config.Path, &opts)
if err != nil {
slog.Error("data source", "error", err)
os.Exit(1)
}
// Hide password when logging.
maskedPath := config.Path
if u, err := url.Parse(maskedPath); err == nil && u.User != nil {
u.User = url.User(u.User.Username())
maskedPath = u.String()
}
slog.Info("data source", "driver", driverName, "path", maskedPath)
return db
}
// inferDriverName infers the driver name from the data source URI.
func inferDriverName(path string) string {
// Infer the driver name based on the data source URI.
if strings.HasPrefix(path, "postgres://") {
return "postgres"
}
return sqliteDriverName
}
// startServer starts the application server.
func startServer(config Config, db *redka.DB, errCh chan<- error) *server.Server {
// Create the server.
var srv *server.Server
if config.Sock != "" {
srv = server.New("unix", config.Sock, db)
} else {
srv = server.New("tcp", config.Addr(), db)
}
// Start the server.
go func() {
if err := srv.Start(); err != nil {
errCh <- fmt.Errorf("start server: %w", err)
}
}()
return srv
}
// startDebugServer starts the debug server.
func startDebugServer(config Config, errCh chan<- error) *server.DebugServer {
if !config.Verbose {
return nil
}
srv := server.NewDebug("localhost", debugPort)
go func() {
if err := srv.Start(); err != nil {
errCh <- fmt.Errorf("start debug server: %w", err)
}
}()
return srv
}
// shutdown stops the main server and the debug server.
func shutdown(srv *server.Server, debugSrv *server.DebugServer) {
// Stop the debug server.

View File

@@ -6,12 +6,18 @@ Install the module as follows:
go get github.com/nalgeon/redka
```
You'll also need an SQLite driver. Use one of the following:
You'll also need an SQLite or PostgreSQL driver.
Use one of the following for SQLite:
- `github.com/mattn/go-sqlite3` (CGO, fastest)
- `github.com/ncruces/go-sqlite3` (pure Go, WASM)
- `github.com/tursodatabase/go-libsql` (CGO)
- `modernc.org/sqlite` (pure Go)
- `modernc.org/sqlite` (pure Go, libc port)
Or one of the following for PostgreSQL:
- `github.com/lib/pq`
- `github.com/jackc/pgx/v5`
Install a driver with `go get` like this:

View File

@@ -7,21 +7,11 @@ I've compared Redka with Redis using [redis-benchmark](https://redis.io/docs/man
- 10000 randomized keys
- GET/SET commands
SQLite settings:
```
pragma journal_mode = wal;
pragma synchronous = normal;
pragma temp_store = memory;
pragma mmap_size = 268435456;
pragma foreign_keys = on;
```
Hardware: Apple M1 8-core CPU, 16GB RAM
## Results
Redis:
```
```text
redis-server --appendonly no
redis-benchmark -p 6379 -q -c 10 -n 1000000 -r 10000 -t get,set
@@ -29,9 +19,9 @@ SET: 133262.25 requests per second, p50=0.055 msec
GET: 139217.59 requests per second, p50=0.055 msec
```
Redka (in-memory):
Redka (SQLite, in-memory):
```
```text
./redka -p 6380
redis-benchmark -p 6380 -q -c 10 -n 1000000 -r 10000 -t get,set
@@ -39,14 +29,50 @@ SET: 36188.62 requests per second, p50=0.167 msec
GET: 104405.93 requests per second, p50=0.063 msec
```
Redka (persisted to disk):
Redka (SQLite, persisted to disk):
```
./redka -p 6380 data.db
```text
./redka -p 6380 redka.db
redis-benchmark -p 6380 -q -c 10 -n 1000000 -r 10000 -t get,set
SET: 26773.76 requests per second, p50=0.215 msec
GET: 103092.78 requests per second, p50=0.063 msec
```
So while Redka is 2-5 times slower than Redis (not surprising, since we are comparing a relational database to a key-value data store), it can still do 26K writes/sec and 94K reads/sec, which is pretty good if you ask me.
Redka (PostgreSQL):
```text
./redka -p 6380 "postgres://redka:redka@localhost:5432/redka?sslmode=disable"
redis-benchmark -p 6380 -q -c 10 -n 100000 -r 10000 -t get,set
SET: 11941.72 requests per second, p50=0.775 msec
GET: 25766.55 requests per second, p50=0.359 msec
```
So while Redka is noticeably slower than Redis (not surprising, since we are comparing a relational database to a key-value data store), it can still handle tens of thousands of operations per second. That should be more than enough for many apps.
## Environment
Hardware: Apple M1 8-core CPU, 16GB RAM
SQLite settings:
```text
pragma journal_mode = wal;
pragma synchronous = normal;
pragma temp_store = memory;
pragma mmap_size = 268435456;
pragma foreign_keys = on;
```
PostgreSQL settings:
```text
checkpoint_completion_target=0.9
effective_cache_size=4GB
maintenance_work_mem=512MB
max_wal_size=1GB
random_page_cost=1.1
shared_buffers=1GB
wal_buffers=16MB
```

View File

@@ -1,6 +1,6 @@
# Persistence
Redka stores data in a SQLite database using the following tables:
Redka stores data in a SQL database using the following tables:
```
rkey

View File

@@ -47,19 +47,19 @@ After opening the database, call `redka.DB` methods to run individual commands:
db.Str().Set("name", "alice")
db.Str().Set("age", 25)
count, err := db.Key().Count("name", "age", "city")
slog.Info("count", "count", count, "err", err)
name, err := db.Str().Get("name")
slog.Info("get", "name", name, "err", err)
age, err := db.Str().Get("age")
slog.Info("get", "age", age, "err", err)
```
```
count count=2 err=<nil>
```text
get name="alice" err=<nil>
get age="25" err=<nil>
```
See the full example in [example/simple/main.go](../example/simple/main.go).
See the full example in [example/mattn/main.go](../example/mattn/main.go).
## Transactions
@@ -84,7 +84,7 @@ err := db.Update(func(tx *redka.Tx) error {
slog.Info("updated", "count", updCount, "err", err)
```
```
```text
updated count=2 err=<nil>
```
@@ -94,7 +94,11 @@ See the full example in [example/tx/main.go](../example/tx/main.go).
Redka supports the following SQLite drivers:
- `github.com/mattn/go-sqlite3` ([example](../example/simple/main.go))
- `github.com/mattn/go-sqlite3` ([example](../example/mattn/main.go))
- `github.com/ncruces/go-sqlite3` ([example](../example/ncruces/main.go))
- `github.com/tursodatabase/go-libsql` ([example](../example/libsql/main.go))
- `modernc.org/sqlite` ([example](../example/modernc/main.go))
And the following Postgres drivers:
- `github.com/lib/pq` ([example](../example/postgres/main.go))
- `github.com/jackc/pgx/v5`

View File

@@ -9,10 +9,20 @@ redka [-h host] [-p port] [-s unix-socket] [db-path]
For example:
```shell
# use in-memory sqlite database
./redka
# use file sqlite database
./redka data.db
# listen on all network interfaces
./redka -h 0.0.0.0 -p 6379 data.db
# listen on unix socket
./redka -s /tmp/redka.sock data.db
# use postgres database
./redka -p 6379 "postgres://redka:redka@localhost:5432/redka?sslmode=disable"
```
Server defaults are host `localhost`, port `6379` and empty DB path. The unix socket path, if given, overrides the host/port arguments.
@@ -42,7 +52,7 @@ Once the server is running, connect to it using `redis-cli` or an API client lik
redis-cli -h localhost -p 6379
```
```
```text
127.0.0.1:6379> echo hello
"hello"
127.0.0.1:6379> set name alice

View File

@@ -2,29 +2,29 @@ module github.com/nalgeon/redka/example
replace github.com/nalgeon/redka => ../
go 1.22
go 1.23.0
toolchain go1.24.0
require (
github.com/mattn/go-sqlite3 v1.14.22
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.28
github.com/nalgeon/redka v0.0.0-00010101000000-000000000000
github.com/ncruces/go-sqlite3 v0.16.2
github.com/tursodatabase/go-libsql v0.0.0-20240429120401-651096bbee0b
modernc.org/sqlite v1.29.5
)
require (
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/libsql/sqlite-antlr4-parser v0.0.0-20240327125255-dbf53b6cbf06 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/ncruces/julianday v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/tetratelabs/wazero v1.7.3 // indirect
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/tools v0.19.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.41.0 // indirect
modernc.org/mathutil v1.6.0 // indirect

View File

@@ -1,47 +1,33 @@
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/libsql/sqlite-antlr4-parser v0.0.0-20240327125255-dbf53b6cbf06 h1:JLvn7D+wXjH9g4Jsjo+VqmzTUpl/LX7vfr6VOfSWTdM=
github.com/libsql/sqlite-antlr4-parser v0.0.0-20240327125255-dbf53b6cbf06/go.mod h1:FUkZ5OHjlGPjnM2UyGJz9TypXQFgYqw6AFNO1UiROTM=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/ncruces/go-sqlite3 v0.16.2-0.20240609232415-e7f8311e2e0d h1:pq4oCRorhPT5EFOyw7OFkGXtJHJ/ViMDjBSmJlPV61g=
github.com/ncruces/go-sqlite3 v0.16.2-0.20240609232415-e7f8311e2e0d/go.mod h1:feFXbBcbLtxNk6XWG1ROt8MS9+E45yCW3G8o4ixIqZ8=
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/nalgeon/be v0.2.0 h1:i1Rsh0F+aNnHdbgph5Cy8Xm5uMVeWrUpm1olgzlPsMo=
github.com/nalgeon/be v0.2.0/go.mod h1:PMwMuBLopwKJkSHnr2qHyLcZYUTqNejN7A8RAqNWO3E=
github.com/ncruces/go-sqlite3 v0.16.2 h1:HesVRr0BC6QSGSEQfEXOntFWS9wd4Z8ms4nJzfUv4Rg=
github.com/ncruces/go-sqlite3 v0.16.2/go.mod h1:wkUIvOrAjFQnefVlivJfcowKUcfMHs4mvLfhVanzHHI=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/tetratelabs/wazero v1.7.2 h1:1+z5nXJNwMLPAWaTePFi49SSTL0IMx/i3Fg8Yc25GDc=
github.com/tetratelabs/wazero v1.7.2/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
github.com/tetratelabs/wazero v1.7.3 h1:PBH5KVahrt3S2AHgEjKu4u+LlDbbk+nsGE3KLucy6Rw=
github.com/tetratelabs/wazero v1.7.3/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y=
github.com/tursodatabase/go-libsql v0.0.0-20240429120401-651096bbee0b h1:R7hev4b96zgXjKbS2ZNbHBnDvyFZhH+LlMqtKH6hIkU=
github.com/tursodatabase/go-libsql v0.0.0-20240429120401-651096bbee0b/go.mod h1:TjsB2miB8RW2Sse8sdxzVTdeGlx74GloD5zJYUC38d8=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@@ -49,8 +35,6 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=

View File

@@ -1,37 +0,0 @@
// An example of using Redka
// with github.com/tursodatabase/go-libsql driver.
package main
import (
"log"
"log/slog"
"github.com/nalgeon/redka"
_ "github.com/tursodatabase/go-libsql"
)
func main() {
// libSQL uses a different driver name ("libsql" instead of "sqlite3").
// It also does not support the journal_mode and mmap_size pragmas
// (see https://github.com/tursodatabase/go-libsql/issues/28),
// so we have to turn them off.
opts := redka.Options{
DriverName: "libsql",
Pragma: map[string]string{
"synchronous": "normal",
"temp_store": "memory",
"foreign_keys": "on",
},
}
db, err := redka.Open("data.db", &opts)
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = db.Str().Set("name", "alice")
slog.Info("set", "err", err)
count, err := db.Key().Count("name", "age", "city")
slog.Info("count", "count", count, "err", err)
}

View File

@@ -11,24 +11,22 @@ import (
)
func main() {
// Open a database.
db, err := redka.Open("data.db", nil)
// Open the database.
db, err := redka.Open("redka.db", nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
defer func() { _ = db.Close() }()
// Set some string keys.
// Set some values.
err = db.Str().Set("name", "alice")
slog.Info("set", "err", err)
err = db.Str().Set("age", 25)
slog.Info("set", "err", err)
// Check if the keys exist.
count, err := db.Key().Count("name", "age", "city")
slog.Info("count", "count", count, "err", err)
// Get a key.
// Read them back.
name, err := db.Str().Get("name")
slog.Info("get", "name", name, "err", err)
age, err := db.Str().Get("age")
slog.Info("get", "age", age, "err", err)
}

View File

@@ -16,15 +16,23 @@ func main() {
opts := redka.Options{
DriverName: "sqlite",
}
db, err := redka.Open("data.db", &opts)
// Open the database.
db, err := redka.Open("redka.db", &opts)
if err != nil {
log.Fatal(err)
}
defer db.Close()
defer func() { _ = db.Close() }()
// Set some values.
err = db.Str().Set("name", "alice")
slog.Info("set", "err", err)
err = db.Str().Set("age", 25)
slog.Info("set", "err", err)
count, err := db.Key().Count("name", "age", "city")
slog.Info("count", "count", count, "err", err)
// Read them back.
name, err := db.Str().Get("name")
slog.Info("get", "name", name, "err", err)
age, err := db.Str().Get("age")
slog.Info("get", "age", age, "err", err)
}

View File

@@ -12,15 +12,22 @@ import (
)
func main() {
db, err := redka.Open("data.db", nil)
// Open the database.
db, err := redka.Open("redka.db", nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
defer func() { _ = db.Close() }()
// Set some values.
err = db.Str().Set("name", "alice")
slog.Info("set", "err", err)
err = db.Str().Set("age", 25)
slog.Info("set", "err", err)
count, err := db.Key().Count("name", "age", "city")
slog.Info("count", "count", count, "err", err)
// Read them back.
name, err := db.Str().Get("name")
slog.Info("get", "name", name, "err", err)
age, err := db.Str().Get("age")
slog.Info("get", "age", age, "err", err)
}

36
example/postgres/main.go Normal file
View File

@@ -0,0 +1,36 @@
// An example of using Redka
// with github.com/lib/pq driver.
package main
import (
"log"
"log/slog"
_ "github.com/lib/pq"
"github.com/nalgeon/redka"
)
func main() {
// Connections settings.
connString := "postgres://redka:redka@localhost:5432/redka?sslmode=disable"
opts := &redka.Options{DriverName: "postgres"}
// Open the database.
db, err := redka.Open(connString, opts)
if err != nil {
log.Fatal(err)
}
defer func() { _ = db.Close() }()
// Set some values.
err = db.Str().Set("name", "alice")
slog.Info("set", "err", err)
err = db.Str().Set("age", 25)
slog.Info("set", "err", err)
// Read them back.
name, err := db.Str().Get("name")
slog.Info("get", "name", name, "err", err)
age, err := db.Str().Get("age")
slog.Info("get", "age", age, "err", err)
}

View File

@@ -10,11 +10,12 @@ import (
)
func main() {
db, err := redka.Open("data.db", nil)
// Open the database.
db, err := redka.Open("redka.db", nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
defer func() { _ = db.Close() }()
{
// Writable transaction.

13
go.mod
View File

@@ -1,10 +1,17 @@
module github.com/nalgeon/redka
go 1.22
go 1.23.0
toolchain go1.24.0
// Main dependencies.
require github.com/tidwall/redcon v1.6.2
// Test dependencies.
require (
github.com/mattn/go-sqlite3 v1.14.22
github.com/tidwall/redcon v1.6.2
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.28
github.com/nalgeon/be v0.2.0
)
require (

8
go.sum
View File

@@ -1,5 +1,9 @@
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/nalgeon/be v0.2.0 h1:i1Rsh0F+aNnHdbgph5Cy8Xm5uMVeWrUpm1olgzlPsMo=
github.com/nalgeon/be v0.2.0/go.mod h1:PMwMuBLopwKJkSHnr2qHyLcZYUTqNejN7A8RAqNWO3E=
github.com/tidwall/btree v1.1.0/go.mod h1:TzIRzen6yHbibdSfK6t8QimqbUnoxUSrZfeW7Uob0q4=
github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI=
github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=

View File

@@ -3,15 +3,12 @@ package conn
import (
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}

View File

@@ -3,8 +3,8 @@ package conn
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestEchoParse(t *testing.T) {
@@ -34,19 +34,18 @@ func TestEchoParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseEcho, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.parts, test.want)
be.Equal(t, cmd.parts, test.want)
} else {
testx.AssertEqual(t, cmd, Echo{})
be.Equal(t, cmd, Echo{})
}
})
}
}
func TestEchoExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
tests := []struct {
cmd string
@@ -70,9 +69,9 @@ func TestEchoExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseEcho, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,8 +3,8 @@ package conn
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestPingParse(t *testing.T) {
@@ -33,19 +33,18 @@ func TestPingParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParsePing, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.message, test.want)
be.Equal(t, cmd.message, test.want)
} else {
testx.AssertEqual(t, cmd, Ping{})
be.Equal(t, cmd, Ping{})
}
})
}
}
func TestPingExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
tests := []struct {
cmd string
@@ -69,9 +68,9 @@ func TestPingExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParsePing, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,8 +3,8 @@ package conn
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSelectParse(t *testing.T) {
@@ -33,19 +33,18 @@ func TestSelectParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSelect, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.index, test.want.index)
be.Equal(t, cmd.index, test.want.index)
} else {
testx.AssertEqual(t, cmd, Select{})
be.Equal(t, cmd, Select{})
}
})
}
}
func TestSelectExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
tests := []struct {
cmd string
@@ -64,9 +63,9 @@ func TestSelectExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseSelect, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,15 +3,12 @@ package hash
import (
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHDelParse(t *testing.T) {
@@ -44,12 +44,12 @@ func TestHDelParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHDel, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.fields, test.fields)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.fields, test.fields)
} else {
testx.AssertEqual(t, cmd, HDel{})
be.Equal(t, cmd, HDel{})
}
})
}
@@ -57,66 +57,63 @@ func TestHDelParse(t *testing.T) {
func TestHDelExec(t *testing.T) {
t.Run("one", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHDel, "hdel person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
_, err = db.Hash().Get("person", "name")
testx.AssertErr(t, err, core.ErrNotFound)
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "25")
_, err = red.Hash().Get("person", "name")
be.Err(t, err, core.ErrNotFound)
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "25")
})
t.Run("some", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
_, _ = db.Hash().Set("person", "happy", true)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
_, _ = red.Hash().Set("person", "happy", true)
cmd := redis.MustParse(ParseHDel, "hdel person name happy city")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
_, err = db.Hash().Get("person", "name")
testx.AssertErr(t, err, core.ErrNotFound)
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "25")
_, err = db.Hash().Get("person", "happy")
testx.AssertErr(t, err, core.ErrNotFound)
_, err = red.Hash().Get("person", "name")
be.Err(t, err, core.ErrNotFound)
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "25")
_, err = red.Hash().Get("person", "happy")
be.Err(t, err, core.ErrNotFound)
})
t.Run("all", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHDel, "hdel person name age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
_, err = db.Hash().Get("person", "name")
testx.AssertErr(t, err, core.ErrNotFound)
_, err = db.Hash().Get("person", "age")
testx.AssertErr(t, err, core.ErrNotFound)
_, err = red.Hash().Get("person", "name")
be.Err(t, err, core.ErrNotFound)
_, err = red.Hash().Get("person", "age")
be.Err(t, err, core.ErrNotFound)
})
}

View File

@@ -3,8 +3,8 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHExistsParse(t *testing.T) {
@@ -43,12 +43,12 @@ func TestHExistsParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHExists, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.field, test.field)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.field, test.field)
} else {
testx.AssertEqual(t, cmd, HExists{})
be.Equal(t, cmd, HExists{})
}
})
}
@@ -56,43 +56,40 @@ func TestHExistsParse(t *testing.T) {
func TestHExistsExec(t *testing.T) {
t.Run("field found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHExists, "hexists person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
})
t.Run("field not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHExists, "hexists person age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHExists, "hexists person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHGetParse(t *testing.T) {
@@ -44,12 +44,12 @@ func TestHGetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHGet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.field, test.field)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.field, test.field)
} else {
testx.AssertEqual(t, cmd, HGet{})
be.Equal(t, cmd, HGet{})
}
})
}
@@ -57,43 +57,38 @@ func TestHGetParse(t *testing.T) {
func TestHGetExec(t *testing.T) {
t.Run("field found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHGet, "hget person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("alice"))
testx.AssertEqual(t, conn.Out(), "alice")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("alice"))
be.Equal(t, conn.Out(), "alice")
})
t.Run("field not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHGet, "hget person age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHGet, "hget person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHGetAllParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestHGetAllParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHGetAll, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, HGetAll{})
be.Equal(t, cmd, HGetAll{})
}
})
}
@@ -46,34 +46,31 @@ func TestHGetAllParse(t *testing.T) {
func TestHGetAllExec(t *testing.T) {
t.Run("key found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHGetAll, "hgetall person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, map[string]core.Value{
be.Err(t, err, nil)
be.Equal(t, res.(map[string]core.Value), map[string]core.Value{
"name": core.Value("alice"), "age": core.Value("25"),
})
testx.AssertEqual(t,
be.Equal(t,
conn.Out() == "4,name,alice,age,25" || conn.Out() == "4,age,25,name,alice",
true)
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHGetAll, "hgetall person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, map[string]core.Value{})
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.(map[string]core.Value), map[string]core.Value{})
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHIncrByParse(t *testing.T) {
@@ -46,13 +46,13 @@ func TestHIncrByParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHIncrBy, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.field, test.field)
testx.AssertEqual(t, cmd.delta, test.delta)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.field, test.field)
be.Equal(t, cmd.delta, test.delta)
} else {
testx.AssertEqual(t, cmd, HIncrBy{})
be.Equal(t, cmd, HIncrBy{})
}
})
}
@@ -60,69 +60,62 @@ func TestHIncrByParse(t *testing.T) {
func TestHIncrByExec(t *testing.T) {
t.Run("incr field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 35)
testx.AssertEqual(t, conn.Out(), "35")
be.Err(t, err, nil)
be.Equal(t, res, 35)
be.Equal(t, conn.Out(), "35")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("35"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("35"))
})
t.Run("decr field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age -10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 15)
testx.AssertEqual(t, conn.Out(), "15")
be.Err(t, err, nil)
be.Equal(t, res, 15)
be.Equal(t, conn.Out(), "15")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("15"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("15"))
})
t.Run("create field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 10)
testx.AssertEqual(t, conn.Out(), "10")
be.Err(t, err, nil)
be.Equal(t, res, 10)
be.Equal(t, conn.Out(), "10")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("10"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("10"))
})
t.Run("create key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHIncrBy, "hincrby person age 10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 10)
testx.AssertEqual(t, conn.Out(), "10")
be.Err(t, err, nil)
be.Equal(t, res, 10)
be.Equal(t, conn.Out(), "10")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("10"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("10"))
})
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHIncrByFloatParse(t *testing.T) {
@@ -46,13 +46,13 @@ func TestHIncrByFloatParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHIncrByFloat, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.field, test.field)
testx.AssertEqual(t, cmd.delta, test.delta)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.field, test.field)
be.Equal(t, cmd.delta, test.delta)
} else {
testx.AssertEqual(t, cmd, HIncrByFloat{})
be.Equal(t, cmd, HIncrByFloat{})
}
})
}
@@ -60,69 +60,62 @@ func TestHIncrByFloatParse(t *testing.T) {
func TestHIncrByFloatExec(t *testing.T) {
t.Run("incr field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 35.5)
testx.AssertEqual(t, conn.Out(), "35.5")
be.Err(t, err, nil)
be.Equal(t, res, 35.5)
be.Equal(t, conn.Out(), "35.5")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("35.5"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("35.5"))
})
t.Run("decr field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age -10.5")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 14.5)
testx.AssertEqual(t, conn.Out(), "14.5")
be.Err(t, err, nil)
be.Equal(t, res, 14.5)
be.Equal(t, conn.Out(), "14.5")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("14.5"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("14.5"))
})
t.Run("create field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 10.5)
testx.AssertEqual(t, conn.Out(), "10.5")
be.Err(t, err, nil)
be.Equal(t, res, 10.5)
be.Equal(t, conn.Out(), "10.5")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("10.5"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("10.5"))
})
t.Run("create key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHIncrByFloat, "hincrbyfloat person age 10.5")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 10.5)
testx.AssertEqual(t, conn.Out(), "10.5")
be.Err(t, err, nil)
be.Equal(t, res, 10.5)
be.Equal(t, conn.Out(), "10.5")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age, core.Value("10.5"))
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age, core.Value("10.5"))
})
}

View File

@@ -1,10 +1,11 @@
package hash
import (
"slices"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHKeysParse(t *testing.T) {
@@ -33,11 +34,11 @@ func TestHKeysParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHKeys, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, HKeys{})
be.Equal(t, cmd, HKeys{})
}
})
}
@@ -45,32 +46,30 @@ func TestHKeysParse(t *testing.T) {
func TestHKeysExec(t *testing.T) {
t.Run("key found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHKeys, "hkeys person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []string{"age", "name"})
testx.AssertEqual(t,
conn.Out() == "2,age,name" || conn.Out() == "2,name,age",
true)
be.Err(t, err, nil)
got := res.([]string)
slices.Sort(got)
be.Equal(t, got, []string{"age", "name"})
be.True(t, conn.Out() == "2,age,name" || conn.Out() == "2,name,age")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHKeys, "hkeys person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []string{})
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]string), []string{})
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,8 +3,8 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHLenParse(t *testing.T) {
@@ -33,11 +33,11 @@ func TestHLenParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHLen, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, HLen{})
be.Equal(t, cmd, HLen{})
}
})
}
@@ -45,30 +45,27 @@ func TestHLenParse(t *testing.T) {
func TestHLenExec(t *testing.T) {
t.Run("key found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHLen, "hlen person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHLen, "hlen person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHMGetParse(t *testing.T) {
@@ -44,12 +44,12 @@ func TestHMGetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHMGet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.fields, test.fields)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.fields, test.fields)
} else {
testx.AssertEqual(t, cmd, HMGet{})
be.Equal(t, cmd, HMGet{})
}
})
}
@@ -57,58 +57,52 @@ func TestHMGetParse(t *testing.T) {
func TestHMGetExec(t *testing.T) {
t.Run("one field", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHMGet, "hmget person name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, conn.Out(), "1,alice")
be.Err(t, err, nil)
be.Equal(t, conn.Out(), "1,alice")
items := res.([]core.Value)
testx.AssertEqual(t, len(items), 1)
testx.AssertEqual(t, items[0], core.Value("alice"))
be.Equal(t, len(items), 1)
be.Equal(t, items[0], core.Value("alice"))
})
t.Run("some fields", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
_, _ = db.Hash().Set("person", "happy", true)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
_, _ = red.Hash().Set("person", "happy", true)
cmd := redis.MustParse(ParseHMGet, "hmget person name happy city")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, conn.Out(), "3,alice,1,(nil)")
be.Err(t, err, nil)
be.Equal(t, conn.Out(), "3,alice,1,(nil)")
items := res.([]core.Value)
testx.AssertEqual(t, len(items), 3)
testx.AssertEqual(t, items[0], core.Value("alice"))
testx.AssertEqual(t, items[1], core.Value("1"))
testx.AssertEqual(t, items[2], core.Value(nil))
be.Equal(t, len(items), 3)
be.Equal(t, items[0], core.Value("alice"))
be.Equal(t, items[1], core.Value("1"))
be.Equal(t, items[2], core.Value(nil))
})
t.Run("all fields", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHMGet, "hmget person name age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, conn.Out(), "2,alice,25")
be.Err(t, err, nil)
be.Equal(t, conn.Out(), "2,alice,25")
items := res.([]core.Value)
testx.AssertEqual(t, len(items), 2)
testx.AssertEqual(t, items[0], core.Value("alice"))
testx.AssertEqual(t, items[1], core.Value("25"))
be.Equal(t, len(items), 2)
be.Equal(t, items[0], core.Value("alice"))
be.Equal(t, items[1], core.Value("25"))
})
}

View File

@@ -3,8 +3,8 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHMSetParse(t *testing.T) {
@@ -51,12 +51,12 @@ func TestHMSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHMSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.items, test.want.items)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.items, test.want.items)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -64,73 +64,67 @@ func TestHMSetParse(t *testing.T) {
func TestHMSetExec(t *testing.T) {
t.Run("create single", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHMSet, "hmset person name alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
})
t.Run("create multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHMSet, "hmset person name alice age 25")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "25")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "25")
})
t.Run("create/update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHMSet, "hmset person name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "bob")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "50")
})
t.Run("update multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHMSet, "hmset person name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "bob")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "50")
})
}

View File

@@ -1,12 +1,13 @@
package hash
import (
"fmt"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/rhash"
"github.com/nalgeon/redka/internal/testx"
)
func TestHScanParse(t *testing.T) {
@@ -103,57 +104,62 @@ func TestHScanParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHScan, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.cursor, test.cursor)
testx.AssertEqual(t, cmd.match, test.match)
testx.AssertEqual(t, cmd.count, test.count)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.cursor, test.cursor)
be.Equal(t, cmd.match, test.match)
be.Equal(t, cmd.count, test.count)
} else {
testx.AssertEqual(t, cmd, HScan{})
be.Equal(t, cmd, HScan{})
}
})
}
}
func TestHScanExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_, _ = db.Hash().Set("key", "f11", "11")
_, _ = db.Hash().Set("key", "f12", "12")
_, _ = db.Hash().Set("key", "f21", "21")
_, _ = db.Hash().Set("key", "f22", "22")
_, _ = db.Hash().Set("key", "f31", "31")
_, _ = red.Hash().Set("key", "f11", "11")
_, _ = red.Hash().Set("key", "f12", "12")
_, _ = red.Hash().Set("key", "f21", "21")
_, _ = red.Hash().Set("key", "f22", "22")
_, _ = red.Hash().Set("key", "f31", "31")
t.Run("hscan all", func(t *testing.T) {
var cursor int
{
// page 1
cmd := redis.MustParse(ParseHScan, "hscan key 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Items), 5)
testx.AssertEqual(t, sres.Items[0].Field, "f11")
testx.AssertEqual(t, sres.Items[0].Value, core.Value("11"))
testx.AssertEqual(t, sres.Items[4].Field, "f31")
testx.AssertEqual(t, sres.Items[4].Value, core.Value("31"))
testx.AssertEqual(t, conn.Out(), "2,5,10,f11,11,f12,12,f21,21,f22,22,f31,31")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Items), 5)
be.Equal(t, sres.Items[0].Field, "f11")
be.Equal(t, sres.Items[0].Value, core.Value("11"))
be.Equal(t, sres.Items[4].Field, "f31")
be.Equal(t, sres.Items[4].Value, core.Value("31"))
wantOut := fmt.Sprintf("2,%d,10,f11,11,f12,12,f21,21,f22,22,f31,31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
cmd := redis.MustParse(ParseHScan, "hscan key 5")
// page 2 (empty)
next := fmt.Sprintf("hscan key %d", cursor)
cmd := redis.MustParse(ParseHScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Items), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Items), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
@@ -162,80 +168,91 @@ func TestHScanExec(t *testing.T) {
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].Field, "f21")
testx.AssertEqual(t, sres.Items[0].Value, core.Value("21"))
testx.AssertEqual(t, sres.Items[1].Field, "f22")
testx.AssertEqual(t, sres.Items[1].Value, core.Value("22"))
testx.AssertEqual(t, conn.Out(), "2,4,4,f21,21,f22,22")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].Field, "f21")
be.Equal(t, sres.Items[0].Value, core.Value("21"))
be.Equal(t, sres.Items[1].Field, "f22")
be.Equal(t, sres.Items[1].Value, core.Value("22"))
wantOut := fmt.Sprintf("2,%d,4,f21,21,f22,22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
})
t.Run("hscan count", func(t *testing.T) {
var cursor int
{
// page 1
cmd := redis.MustParse(ParseHScan, "hscan key 0 match * count 2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 2)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].Field, "f11")
testx.AssertEqual(t, sres.Items[0].Value, core.Value("11"))
testx.AssertEqual(t, sres.Items[1].Field, "f12")
testx.AssertEqual(t, sres.Items[1].Value, core.Value("12"))
testx.AssertEqual(t, conn.Out(), "2,2,4,f11,11,f12,12")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].Field, "f11")
be.Equal(t, sres.Items[0].Value, core.Value("11"))
be.Equal(t, sres.Items[1].Field, "f12")
be.Equal(t, sres.Items[1].Value, core.Value("12"))
wantOut := fmt.Sprintf("2,%d,4,f11,11,f12,12", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 2
cmd := redis.MustParse(ParseHScan, "hscan key 2 match * count 2")
next := fmt.Sprintf("hscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseHScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].Field, "f21")
testx.AssertEqual(t, sres.Items[0].Value, core.Value("21"))
testx.AssertEqual(t, sres.Items[1].Field, "f22")
testx.AssertEqual(t, sres.Items[1].Value, core.Value("22"))
testx.AssertEqual(t, conn.Out(), "2,4,4,f21,21,f22,22")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].Field, "f21")
be.Equal(t, sres.Items[0].Value, core.Value("21"))
be.Equal(t, sres.Items[1].Field, "f22")
be.Equal(t, sres.Items[1].Value, core.Value("22"))
wantOut := fmt.Sprintf("2,%d,4,f21,21,f22,22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 3
cmd := redis.MustParse(ParseHScan, "hscan key 4 match * count 2")
next := fmt.Sprintf("hscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseHScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Items), 1)
testx.AssertEqual(t, sres.Items[0].Field, "f31")
testx.AssertEqual(t, sres.Items[0].Value, core.Value("31"))
testx.AssertEqual(t, conn.Out(), "2,5,2,f31,31")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Items), 1)
be.Equal(t, sres.Items[0].Field, "f31")
be.Equal(t, sres.Items[0].Value, core.Value("31"))
wantOut := fmt.Sprintf("2,%d,2,f31,31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// no more pages
cmd := redis.MustParse(ParseHScan, "hscan key 5 match * count 2")
next := fmt.Sprintf("hscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseHScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rhash.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Items), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Items), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
}

View File

@@ -3,8 +3,8 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHSetParse(t *testing.T) {
@@ -51,12 +51,12 @@ func TestHSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.items, test.want.items)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.items, test.want.items)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -64,73 +64,67 @@ func TestHSetParse(t *testing.T) {
func TestHSetExec(t *testing.T) {
t.Run("create single", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHSet, "hset person name alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
})
t.Run("create multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHSet, "hset person name alice age 25")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "25")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "25")
})
t.Run("create/update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHSet, "hset person name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "bob")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "50")
})
t.Run("update multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHSet, "hset person name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Hash().Get("person", "age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "bob")
age, _ := red.Hash().Get("person", "age")
be.Equal(t, age.String(), "50")
})
}

View File

@@ -3,8 +3,8 @@ package hash
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHSetNXParse(t *testing.T) {
@@ -43,12 +43,12 @@ func TestHSetNXParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHSetNX, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.value, test.want.value)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.value, test.want.value)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -56,34 +56,31 @@ func TestHSetNXParse(t *testing.T) {
func TestHSetNXExec(t *testing.T) {
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHSetNX, "hsetnx person name alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
})
t.Run("update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
cmd := redis.MustParse(ParseHSetNX, "hsetnx person name bob")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
name, _ := db.Hash().Get("person", "name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Hash().Get("person", "name")
be.Equal(t, name.String(), "alice")
})
}

View File

@@ -1,11 +1,12 @@
package hash
import (
"slices"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestHValsParse(t *testing.T) {
@@ -34,11 +35,11 @@ func TestHValsParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseHVals, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, HVals{})
be.Equal(t, cmd, HVals{})
}
})
}
@@ -46,30 +47,32 @@ func TestHValsParse(t *testing.T) {
func TestHValsExec(t *testing.T) {
t.Run("key found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Hash().Set("person", "name", "alice")
_, _ = db.Hash().Set("person", "age", 25)
red := getRedka(t)
_, _ = red.Hash().Set("person", "name", "alice")
_, _ = red.Hash().Set("person", "age", 25)
cmd := redis.MustParse(ParseHVals, "hvals person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{core.Value("25"), core.Value("alice")})
testx.AssertEqual(t, conn.Out(), "2,25,alice")
be.Err(t, err, nil)
var got []string
for _, val := range res.([]core.Value) {
got = append(got, val.String())
}
slices.Sort(got)
be.Equal(t, got, []string{"25", "alice"})
be.True(t, conn.Out() == "2,25,alice" || conn.Out() == "2,alice,25")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseHVals, "hvals person")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{})
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value{})
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestDelParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestDelParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseDel, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want)
be.Equal(t, cmd.keys, test.want)
} else {
testx.AssertEqual(t, cmd, Del{})
be.Equal(t, cmd, Del{})
}
})
}
@@ -69,24 +69,23 @@ func TestDelExec(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 50)
_ = db.Str().Set("city", "paris")
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 50)
_ = red.Str().Set("city", "paris")
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseDel, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
_, err = db.Str().Get("name")
testx.AssertErr(t, err, core.ErrNotFound)
city, _ := db.Str().Get("city")
testx.AssertEqual(t, city.String(), "paris")
_, err = red.Str().Get("name")
be.Err(t, err, core.ErrNotFound)
city, _ := red.Str().Get("city")
be.Equal(t, city.String(), "paris")
})
}
}

View File

@@ -3,8 +3,8 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestExistsParse(t *testing.T) {
@@ -33,23 +33,22 @@ func TestExistsParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseExists, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want)
be.Equal(t, cmd.keys, test.want)
} else {
testx.AssertEqual(t, cmd, Exists{})
be.Equal(t, cmd, Exists{})
}
})
}
}
func TestExistsExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 50)
_ = db.Str().Set("city", "paris")
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 50)
_ = red.Str().Set("city", "paris")
tests := []struct {
cmd string
@@ -78,9 +77,9 @@ func TestExistsExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseExists, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestExpireParse(t *testing.T) {
@@ -54,12 +54,12 @@ func TestExpireParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.ttl, test.ttl)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.ttl, test.ttl)
} else {
testx.AssertEqual(t, cmd, Expire{})
be.Equal(t, cmd, Expire{})
}
})
}
@@ -70,89 +70,79 @@ func TestExpireExec(t *testing.T) {
return ParseExpire(b, 1000)
}
t.Run("create expire", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expire name 60")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
expireAt := time.Now().Add(60 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
})
t.Run("update expire", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
red := getRedka(t)
_ = red.Str().SetExpires("name", "alice", 60*time.Second)
cmd := redis.MustParse(parse, "expire name 30")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
expireAt := time.Now().Add(30 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
})
t.Run("set to zero", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expire name 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("negative", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expire name -10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expire age 60")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("age")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("age")
be.Equal(t, key.Exists(), false)
})
}

View File

@@ -5,8 +5,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestExpireAtParse(t *testing.T) {
@@ -55,12 +55,12 @@ func TestExpireAtParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.at.Unix(), test.at.Unix())
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.at.Unix(), test.at.Unix())
} else {
testx.AssertEqual(t, cmd, ExpireAt{})
be.Equal(t, cmd, ExpireAt{})
}
})
}
@@ -71,96 +71,86 @@ func TestExpireAtExec(t *testing.T) {
return ParseExpireAt(b, 1000)
}
t.Run("create expireat", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
expireAt := time.Now().Add(60 * time.Second)
cmd := redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Unix()))
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
})
t.Run("update expire", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
expireAt := time.Now()
cmd := redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Add(60*time.Second).Unix()))
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
cmd = redis.MustParse(parse, fmt.Sprintf("expireat name %d", expireAt.Add(20*time.Second).Unix()))
conn = redis.NewFakeConn()
res, err = cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.Add(20*time.Second).UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.Add(20*time.Second).UnixMilli()/1000)
})
t.Run("set to zero", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expireat name 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("negative", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expireat name -10")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "expireat age 1700000000")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("age")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("age")
be.Equal(t, key.Exists(), false)
})
}

View File

@@ -3,8 +3,8 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestFlushDBParse(t *testing.T) {
@@ -29,9 +29,9 @@ func TestFlushDBParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseFlushDB, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err != nil {
testx.AssertEqual(t, cmd, FlushDB{})
be.Equal(t, cmd, FlushDB{})
}
})
}
@@ -39,35 +39,32 @@ func TestFlushDBParse(t *testing.T) {
func TestFlushDBExec(t *testing.T) {
t.Run("full", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 25)
red := getRedka(t)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 25)
cmd := redis.MustParse(ParseFlushDB, "flushdb")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
keys, _ := db.Key().Keys("*")
testx.AssertEqual(t, len(keys), 0)
keys, _ := red.Key().Keys("*")
be.Equal(t, len(keys), 0)
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseFlushDB, "flushdb")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
keys, _ := db.Key().Keys("*")
testx.AssertEqual(t, len(keys), 0)
keys, _ := red.Key().Keys("*")
be.Equal(t, len(keys), 0)
})
}

View File

@@ -3,15 +3,12 @@ package key
import (
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}

View File

@@ -3,9 +3,9 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestKeysParse(t *testing.T) {
@@ -39,25 +39,24 @@ func TestKeysParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseKeys, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.pattern, test.want)
be.Equal(t, cmd.pattern, test.want)
} else {
testx.AssertEqual(t, cmd, Keys{})
be.Equal(t, cmd, Keys{})
}
})
}
}
func TestKeysExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("k11", "11")
_ = db.Str().Set("k12", "12")
_ = db.Str().Set("k21", "21")
_ = db.Str().Set("k22", "22")
_ = db.Str().Set("k31", "31")
_ = red.Str().Set("k11", "11")
_ = red.Str().Set("k12", "12")
_ = red.Str().Set("k21", "21")
_ = red.Str().Set("k22", "22")
_ = red.Str().Set("k31", "31")
tests := []struct {
cmd string
@@ -91,11 +90,11 @@ func TestKeysExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseKeys, test.cmd)
keys, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
for i, key := range keys.([]core.Key) {
testx.AssertEqual(t, key.Key, test.res[i])
be.Equal(t, key.Key, test.res[i])
}
testx.AssertEqual(t, conn.Out(), test.out)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestPersistParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestPersistParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParsePersist, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, Persist{})
be.Equal(t, cmd, Persist{})
}
})
}
@@ -46,53 +46,47 @@ func TestPersistParse(t *testing.T) {
func TestPersistExec(t *testing.T) {
t.Run("persist to persist", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParsePersist, "persist name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.ETime, (*int64)(nil))
key, _ := red.Key().Get("name")
be.Equal(t, key.ETime, (*int64)(nil))
})
t.Run("volatile to persist", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
red := getRedka(t)
_ = red.Str().SetExpires("name", "alice", 60*time.Second)
cmd := redis.MustParse(ParsePersist, "persist name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.ETime, (*int64)(nil))
key, _ := red.Key().Get("name")
be.Equal(t, key.ETime, (*int64)(nil))
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParsePersist, "persist age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("age")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("age")
be.Equal(t, key.Exists(), false)
})
}

View File

@@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestPExpireParse(t *testing.T) {
@@ -54,12 +54,12 @@ func TestPExpireParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.ttl, test.ttl)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.ttl, test.ttl)
} else {
testx.AssertEqual(t, cmd, Expire{})
be.Equal(t, cmd, Expire{})
}
})
}
@@ -71,84 +71,79 @@ func TestPExpireExec(t *testing.T) {
}
t.Run("create pexpire", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "pexpire name 60000")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
expireAt := time.Now().Add(60 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
})
t.Run("update pexpire", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
red := getRedka(t)
_ = red.Str().SetExpires("name", "alice", 60*time.Second)
cmd := redis.MustParse(parse, "pexpire name 30000")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
expireAt := time.Now().Add(30 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
})
t.Run("set to zero", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "pexpire name 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("negative", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "pexpire name -1000")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "pexpire age 1000")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("age")
testx.AssertEqual(t, key.Exists(), false)
key, _ := red.Key().Get("age")
be.Equal(t, key.Exists(), false)
})
}

View File

@@ -4,9 +4,9 @@ import (
"slices"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRandomKeyParse(t *testing.T) {
@@ -31,9 +31,9 @@ func TestRandomKeyParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRandomKey, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err != nil {
testx.AssertEqual(t, cmd, RandomKey{})
be.Equal(t, cmd, RandomKey{})
}
})
}
@@ -41,28 +41,26 @@ func TestRandomKeyParse(t *testing.T) {
func TestRandomKeyExec(t *testing.T) {
t.Run("found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 25)
_ = db.Str().Set("city", "paris")
keys := []string{"name", "age", "city"}
red := getRedka(t)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 25)
_ = red.Str().Set("city", "paris")
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseRandomKey, "randomkey")
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, slices.Contains(keys, res.(core.Key).Key), true)
testx.AssertEqual(t, slices.Contains(keys, conn.Out()), true)
be.Err(t, err, nil)
keys := []string{"name", "age", "city"}
be.True(t, slices.Contains(keys, res.(core.Key).Key))
be.True(t, slices.Contains(keys, conn.Out()))
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseRandomKey, "randomkey")
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRenameParse(t *testing.T) {
@@ -38,12 +38,12 @@ func TestRenameParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRename, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.newKey, test.newKey)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.newKey, test.newKey)
} else {
testx.AssertEqual(t, cmd, Rename{})
be.Equal(t, cmd, Rename{})
}
})
}
@@ -51,83 +51,75 @@ func TestRenameParse(t *testing.T) {
func TestRenameExec(t *testing.T) {
t.Run("create new", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseRename, "rename name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
})
t.Run("replace existing", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("title", "bob")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("title", "bob")
cmd := redis.MustParse(ParseRename, "rename name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("title")
testx.AssertEqual(t, val.String(), "alice")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("title")
be.Equal(t, val.String(), "alice")
})
t.Run("rename to self", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseRename, "rename name name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("name")
testx.AssertEqual(t, val.String(), "alice")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("name")
be.Equal(t, val.String(), "alice")
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("title", "bob")
red := getRedka(t)
_ = red.Str().Set("title", "bob")
cmd := redis.MustParse(ParseRename, "rename name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertEqual(t, err, core.ErrNotFound)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), redis.ErrNotFound.Error()+" (rename)")
be.Equal(t, err, core.ErrNotFound)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), redis.ErrNotFound.Error()+" (rename)")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("title")
testx.AssertEqual(t, val.String(), "bob")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("title")
be.Equal(t, val.String(), "bob")
})
}

View File

@@ -3,9 +3,9 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRenameNXParse(t *testing.T) {
@@ -38,12 +38,12 @@ func TestRenameNXParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRenameNX, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.newKey, test.newKey)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.newKey, test.newKey)
} else {
testx.AssertEqual(t, cmd, RenameNX{})
be.Equal(t, cmd, RenameNX{})
}
})
}
@@ -51,85 +51,77 @@ func TestRenameNXParse(t *testing.T) {
func TestRenameNXExec(t *testing.T) {
t.Run("create new", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
})
t.Run("replace existing", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("title", "bob")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("title", "bob")
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("name")
testx.AssertEqual(t, val.String(), "alice")
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
val, _ = db.Str().Get("title")
testx.AssertEqual(t, val.String(), "bob")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("name")
be.Equal(t, val.String(), "alice")
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
val, _ = red.Str().Get("title")
be.Equal(t, val.String(), "bob")
})
t.Run("rename to self", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseRenameNX, "renamenx name name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("name")
testx.AssertEqual(t, val.String(), "alice")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("name")
be.Equal(t, val.String(), "alice")
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("title", "bob")
red := getRedka(t)
_ = red.Str().Set("title", "bob")
cmd := redis.MustParse(ParseRenameNX, "renamenx name title")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertEqual(t, err, core.ErrNotFound)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), redis.ErrNotFound.Error()+" (renamenx)")
be.Equal(t, err, core.ErrNotFound)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), redis.ErrNotFound.Error()+" (renamenx)")
key, _ := db.Key().Get("name")
testx.AssertEqual(t, key.Exists(), false)
key, _ = db.Key().Get("title")
testx.AssertEqual(t, key.Exists(), true)
val, _ := db.Str().Get("title")
testx.AssertEqual(t, val.String(), "bob")
key, _ := red.Key().Get("name")
be.Equal(t, key.Exists(), false)
key, _ = red.Key().Get("title")
be.Equal(t, key.Exists(), true)
val, _ := red.Str().Get("title")
be.Equal(t, val.String(), "bob")
})
}

View File

@@ -1,11 +1,12 @@
package key
import (
"fmt"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/rkey"
"github.com/nalgeon/redka/internal/testx"
)
func TestScanParse(t *testing.T) {
@@ -108,14 +109,14 @@ func TestScanParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseScan, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.cursor, test.cursor)
testx.AssertEqual(t, cmd.match, test.match)
testx.AssertEqual(t, cmd.ktype, test.ktype)
testx.AssertEqual(t, cmd.count, test.count)
be.Equal(t, cmd.cursor, test.cursor)
be.Equal(t, cmd.match, test.match)
be.Equal(t, cmd.ktype, test.ktype)
be.Equal(t, cmd.count, test.count)
} else {
testx.AssertEqual(t, cmd, Scan{})
be.Equal(t, cmd, Scan{})
}
})
}
@@ -123,152 +124,164 @@ func TestScanParse(t *testing.T) {
func TestScanExec(t *testing.T) {
t.Run("scan all", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("k11", "11")
_ = db.Str().Set("k12", "12")
_ = db.Str().Set("k21", "21")
_ = db.Str().Set("k22", "22")
_ = db.Str().Set("k31", "31")
_ = red.Str().Set("k11", "11")
_ = red.Str().Set("k12", "12")
_ = red.Str().Set("k21", "21")
_ = red.Str().Set("k22", "22")
_ = red.Str().Set("k31", "31")
var cursor int
{
cmd := redis.MustParse(ParseScan, "scan 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Keys), 5)
testx.AssertEqual(t, sres.Keys[0].Key, "k11")
testx.AssertEqual(t, sres.Keys[4].Key, "k31")
testx.AssertEqual(t, conn.Out(), "2,5,5,k11,k12,k21,k22,k31")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Keys), 5)
be.Equal(t, sres.Keys[0].Key, "k11")
be.Equal(t, sres.Keys[4].Key, "k31")
wantOut := fmt.Sprintf("2,%d,5,k11,k12,k21,k22,k31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
cmd := redis.MustParse(ParseScan, "scan 5")
next := fmt.Sprintf("scan %d", cursor)
cmd := redis.MustParse(ParseScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Keys), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Keys), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
t.Run("scan pattern", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("k11", "11")
_ = db.Str().Set("k12", "12")
_ = db.Str().Set("k21", "21")
_ = db.Str().Set("k22", "22")
_ = db.Str().Set("k31", "31")
_ = red.Str().Set("k11", "11")
_ = red.Str().Set("k12", "12")
_ = red.Str().Set("k21", "21")
_ = red.Str().Set("k22", "22")
_ = red.Str().Set("k31", "31")
cmd := redis.MustParse(ParseScan, "scan 0 match k2*")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Keys), 2)
testx.AssertEqual(t, sres.Keys[0].Key, "k21")
testx.AssertEqual(t, sres.Keys[1].Key, "k22")
testx.AssertEqual(t, conn.Out(), "2,4,2,k21,k22")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Keys), 2)
be.Equal(t, sres.Keys[0].Key, "k21")
be.Equal(t, sres.Keys[1].Key, "k22")
wantOut := fmt.Sprintf("2,%d,2,k21,k22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
})
t.Run("scan type", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("t1", "str")
_, _ = db.List().PushBack("t2", "elem")
_, _ = db.Hash().Set("t4", "field", "value")
_, _ = db.ZSet().Add("t5", "elem", 11)
_ = red.Str().Set("t1", "str")
_, _ = red.List().PushBack("t2", "elem")
_, _ = red.Hash().Set("t4", "field", "value")
_, _ = red.ZSet().Add("t5", "elem", 11)
cmd := redis.MustParse(ParseScan, "scan 0 match t* type hash")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 3)
testx.AssertEqual(t, len(sres.Keys), 1)
testx.AssertEqual(t, sres.Keys[0].Key, "t4")
testx.AssertEqual(t, conn.Out(), "2,3,1,t4")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Keys), 1)
be.Equal(t, sres.Keys[0].Key, "t4")
wantOut := fmt.Sprintf("2,%d,1,t4", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
})
t.Run("scan count", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("k11", "11")
_ = db.Str().Set("k12", "12")
_ = db.Str().Set("k21", "21")
_ = db.Str().Set("k22", "22")
_ = db.Str().Set("k31", "31")
_ = red.Str().Set("k11", "11")
_ = red.Str().Set("k12", "12")
_ = red.Str().Set("k21", "21")
_ = red.Str().Set("k22", "22")
_ = red.Str().Set("k31", "31")
var cursor int
{
// page 1
cmd := redis.MustParse(ParseScan, "scan 0 match * count 2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 2)
testx.AssertEqual(t, len(sres.Keys), 2)
testx.AssertEqual(t, sres.Keys[0].Key, "k11")
testx.AssertEqual(t, sres.Keys[1].Key, "k12")
testx.AssertEqual(t, conn.Out(), "2,2,2,k11,k12")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Keys), 2)
be.Equal(t, sres.Keys[0].Key, "k11")
be.Equal(t, sres.Keys[1].Key, "k12")
wantOut := fmt.Sprintf("2,%d,2,k11,k12", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 2
cmd := redis.MustParse(ParseScan, "scan 2 match * count 2")
next := fmt.Sprintf("scan %d match * count 2", cursor)
cmd := redis.MustParse(ParseScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Keys), 2)
testx.AssertEqual(t, sres.Keys[0].Key, "k21")
testx.AssertEqual(t, sres.Keys[1].Key, "k22")
testx.AssertEqual(t, conn.Out(), "2,4,2,k21,k22")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Keys), 2)
be.Equal(t, sres.Keys[0].Key, "k21")
be.Equal(t, sres.Keys[1].Key, "k22")
wantOut := fmt.Sprintf("2,%d,2,k21,k22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 3
cmd := redis.MustParse(ParseScan, "scan 4 match * count 2")
next := fmt.Sprintf("scan %d match * count 2", cursor)
cmd := redis.MustParse(ParseScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Keys), 1)
testx.AssertEqual(t, sres.Keys[0].Key, "k31")
testx.AssertEqual(t, conn.Out(), "2,5,1,k31")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Keys), 1)
be.Equal(t, sres.Keys[0].Key, "k31")
wantOut := fmt.Sprintf("2,%d,1,k31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// no more pages
cmd := redis.MustParse(ParseScan, "scan 5 match * count 2")
next := fmt.Sprintf("scan %d match * count 2", cursor)
cmd := redis.MustParse(ParseScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rkey.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Keys), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Keys), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
}

View File

@@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestTTLParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestTTLParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseTTL, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, TTL{})
be.Equal(t, cmd, TTL{})
}
})
}
@@ -46,42 +46,37 @@ func TestTTLParse(t *testing.T) {
func TestTTLExec(t *testing.T) {
t.Run("has ttl", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
red := getRedka(t)
_ = red.Str().SetExpires("name", "alice", 60*time.Second)
cmd := redis.MustParse(ParseTTL, "ttl name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 60)
testx.AssertEqual(t, conn.Out(), "60")
be.Err(t, err, nil)
be.Equal(t, res, 60)
be.Equal(t, conn.Out(), "60")
})
t.Run("no ttl", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseTTL, "ttl name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, -1)
testx.AssertEqual(t, conn.Out(), "-1")
be.Err(t, err, nil)
be.Equal(t, res, -1)
be.Equal(t, conn.Out(), "-1")
})
t.Run("not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseTTL, "ttl name")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, -2)
testx.AssertEqual(t, conn.Out(), "-2")
be.Err(t, err, nil)
be.Equal(t, res, -2)
be.Equal(t, conn.Out(), "-2")
})
}

View File

@@ -3,8 +3,8 @@ package key
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestTypeParse(t *testing.T) {
@@ -33,24 +33,23 @@ func TestTypeParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseType, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
be.Equal(t, cmd.key, test.key)
} else {
testx.AssertEqual(t, cmd, Type{})
be.Equal(t, cmd, Type{})
}
})
}
}
func TestTypeExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("kstr", "string")
_, _ = db.List().PushBack("klist", "list")
_, _ = db.Hash().Set("khash", "field", "hash")
_, _ = db.ZSet().Add("kzset", "zset", 1)
_ = red.Str().Set("kstr", "string")
_, _ = red.List().PushBack("klist", "list")
_, _ = red.Hash().Set("khash", "field", "hash")
_, _ = red.ZSet().Add("kzset", "zset", 1)
tests := []struct {
key string
@@ -68,9 +67,9 @@ func TestTypeExec(t *testing.T) {
cmd := redis.MustParse(ParseType, "type "+test.key)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.want)
testx.AssertEqual(t, conn.Out(), test.want)
be.Err(t, err, nil)
be.Equal(t, res.(string), test.want)
be.Equal(t, conn.Out(), test.want)
})
}
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLIndexParse(t *testing.T) {
@@ -39,12 +39,12 @@ func TestLIndexParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLIndex, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.index, test.want.index)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.index, test.want.index)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -52,78 +52,72 @@ func TestLIndexParse(t *testing.T) {
func TestLIndexExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLIndex, "lindex key 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("single elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLIndex, "lindex key 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("elem"))
testx.AssertEqual(t, conn.Out(), "elem")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("elem"))
be.Equal(t, conn.Out(), "elem")
})
t.Run("multiple elems", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLIndex, "lindex key 1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
})
t.Run("list index out of bounds", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLIndex, "lindex key 1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("negative index", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLIndex, "lindex key -2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLIndex, "lindex key 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLInsertParse(t *testing.T) {
@@ -55,14 +55,14 @@ func TestLInsertParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLInsert, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.where, test.want.where)
testx.AssertEqual(t, cmd.pivot, test.want.pivot)
testx.AssertEqual(t, cmd.elem, test.want.elem)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.where, test.want.where)
be.Equal(t, cmd.pivot, test.want.pivot)
be.Equal(t, cmd.elem, test.want.elem)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -70,90 +70,84 @@ func TestLInsertParse(t *testing.T) {
func TestLInsertExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLInsert, "linsert key before pivot elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
_, err = db.List().Get("key", 0)
testx.AssertEqual(t, err, core.ErrNotFound)
_, err = red.List().Get("key", 0)
be.Equal(t, err, core.ErrNotFound)
})
t.Run("insert before first", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, err := db.List().PushBack("key", "pivot")
testx.AssertNoErr(t, err)
red := getRedka(t)
_, err := red.List().PushBack("key", "pivot")
be.Err(t, err, nil)
cmd := redis.MustParse(ParseLInsert, "linsert key before pivot elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
elem, _ := db.List().Get("key", 0)
testx.AssertEqual(t, elem, core.Value("elem"))
elem, _ := red.List().Get("key", 0)
be.Equal(t, elem, core.Value("elem"))
})
t.Run("insert before middle", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLInsert, "linsert key before thr two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 3)
testx.AssertEqual(t, conn.Out(), "3")
be.Err(t, err, nil)
be.Equal(t, res, 3)
be.Equal(t, conn.Out(), "3")
elem, _ := db.List().Get("key", 1)
testx.AssertEqual(t, elem, core.Value("two"))
elem, _ := red.List().Get("key", 1)
be.Equal(t, elem, core.Value("two"))
})
t.Run("insert after middle", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLInsert, "linsert key after thr two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 3)
testx.AssertEqual(t, conn.Out(), "3")
be.Err(t, err, nil)
be.Equal(t, res, 3)
be.Equal(t, conn.Out(), "3")
elem, _ := db.List().Get("key", 2)
testx.AssertEqual(t, elem, core.Value("two"))
elem, _ := red.List().Get("key", 2)
be.Equal(t, elem, core.Value("two"))
})
t.Run("elem not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
cmd := redis.MustParse(ParseLInsert, "linsert key before thr two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, -1)
testx.AssertEqual(t, conn.Out(), "-1")
be.Err(t, err, nil)
be.Equal(t, res, -1)
be.Equal(t, conn.Out(), "-1")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLInsert, "linsert key before pivot elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,15 +3,12 @@ package list
import (
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}

View File

@@ -3,8 +3,8 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLLenParse(t *testing.T) {
@@ -33,11 +33,11 @@ func TestLLenParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLLen, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -45,52 +45,48 @@ func TestLLenParse(t *testing.T) {
func TestLLenExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLLen, "llen key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("single elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLLen, "llen key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
})
t.Run("multiple elems", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLLen, "llen key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 3)
testx.AssertEqual(t, conn.Out(), "3")
be.Err(t, err, nil)
be.Equal(t, res, 3)
be.Equal(t, conn.Out(), "3")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLLen, "llen key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLPopParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestLPopParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLPop, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,62 +46,58 @@ func TestLPopParse(t *testing.T) {
func TestLPopExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLPop, "lpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("pop elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLPop, "lpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("elem"))
testx.AssertEqual(t, conn.Out(), "elem")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("elem"))
be.Equal(t, conn.Out(), "elem")
})
t.Run("pop multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
{
cmd := redis.MustParse(ParseLPop, "lpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("one"))
testx.AssertEqual(t, conn.Out(), "one")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("one"))
be.Equal(t, conn.Out(), "one")
}
{
cmd := redis.MustParse(ParseLPop, "lpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
}
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLPop, "lpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLPushParse(t *testing.T) {
@@ -39,10 +39,10 @@ func TestLPushParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLPush, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.elem, test.want.elem)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.elem, test.want.elem)
}
})
}
@@ -50,70 +50,66 @@ func TestLPushParse(t *testing.T) {
func TestLPushExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLPush, "lpush key elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
elem, _ := db.List().Get("key", 0)
testx.AssertEqual(t, elem.String(), "elem")
elem, _ := red.List().Get("key", 0)
be.Equal(t, elem.String(), "elem")
})
t.Run("add elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
cmd := redis.MustParse(ParseLPush, "lpush key two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
elem, _ := db.List().Get("key", 0)
testx.AssertEqual(t, elem.String(), "two")
elem, _ := red.List().Get("key", 0)
be.Equal(t, elem.String(), "two")
})
t.Run("add miltiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
{
cmd := redis.MustParse(ParseLPush, "lpush key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
}
{
cmd := redis.MustParse(ParseLPush, "lpush key two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
}
el0, _ := db.List().Get("key", 0)
testx.AssertEqual(t, el0.String(), "two")
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "one")
el0, _ := red.List().Get("key", 0)
be.Equal(t, el0.String(), "two")
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "one")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLPush, "lpush key elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (lpush)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (lpush)")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLRangeParse(t *testing.T) {
@@ -39,13 +39,13 @@ func TestLRangeParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLRange, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.start, test.want.start)
testx.AssertEqual(t, cmd.stop, test.want.stop)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.start, test.want.start)
be.Equal(t, cmd.stop, test.want.stop)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -53,94 +53,87 @@ func TestLRangeParse(t *testing.T) {
func TestLRangeExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLRange, "lrange key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
t.Run("single elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLRange, "lrange key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{core.Value("elem")})
testx.AssertEqual(t, conn.Out(), "1,elem")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value{core.Value("elem")})
be.Equal(t, conn.Out(), "1,elem")
})
t.Run("multiple elems", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLRange, "lrange key 0 1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{core.Value("one"), core.Value("two")})
testx.AssertEqual(t, conn.Out(), "2,one,two")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, conn.Out(), "2,one,two")
})
t.Run("negative indexes", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLRange, "lrange key -2 -1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{core.Value("two"), core.Value("thr")})
testx.AssertEqual(t, conn.Out(), "2,two,thr")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value{core.Value("two"), core.Value("thr")})
be.Equal(t, conn.Out(), "2,two,thr")
})
t.Run("out of bounds", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLRange, "lrange key 3 5")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
t.Run("start < stop", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLRange, "lrange key 2 1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLRange, "lrange key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,8 +3,8 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLRemParse(t *testing.T) {
@@ -43,13 +43,13 @@ func TestLRemParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLRem, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.count, test.want.count)
testx.AssertEqual(t, cmd.elem, test.want.elem)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.count, test.want.count)
be.Equal(t, cmd.elem, test.want.elem)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -57,120 +57,113 @@ func TestLRemParse(t *testing.T) {
func TestLRemExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLRem, "lrem key 1 elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("delete elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLRem, "lrem key 1 elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 0)
count, _ := red.List().Len("key")
be.Equal(t, count, 0)
})
t.Run("delete front", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "fou")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "fou")
cmd := redis.MustParse(ParseLRem, "lrem key 2 two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 4)
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "thr")
count, _ := red.List().Len("key")
be.Equal(t, count, 4)
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "thr")
})
t.Run("delete back", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "fou")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "fou")
cmd := redis.MustParse(ParseLRem, "lrem key -2 two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 4)
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "two")
count, _ := red.List().Len("key")
be.Equal(t, count, 4)
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "two")
})
t.Run("delete all", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "fou")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "fou")
cmd := redis.MustParse(ParseLRem, "lrem key 0 two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 3)
testx.AssertEqual(t, conn.Out(), "3")
be.Err(t, err, nil)
be.Equal(t, res, 3)
be.Equal(t, conn.Out(), "3")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 3)
count, _ := red.List().Len("key")
be.Equal(t, count, 3)
})
t.Run("elem not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLRem, "lrem key 1 other")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 1)
count, _ := red.List().Len("key")
be.Equal(t, count, 1)
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLRem, "lrem key 1 elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLSetParse(t *testing.T) {
@@ -44,13 +44,13 @@ func TestLSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.index, test.want.index)
testx.AssertEqual(t, cmd.elem, test.want.elem)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.index, test.want.index)
be.Equal(t, cmd.elem, test.want.elem)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -58,72 +58,67 @@ func TestLSetParse(t *testing.T) {
func TestLSetExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLSet, "lset key 0 elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrNotFound)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
be.Err(t, err, core.ErrNotFound)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
})
t.Run("set elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLSet, "lset key 1 upd")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), "OK")
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "upd")
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "upd")
})
t.Run("negative index", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLSet, "lset key -1 upd")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), "OK")
el2, _ := db.List().Get("key", 2)
testx.AssertEqual(t, el2.String(), "upd")
el2, _ := red.List().Get("key", 2)
be.Equal(t, el2.String(), "upd")
})
t.Run("index out of bounds", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLSet, "lset key 1 upd")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrNotFound)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
be.Err(t, err, core.ErrNotFound)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLSet, "lset key 0 elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrNotFound)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
be.Err(t, err, core.ErrNotFound)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), redis.ErrOutOfRange.Error()+" (lset)")
})
}

View File

@@ -3,8 +3,8 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLTrimParse(t *testing.T) {
@@ -33,13 +33,13 @@ func TestLTrimParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLTrim, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.start, test.want.start)
testx.AssertEqual(t, cmd.stop, test.want.stop)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.start, test.want.start)
be.Equal(t, cmd.stop, test.want.stop)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -47,98 +47,92 @@ func TestLTrimParse(t *testing.T) {
func TestLTrimExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLTrim, "ltrim key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "OK")
})
t.Run("keep single elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseLTrim, "ltrim key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "OK")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 1)
count, _ := red.List().Len("key")
be.Equal(t, count, 1)
})
t.Run("keep multiple elems", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
_, _ = db.List().PushBack("key", "fou")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
_, _ = red.List().PushBack("key", "fou")
cmd := redis.MustParse(ParseLTrim, "ltrim key 1 2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "OK")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 2)
el0, _ := db.List().Get("key", 0)
testx.AssertEqual(t, el0.String(), "two")
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "thr")
count, _ := red.List().Len("key")
be.Equal(t, count, 2)
el0, _ := red.List().Get("key", 0)
be.Equal(t, el0.String(), "two")
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "thr")
})
t.Run("negative index", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
_, _ = db.List().PushBack("key", "fou")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
_, _ = red.List().PushBack("key", "fou")
cmd := redis.MustParse(ParseLTrim, "ltrim key 0 -1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "OK")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 4)
count, _ := red.List().Len("key")
be.Equal(t, count, 4)
})
t.Run("start > stop", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
cmd := redis.MustParse(ParseLTrim, "ltrim key 2 1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 3)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 3)
be.Equal(t, conn.Out(), "OK")
count, _ := db.List().Len("key")
testx.AssertEqual(t, count, 0)
count, _ := red.List().Len("key")
be.Equal(t, count, 0)
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseLTrim, "ltrim key 0 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "OK")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRPopParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestRPopParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRPop, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,62 +46,58 @@ func TestRPopParse(t *testing.T) {
func TestRPopExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseRPop, "rpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("pop elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("key", "elem")
cmd := redis.MustParse(ParseRPop, "rpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("elem"))
testx.AssertEqual(t, conn.Out(), "elem")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("elem"))
be.Equal(t, conn.Out(), "elem")
})
t.Run("pop multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
_, _ = db.List().PushBack("key", "two")
_, _ = db.List().PushBack("key", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
_, _ = red.List().PushBack("key", "two")
_, _ = red.List().PushBack("key", "thr")
{
cmd := redis.MustParse(ParseRPop, "rpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("thr"))
testx.AssertEqual(t, conn.Out(), "thr")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("thr"))
be.Equal(t, conn.Out(), "thr")
}
{
cmd := redis.MustParse(ParseRPop, "rpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
}
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseRPop, "rpop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRPopLPushParse(t *testing.T) {
@@ -34,12 +34,12 @@ func TestRPopLPushParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRPopLPush, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.src, test.want.src)
testx.AssertEqual(t, cmd.dst, test.want.dst)
be.Equal(t, cmd.src, test.want.src)
be.Equal(t, cmd.dst, test.want.dst)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -47,101 +47,96 @@ func TestRPopLPushParse(t *testing.T) {
func TestRPopLPushExec(t *testing.T) {
t.Run("src not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src dst")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("pop elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("src", "elem")
red := getRedka(t)
_, _ = red.List().PushBack("src", "elem")
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src dst")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("elem"))
testx.AssertEqual(t, conn.Out(), "elem")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("elem"))
be.Equal(t, conn.Out(), "elem")
count, _ := db.List().Len("src")
testx.AssertEqual(t, count, 0)
count, _ = db.List().Len("dst")
testx.AssertEqual(t, count, 1)
count, _ := red.List().Len("src")
be.Equal(t, count, 0)
count, _ = red.List().Len("dst")
be.Equal(t, count, 1)
})
t.Run("pop multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("src", "one")
_, _ = db.List().PushBack("src", "two")
_, _ = db.List().PushBack("src", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("src", "one")
_, _ = red.List().PushBack("src", "two")
_, _ = red.List().PushBack("src", "thr")
{
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src dst")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("thr"))
testx.AssertEqual(t, conn.Out(), "thr")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("thr"))
be.Equal(t, conn.Out(), "thr")
}
{
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src dst")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
}
count, _ := db.List().Len("src")
testx.AssertEqual(t, count, 1)
count, _ = db.List().Len("dst")
testx.AssertEqual(t, count, 2)
count, _ := red.List().Len("src")
be.Equal(t, count, 1)
count, _ = red.List().Len("dst")
be.Equal(t, count, 2)
})
t.Run("push to self", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("src", "one")
_, _ = db.List().PushBack("src", "two")
_, _ = db.List().PushBack("src", "thr")
red := getRedka(t)
_, _ = red.List().PushBack("src", "one")
_, _ = red.List().PushBack("src", "two")
_, _ = red.List().PushBack("src", "thr")
{
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src src")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("thr"))
testx.AssertEqual(t, conn.Out(), "thr")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("thr"))
be.Equal(t, conn.Out(), "thr")
}
{
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src src")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("two"))
testx.AssertEqual(t, conn.Out(), "two")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("two"))
be.Equal(t, conn.Out(), "two")
}
elems, _ := db.List().Range("src", 0, -1)
testx.AssertEqual(t, elems[0].String(), "two")
testx.AssertEqual(t, elems[1].String(), "thr")
testx.AssertEqual(t, elems[2].String(), "one")
elems, _ := red.List().Range("src", 0, -1)
be.Equal(t, elems[0].String(), "two")
be.Equal(t, elems[1].String(), "thr")
be.Equal(t, elems[2].String(), "one")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("src", "str")
red := getRedka(t)
_ = red.Str().Set("src", "str")
cmd := redis.MustParse(ParseRPopLPush, "rpoplpush src dst")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package list
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestRPushParse(t *testing.T) {
@@ -39,12 +39,12 @@ func TestRPushParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseRPush, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.elem, test.want.elem)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.elem, test.want.elem)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -52,70 +52,66 @@ func TestRPushParse(t *testing.T) {
func TestRPushExec(t *testing.T) {
t.Run("empty list", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseRPush, "rpush key elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
elem, _ := db.List().Get("key", 0)
testx.AssertEqual(t, elem.String(), "elem")
elem, _ := red.List().Get("key", 0)
be.Equal(t, elem.String(), "elem")
})
t.Run("add elem", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.List().PushBack("key", "one")
red := getRedka(t)
_, _ = red.List().PushBack("key", "one")
cmd := redis.MustParse(ParseRPush, "rpush key two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
elem, _ := db.List().Get("key", 1)
testx.AssertEqual(t, elem.String(), "two")
elem, _ := red.List().Get("key", 1)
be.Equal(t, elem.String(), "two")
})
t.Run("add miltiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
{
cmd := redis.MustParse(ParseRPush, "rpush key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
}
{
cmd := redis.MustParse(ParseRPush, "rpush key two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
}
el0, _ := db.List().Get("key", 0)
testx.AssertEqual(t, el0.String(), "one")
el1, _ := db.List().Get("key", 1)
testx.AssertEqual(t, el1.String(), "two")
el0, _ := red.List().Get("key", 0)
be.Equal(t, el0.String(), "one")
el1, _ := red.List().Get("key", 1)
be.Equal(t, el1.String(), "two")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseRPush, "rpush key elem")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (rpush)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (rpush)")
})
}

View File

@@ -3,8 +3,8 @@ package server
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestConfigParse(t *testing.T) {
@@ -38,11 +38,11 @@ func TestConfigParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseConfig, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.subcmd, test.want.subcmd)
be.Equal(t, cmd.subcmd, test.want.subcmd)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -50,14 +50,13 @@ func TestConfigParse(t *testing.T) {
func TestConfigExec(t *testing.T) {
t.Run("config get", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseConfig, "config get *")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "2,databases,1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "2,databases,1")
})
}

View File

@@ -3,8 +3,8 @@ package server
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestDBSizeParse(t *testing.T) {
@@ -25,9 +25,9 @@ func TestDBSizeParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseDBSize, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err != nil {
testx.AssertEqual(t, cmd, DBSize{})
be.Equal(t, cmd, DBSize{})
}
})
}
@@ -35,29 +35,26 @@ func TestDBSizeParse(t *testing.T) {
func TestDBSizeExec(t *testing.T) {
t.Run("dbsize", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 25)
red := getRedka(t)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 25)
cmd := redis.MustParse(ParseDBSize, "dbsize")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseDBSize, "dbsize")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -4,8 +4,8 @@ import (
"strings"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestLolwutParse(t *testing.T) {
@@ -30,9 +30,9 @@ func TestLolwutParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseLolwut, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err != nil {
testx.AssertEqual(t, cmd, Lolwut{})
be.Equal(t, cmd, Lolwut{})
}
})
}
@@ -40,24 +40,22 @@ func TestLolwutParse(t *testing.T) {
func TestLolwutExec(t *testing.T) {
t.Run("lolwut", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLolwut, "lolwut you ok?")
conn := redis.NewFakeConn()
_, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(conn.Out()) >= 3, true)
be.Err(t, err, nil)
be.Equal(t, len(conn.Out()) >= 3, true)
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseLolwut, "lolwut")
conn := redis.NewFakeConn()
_, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, strings.HasPrefix(conn.Out(), "Ask me a question"), true)
be.Err(t, err, nil)
be.Equal(t, strings.HasPrefix(conn.Out(), "Ask me a question"), true)
})
}

View File

@@ -3,15 +3,12 @@ package server
import (
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSAddParse(t *testing.T) {
@@ -44,12 +44,12 @@ func TestSAddParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSAdd, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.members, test.want.members)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.members, test.want.members)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -57,76 +57,71 @@ func TestSAddParse(t *testing.T) {
func TestSAddExec(t *testing.T) {
t.Run("create single", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSAdd, "sadd key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("key")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("key")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("create multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSAdd, "sadd key one two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("key")
items, _ := red.Set().Items("key")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("create/update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one")
red := getRedka(t)
_, _ = red.Set().Add("key", "one")
cmd := redis.MustParse(ParseSAdd, "sadd key one two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("key")
items, _ := red.Set().Items("key")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("update multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two")
cmd := redis.MustParse(ParseSAdd, "sadd key one two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("key")
items, _ := red.Set().Items("key")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "value")
red := getRedka(t)
_ = red.Str().Set("key", "value")
cmd := redis.MustParse(ParseSAdd, "sadd key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (sadd)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (sadd)")
})
}

View File

@@ -3,8 +3,8 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSCardParse(t *testing.T) {
@@ -33,11 +33,11 @@ func TestSCardParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSCard, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -45,51 +45,47 @@ func TestSCardParse(t *testing.T) {
func TestSCardExec(t *testing.T) {
t.Run("card", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two")
cmd := redis.MustParse(ParseSCard, "scard key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one")
_, _ = db.Set().Delete("key", "one")
red := getRedka(t)
_, _ = red.Set().Add("key", "one")
_, _ = red.Set().Delete("key", "one")
cmd := redis.MustParse(ParseSCard, "scard key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSCard, "scard key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "value")
red := getRedka(t)
_ = red.Str().Set("key", "value")
cmd := redis.MustParse(ParseSCard, "scard key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSDiffParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSDiffParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSDiff, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.keys, test.want.keys)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,105 +46,97 @@ func TestSDiffParse(t *testing.T) {
func TestSDiffExec(t *testing.T) {
t.Run("non-empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr", "fiv")
_, _ = db.Set().Add("key2", "two", "fou", "six")
_, _ = db.Set().Add("key3", "thr", "six")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr", "fiv")
_, _ = red.Set().Add("key2", "two", "fou", "six")
_, _ = red.Set().Add("key3", "thr", "six")
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 2)
testx.AssertEqual(t, conn.Out(), "2,fiv,one")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 2)
be.Equal(t, conn.Out(), "2,fiv,one", "2,one,fiv")
})
t.Run("no keys", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSDiff, "sdiff key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
cmd := redis.MustParse(ParseSDiff, "sdiff key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 3)
testx.AssertEqual(t, conn.Out(), "3,one,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 3)
be.Equal(t, conn.Out(), "3,one,thr,two", "3,one,two,thr")
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("key2", "one", "fou")
_, _ = db.Set().Add("key3", "two", "fiv")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("key2", "one", "fou")
_, _ = red.Set().Add("key3", "two", "fiv")
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("first not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key2", "two")
_, _ = db.Set().Add("key3", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key2", "two")
_, _ = red.Set().Add("key3", "thr")
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("rest not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 1)
testx.AssertEqual(t, conn.Out(), "1,one")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 1)
be.Equal(t, conn.Out(), "1,one")
})
t.Run("all not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_ = db.Str().Set("key2", "two")
_, _ = db.Set().Add("key3", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_ = red.Str().Set("key2", "two")
_, _ = red.Set().Add("key3", "thr")
cmd := redis.MustParse(ParseSDiff, "sdiff key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 1)
testx.AssertEqual(t, conn.Out(), "1,one")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 1)
be.Equal(t, conn.Out(), "1,one")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSDiffStoreParse(t *testing.T) {
@@ -39,12 +39,12 @@ func TestSDiffStoreParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSDiffStore, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.dest, test.want.dest)
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.dest, test.want.dest)
be.Equal(t, cmd.keys, test.want.keys)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -52,139 +52,131 @@ func TestSDiffStoreParse(t *testing.T) {
func TestSDiffStoreExec(t *testing.T) {
t.Run("store", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr", "fiv")
_, _ = db.Set().Add("key2", "two", "fou", "six")
_, _ = db.Set().Add("key3", "thr", "six")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr", "fiv")
_, _ = red.Set().Add("key2", "two", "fou", "six")
_, _ = red.Set().Add("key3", "thr", "six")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("fiv"), core.Value("one")})
be.Equal(t, items, []core.Value{core.Value("fiv"), core.Value("one")})
})
t.Run("rewrite dest", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("first not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key2", "two")
_, _ = db.Set().Add("key3", "thr")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key2", "two")
_, _ = red.Set().Add("key3", "thr")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("rest not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("source key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
_ = db.Str().Set("key3", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
_ = red.Str().Set("key3", "thr")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("dest key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
_ = db.Str().Set("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
_ = red.Str().Set("dest", "old")
cmd := redis.MustParse(ParseSDiffStore, "sdiffstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (sdiffstore)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (sdiffstore)")
sval, _ := db.Str().Get("dest")
testx.AssertEqual(t, sval, core.Value("old"))
sval, _ := red.Str().Get("dest")
be.Equal(t, sval, core.Value("old"))
})
}

View File

@@ -5,18 +5,15 @@ import (
"sort"
"testing"
"github.com/nalgeon/redka"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func getDB(tb testing.TB) (*redka.DB, redis.Redka) {
func getRedka(tb testing.TB) redis.Redka {
tb.Helper()
db, err := redka.Open("file:/data.db?vfs=memdb", nil)
if err != nil {
tb.Fatal(err)
}
return db, redis.RedkaDB(db)
db := testx.OpenDB(tb)
return redis.RedkaDB(db)
}
func sortValues(vals []core.Value) {

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSInterParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSInterParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSInter, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.keys, test.want.keys)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,92 +46,85 @@ func TestSInterParse(t *testing.T) {
func TestSInterExec(t *testing.T) {
t.Run("non-empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
_, _ = db.Set().Add("key2", "two", "thr", "fou")
_, _ = db.Set().Add("key3", "one", "two", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
_, _ = red.Set().Add("key2", "two", "thr", "fou")
_, _ = red.Set().Add("key3", "one", "two", "thr", "fou")
cmd := redis.MustParse(ParseSInter, "sinter key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 2)
testx.AssertEqual(t, conn.Out(), "2,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 2)
be.Equal(t, conn.Out(), "2,thr,two")
})
t.Run("no keys", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSInter, "sinter key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
cmd := redis.MustParse(ParseSInter, "sinter key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 3)
testx.AssertEqual(t, conn.Out(), "3,one,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 3)
be.Equal(t, conn.Out(), "3,one,thr,two")
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("key2", "two", "thr")
_, _ = db.Set().Add("key3", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("key2", "two", "thr")
_, _ = red.Set().Add("key3", "thr", "fou")
cmd := redis.MustParse(ParseSInter, "sinter key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
cmd := redis.MustParse(ParseSInter, "sinter key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("all not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSInter, "sinter key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_ = db.Str().Set("key2", "one")
_, _ = db.Set().Add("key3", "one")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_ = red.Str().Set("key2", "one")
_, _ = red.Set().Add("key3", "one")
cmd := redis.MustParse(ParseSInter, "sinter key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSInterStoreParse(t *testing.T) {
@@ -39,10 +39,10 @@ func TestSInterStoreParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSInterStore, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.dest, test.want.dest)
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.dest, test.want.dest)
be.Equal(t, cmd.keys, test.want.keys)
}
})
}
@@ -50,123 +50,116 @@ func TestSInterStoreParse(t *testing.T) {
func TestSInterStoreExec(t *testing.T) {
t.Run("store", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
_, _ = db.Set().Add("key2", "two", "thr", "fou")
_, _ = db.Set().Add("key3", "one", "two", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
_, _ = red.Set().Add("key2", "two", "thr", "fou")
_, _ = red.Set().Add("key3", "one", "two", "thr", "fou")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("thr"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("thr"), core.Value("two")})
})
t.Run("rewrite dest", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("source key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("source key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_ = db.Str().Set("key3", "one")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_ = red.Str().Set("key3", "one")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("dest key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_ = db.Str().Set("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_ = red.Str().Set("dest", "old")
cmd := redis.MustParse(ParseSInterStore, "sinterstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (sinterstore)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (sinterstore)")
sval, _ := db.Str().Get("dest")
testx.AssertEqual(t, sval, core.Value("old"))
sval, _ := red.Str().Get("dest")
be.Equal(t, sval, core.Value("old"))
})
}

View File

@@ -3,8 +3,8 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSIsMemberParse(t *testing.T) {
@@ -38,12 +38,12 @@ func TestSIsMemberParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSIsMember, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.member, test.want.member)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.member, test.want.member)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -51,50 +51,46 @@ func TestSIsMemberParse(t *testing.T) {
func TestSIsMemberExec(t *testing.T) {
t.Run("elem found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one")
red := getRedka(t)
_, _ = red.Set().Add("key", "one")
cmd := redis.MustParse(ParseSIsMember, "sismember key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "1")
})
t.Run("elem not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one")
red := getRedka(t)
_, _ = red.Set().Add("key", "one")
cmd := redis.MustParse(ParseSIsMember, "sismember key two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSIsMember, "sismember key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "one")
red := getRedka(t)
_ = red.Str().Set("key", "one")
cmd := redis.MustParse(ParseSIsMember, "sismember key one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, false)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, false)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSMembersParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSMembersParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSMembers, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,40 +46,35 @@ func TestSMembersParse(t *testing.T) {
func TestSMembersExec(t *testing.T) {
t.Run("items", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two", "thr")
cmd := redis.MustParse(ParseSMembers, "smembers key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value{
core.Value("one"), core.Value("thr"), core.Value("two"),
})
testx.AssertEqual(t, conn.Out(), "3,one,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 3)
be.Equal(t, conn.Out(), "3,one,thr,two", "3,one,two,thr")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSMembers, "smembers key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "value")
red := getRedka(t)
_ = red.Str().Set("key", "value")
cmd := redis.MustParse(ParseSMembers, "smembers key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, []core.Value(nil))
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res.([]core.Value), []core.Value(nil))
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSMoveParse(t *testing.T) {
@@ -39,13 +39,13 @@ func TestSMoveParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSMove, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.src, test.want.src)
testx.AssertEqual(t, cmd.dest, test.want.dest)
testx.AssertEqual(t, cmd.member, test.want.member)
be.Equal(t, cmd.src, test.want.src)
be.Equal(t, cmd.dest, test.want.dest)
be.Equal(t, cmd.member, test.want.member)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -53,109 +53,103 @@ func TestSMoveParse(t *testing.T) {
func TestSMoveExec(t *testing.T) {
t.Run("move", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("src", "one", "two")
_, _ = db.Set().Add("dest", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("src", "one", "two")
_, _ = red.Set().Add("dest", "thr", "fou")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, false)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, true)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, false)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, true)
})
t.Run("dest not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("src", "one", "two")
red := getRedka(t)
_, _ = red.Set().Add("src", "one", "two")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, false)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, true)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, false)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, true)
})
t.Run("src elem not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("src", "two")
_, _ = db.Set().Add("dest", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("src", "two")
_, _ = red.Set().Add("dest", "thr", "fou")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, false)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, false)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, false)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, false)
})
t.Run("src key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("dest", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("dest", "thr", "fou")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, false)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, false)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, false)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, false)
})
t.Run("dest type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("src", "one", "two")
_ = db.Str().Set("dest", "str")
red := getRedka(t)
_, _ = red.Set().Add("src", "one", "two")
_ = red.Str().Set("dest", "str")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (smove)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (smove)")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, true)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, false)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, true)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, false)
})
t.Run("src type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("src", "one")
_, _ = db.Set().Add("dest", "thr", "fou")
red := getRedka(t)
_ = red.Str().Set("src", "one")
_, _ = red.Set().Add("dest", "thr", "fou")
cmd := redis.MustParse(ParseSMove, "smove src dest one")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
sone, _ := db.Set().Exists("src", "one")
testx.AssertEqual(t, sone, false)
done, _ := db.Set().Exists("dest", "one")
testx.AssertEqual(t, done, false)
sone, _ := red.Set().Exists("src", "one")
be.Equal(t, sone, false)
done, _ := red.Set().Exists("dest", "one")
be.Equal(t, done, false)
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSPopParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSPopParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSPop, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,43 +46,40 @@ func TestSPopParse(t *testing.T) {
func TestSPopExec(t *testing.T) {
t.Run("pop", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two", "thr")
cmd := redis.MustParse(ParseSPop, "spop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
s := res.(core.Value).String()
testx.AssertEqual(t, s == "one" || s == "two" || s == "thr", true)
be.Equal(t, s == "one" || s == "two" || s == "thr", true)
s = conn.Out()
testx.AssertEqual(t, s == "one" || s == "two" || s == "thr", true)
be.Equal(t, s == "one" || s == "two" || s == "thr", true)
slen, _ := db.Set().Len("key")
testx.AssertEqual(t, slen, 2)
slen, _ := red.Set().Len("key")
be.Equal(t, slen, 2)
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSPop, "spop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "value")
red := getRedka(t)
_ = red.Str().Set("key", "value")
cmd := redis.MustParse(ParseSPop, "spop key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSRandMemberParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSRandMemberParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSRandMember, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
be.Equal(t, cmd.key, test.want.key)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,40 +46,37 @@ func TestSRandMemberParse(t *testing.T) {
func TestSRandMemberExec(t *testing.T) {
t.Run("random", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two", "thr")
cmd := redis.MustParse(ParseSRandMember, "srandmember key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
s := res.(core.Value).String()
testx.AssertEqual(t, s == "one" || s == "two" || s == "thr", true)
be.Equal(t, s == "one" || s == "two" || s == "thr", true)
s = conn.Out()
testx.AssertEqual(t, s == "one" || s == "two" || s == "thr", true)
be.Equal(t, s == "one" || s == "two" || s == "thr", true)
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSRandMember, "srandmember key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "value")
red := getRedka(t)
_ = red.Str().Set("key", "value")
cmd := redis.MustParse(ParseSRandMember, "srandmember key")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSRemParse(t *testing.T) {
@@ -44,12 +44,12 @@ func TestSRemParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSRem, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.members, test.want.members)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.members, test.want.members)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -57,56 +57,52 @@ func TestSRemParse(t *testing.T) {
func TestSRemExec(t *testing.T) {
t.Run("some", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two", "thr")
cmd := redis.MustParse(ParseSRem, "srem key one thr")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("key")
testx.AssertEqual(t, items, []core.Value{core.Value("two")})
items, _ := red.Set().Items("key")
be.Equal(t, items, []core.Value{core.Value("two")})
})
t.Run("none", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key", "one", "two", "thr")
cmd := redis.MustParse(ParseSRem, "srem key fou fiv")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
slen, _ := db.Set().Len("key")
testx.AssertEqual(t, slen, 3)
slen, _ := red.Set().Len("key")
be.Equal(t, slen, 3)
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSRem, "srem key one two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("key", "str")
red := getRedka(t)
_ = red.Str().Set("key", "str")
cmd := redis.MustParse(ParseSRem, "srem key one two")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
})
}

View File

@@ -1,12 +1,13 @@
package set
import (
"fmt"
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/rset"
"github.com/nalgeon/redka/internal/testx"
)
func TestSScanParse(t *testing.T) {
@@ -103,50 +104,53 @@ func TestSScanParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSScan, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.key)
testx.AssertEqual(t, cmd.cursor, test.cursor)
testx.AssertEqual(t, cmd.match, test.match)
testx.AssertEqual(t, cmd.count, test.count)
be.Equal(t, cmd.key, test.key)
be.Equal(t, cmd.cursor, test.cursor)
be.Equal(t, cmd.match, test.match)
be.Equal(t, cmd.count, test.count)
} else {
testx.AssertEqual(t, cmd, SScan{})
be.Equal(t, cmd, SScan{})
}
})
}
}
func TestSScanExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key", "m11", "m12", "m21", "m22", "m31")
red := getRedka(t)
_, _ = red.Set().Add("key", "m11", "m12", "m21", "m22", "m31")
t.Run("sscan all", func(t *testing.T) {
var cursor int
{
cmd := redis.MustParse(ParseSScan, "sscan key 0")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Items), 5)
testx.AssertEqual(t, sres.Items[0], core.Value("m11"))
testx.AssertEqual(t, sres.Items[4], core.Value("m31"))
testx.AssertEqual(t, conn.Out(), "2,5,5,m11,m12,m21,m22,m31")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Items), 5)
be.Equal(t, sres.Items[0], core.Value("m11"))
be.Equal(t, sres.Items[4], core.Value("m31"))
wantOut := fmt.Sprintf("2,%d,5,m11,m12,m21,m22,m31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
cmd := redis.MustParse(ParseSScan, "sscan key 5")
next := fmt.Sprintf("sscan key %d", cursor)
cmd := redis.MustParse(ParseSScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Items), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Items), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
t.Run("sscan pattern", func(t *testing.T) {
@@ -154,72 +158,83 @@ func TestSScanExec(t *testing.T) {
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].String(), "m21")
testx.AssertEqual(t, sres.Items[1].String(), "m22")
testx.AssertEqual(t, conn.Out(), "2,4,2,m21,m22")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].String(), "m21")
be.Equal(t, sres.Items[1].String(), "m22")
wantOut := fmt.Sprintf("2,%d,2,m21,m22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
})
t.Run("sscan count", func(t *testing.T) {
var cursor int
{
// page 1
cmd := redis.MustParse(ParseSScan, "sscan key 0 match * count 2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 2)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].String(), "m11")
testx.AssertEqual(t, sres.Items[1].String(), "m12")
testx.AssertEqual(t, conn.Out(), "2,2,2,m11,m12")
be.True(t, sres.Cursor > 0)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].String(), "m11")
be.Equal(t, sres.Items[1].String(), "m12")
wantOut := fmt.Sprintf("2,%d,2,m11,m12", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 2
cmd := redis.MustParse(ParseSScan, "sscan key 2 match * count 2")
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseSScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 4)
testx.AssertEqual(t, len(sres.Items), 2)
testx.AssertEqual(t, sres.Items[0].String(), "m21")
testx.AssertEqual(t, sres.Items[1].String(), "m22")
testx.AssertEqual(t, conn.Out(), "2,4,2,m21,m22")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Items), 2)
be.Equal(t, sres.Items[0].String(), "m21")
be.Equal(t, sres.Items[1].String(), "m22")
wantOut := fmt.Sprintf("2,%d,2,m21,m22", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// page 3
cmd := redis.MustParse(ParseSScan, "sscan key 4 match * count 2")
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseSScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 5)
testx.AssertEqual(t, len(sres.Items), 1)
testx.AssertEqual(t, sres.Items[0].String(), "m31")
testx.AssertEqual(t, conn.Out(), "2,5,1,m31")
be.True(t, sres.Cursor > cursor)
be.Equal(t, len(sres.Items), 1)
be.Equal(t, sres.Items[0].String(), "m31")
wantOut := fmt.Sprintf("2,%d,1,m31", sres.Cursor)
be.Equal(t, conn.Out(), wantOut)
cursor = sres.Cursor
}
{
// no more pages
cmd := redis.MustParse(ParseSScan, "sscan key 5 match * count 2")
next := fmt.Sprintf("sscan key %d match * count 2", cursor)
cmd := redis.MustParse(ParseSScan, next)
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
be.Err(t, err, nil)
sres := res.(rset.ScanResult)
testx.AssertEqual(t, sres.Cursor, 0)
testx.AssertEqual(t, len(sres.Items), 0)
testx.AssertEqual(t, conn.Out(), "2,0,0")
be.Equal(t, sres.Cursor, 0)
be.Equal(t, len(sres.Items), 0)
be.Equal(t, conn.Out(), "2,0,0")
}
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSUnionParse(t *testing.T) {
@@ -34,11 +34,11 @@ func TestSUnionParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSUnion, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.keys, test.want.keys)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -46,78 +46,72 @@ func TestSUnionParse(t *testing.T) {
func TestSUnionExec(t *testing.T) {
t.Run("non-empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("key2", "two", "thr")
_, _ = db.Set().Add("key3", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("key2", "two", "thr")
_, _ = red.Set().Add("key3", "thr", "fou")
cmd := redis.MustParse(ParseSUnion, "sunion key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 4)
testx.AssertEqual(t, conn.Out(), "4,fou,one,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 4)
be.Equal(t, conn.Out(), "4,fou,one,thr,two")
})
t.Run("no keys", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSUnion, "sunion key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
cmd := redis.MustParse(ParseSUnion, "sunion key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 3)
testx.AssertEqual(t, conn.Out(), "3,one,thr,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 3)
be.Equal(t, conn.Out(), "3,one,thr,two")
})
t.Run("key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "two")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "two")
cmd := redis.MustParse(ParseSUnion, "sunion key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 2)
testx.AssertEqual(t, conn.Out(), "2,one,two")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 2)
be.Equal(t, conn.Out(), "2,one,two")
})
t.Run("all not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseSUnion, "sunion key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 0)
be.Equal(t, conn.Out(), "0")
})
t.Run("key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_ = db.Str().Set("key2", "two")
_, _ = db.Set().Add("key3", "thr")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_ = red.Str().Set("key2", "two")
_, _ = red.Set().Add("key3", "thr")
cmd := redis.MustParse(ParseSUnion, "sunion key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, len(res.([]core.Value)), 2)
testx.AssertEqual(t, conn.Out(), "2,one,thr")
be.Err(t, err, nil)
be.Equal(t, len(res.([]core.Value)), 2)
be.Equal(t, conn.Out(), "2,one,thr")
})
}

View File

@@ -3,9 +3,9 @@ package set
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSUnionStoreParse(t *testing.T) {
@@ -39,12 +39,12 @@ func TestSUnionStoreParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSUnionStore, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.dest, test.want.dest)
testx.AssertEqual(t, cmd.keys, test.want.keys)
be.Equal(t, cmd.dest, test.want.dest)
be.Equal(t, cmd.keys, test.want.keys)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -52,123 +52,116 @@ func TestSUnionStoreParse(t *testing.T) {
func TestSUnionStoreExec(t *testing.T) {
t.Run("store", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two", "thr")
_, _ = db.Set().Add("key2", "two", "thr", "fou")
_, _ = db.Set().Add("key3", "one", "two", "thr", "fou")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two", "thr")
_, _ = red.Set().Add("key2", "two", "thr", "fou")
_, _ = red.Set().Add("key3", "one", "two", "thr", "fou")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 4)
testx.AssertEqual(t, conn.Out(), "4")
be.Err(t, err, nil)
be.Equal(t, res, 4)
be.Equal(t, conn.Out(), "4")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{
be.Equal(t, items, []core.Value{
core.Value("fou"), core.Value("one"), core.Value("thr"), core.Value("two"),
})
})
t.Run("rewrite dest", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("single key", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one", "two")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one", "two")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 2)
testx.AssertEqual(t, conn.Out(), "2")
be.Err(t, err, nil)
be.Equal(t, res, 2)
be.Equal(t, conn.Out(), "2")
items, _ := db.Set().Items("dest")
items, _ := red.Set().Items("dest")
sortValues(items)
testx.AssertEqual(t, items, []core.Value{core.Value("one"), core.Value("two")})
be.Equal(t, items, []core.Value{core.Value("one"), core.Value("two")})
})
t.Run("empty", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 0)
testx.AssertEqual(t, conn.Out(), "0")
be.Err(t, err, nil)
be.Equal(t, res, 0)
be.Equal(t, conn.Out(), "0")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value(nil))
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value(nil))
})
t.Run("source key not found", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_, _ = db.Set().Add("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_, _ = red.Set().Add("dest", "old")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("source key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_ = db.Str().Set("key3", "one")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_ = red.Str().Set("key3", "one")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2 key3")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
items, _ := db.Set().Items("dest")
testx.AssertEqual(t, items, []core.Value{core.Value("one")})
items, _ := red.Set().Items("dest")
be.Equal(t, items, []core.Value{core.Value("one")})
})
t.Run("dest key type mismatch", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_, _ = db.Set().Add("key1", "one")
_, _ = db.Set().Add("key2", "one")
_ = db.Str().Set("dest", "old")
red := getRedka(t)
_, _ = red.Set().Add("key1", "one")
_, _ = red.Set().Add("key2", "one")
_ = red.Str().Set("dest", "old")
cmd := redis.MustParse(ParseSUnionStore, "sunionstore dest key1 key2")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertErr(t, err, core.ErrKeyType)
testx.AssertEqual(t, res, nil)
testx.AssertEqual(t, conn.Out(), core.ErrKeyType.Error()+" (sunionstore)")
be.Err(t, err, core.ErrKeyType)
be.Equal(t, res, nil)
be.Equal(t, conn.Out(), core.ErrKeyType.Error()+" (sunionstore)")
sval, _ := db.Str().Get("dest")
testx.AssertEqual(t, sval, core.Value("old"))
sval, _ := red.Str().Get("dest")
be.Equal(t, sval, core.Value("old"))
})
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestDecrParse(t *testing.T) {
@@ -37,12 +37,12 @@ func TestDecrParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.delta, test.want.delta)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.delta, test.want.delta)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -54,33 +54,31 @@ func TestDecrExec(t *testing.T) {
}
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(parse, "decr age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, -1)
testx.AssertEqual(t, conn.Out(), "-1")
be.Err(t, err, nil)
be.Equal(t, res, -1)
be.Equal(t, conn.Out(), "-1")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), -1)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), -1)
})
t.Run("decr", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("age", "25")
red := getRedka(t)
_ = red.Str().Set("age", "25")
cmd := redis.MustParse(parse, "decr age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 24)
testx.AssertEqual(t, conn.Out(), "24")
be.Err(t, err, nil)
be.Equal(t, res, 24)
be.Equal(t, conn.Out(), "24")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 24)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 24)
})
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestDecrByParse(t *testing.T) {
@@ -37,12 +37,12 @@ func TestDecrByParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.delta, test.want.delta)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.delta, test.want.delta)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -54,33 +54,31 @@ func TestDecrByExec(t *testing.T) {
}
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(parse, "decrby age 12")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, -12)
testx.AssertEqual(t, conn.Out(), "-12")
be.Err(t, err, nil)
be.Equal(t, res, -12)
be.Equal(t, conn.Out(), "-12")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), -12)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), -12)
})
t.Run("decrby", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("age", "25")
red := getRedka(t)
_ = red.Str().Set("age", "25")
cmd := redis.MustParse(parse, "decrby age 12")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 13)
testx.AssertEqual(t, conn.Out(), "13")
be.Err(t, err, nil)
be.Equal(t, res, 13)
be.Equal(t, conn.Out(), "13")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 13)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 13)
})
}

View File

@@ -3,9 +3,9 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestGetParse(t *testing.T) {
@@ -34,21 +34,19 @@ func TestGetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseGet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want)
be.Equal(t, cmd.key, test.want)
} else {
testx.AssertEqual(t, cmd, Get{})
be.Equal(t, cmd, Get{})
}
})
}
}
func TestGetExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
tests := []struct {
cmd string
@@ -72,9 +70,9 @@ func TestGetExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseGet, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,9 +3,9 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestGetSetParse(t *testing.T) {
@@ -39,12 +39,12 @@ func TestGetSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseGetSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.value, test.want.value)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.value, test.want.value)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -52,34 +52,31 @@ func TestGetSetParse(t *testing.T) {
func TestGetSetExec(t *testing.T) {
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseGetSet, "getset name alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value(nil))
testx.AssertEqual(t, conn.Out(), "(nil)")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value(nil))
be.Equal(t, conn.Out(), "(nil)")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "alice")
})
t.Run("update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseGetSet, "getset name bob")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, core.Value("alice"))
testx.AssertEqual(t, conn.Out(), "alice")
be.Err(t, err, nil)
be.Equal(t, res.(core.Value), core.Value("alice"))
be.Equal(t, conn.Out(), "alice")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "bob")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "bob")
})
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestIncrParse(t *testing.T) {
@@ -37,12 +37,12 @@ func TestIncrParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.delta, test.want.delta)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.delta, test.want.delta)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -54,33 +54,31 @@ func TestIncrExec(t *testing.T) {
}
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(parse, "incr age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 1)
testx.AssertEqual(t, conn.Out(), "1")
be.Err(t, err, nil)
be.Equal(t, res, 1)
be.Equal(t, conn.Out(), "1")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 1)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 1)
})
t.Run("incr", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("age", "25")
red := getRedka(t)
_ = red.Str().Set("age", "25")
cmd := redis.MustParse(parse, "incr age")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 26)
testx.AssertEqual(t, conn.Out(), "26")
be.Err(t, err, nil)
be.Equal(t, res, 26)
be.Equal(t, conn.Out(), "26")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 26)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 26)
})
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestIncrByParse(t *testing.T) {
@@ -37,12 +37,12 @@ func TestIncrByParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.delta, test.want.delta)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.delta, test.want.delta)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -54,33 +54,31 @@ func TestIncrByExec(t *testing.T) {
}
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(parse, "incrby age 42")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 42)
testx.AssertEqual(t, conn.Out(), "42")
be.Err(t, err, nil)
be.Equal(t, res, 42)
be.Equal(t, conn.Out(), "42")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 42)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 42)
})
t.Run("incrby", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("age", "25")
red := getRedka(t)
_ = red.Str().Set("age", "25")
cmd := redis.MustParse(parse, "incrby age 42")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, 67)
testx.AssertEqual(t, conn.Out(), "67")
be.Err(t, err, nil)
be.Equal(t, res, 67)
be.Equal(t, conn.Out(), "67")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.MustInt(), 67)
age, _ := red.Str().Get("age")
be.Equal(t, age.MustInt(), 67)
})
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestIncrByFloatParse(t *testing.T) {
@@ -43,20 +43,19 @@ func TestIncrByFloatParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseIncrByFloat, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.delta, test.want.delta)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.delta, test.want.delta)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
}
func TestIncrByFloatExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
tests := []struct {
cmd string
@@ -87,15 +86,14 @@ func TestIncrByFloatExec(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
_ = db.Str().Set("age", 25)
_ = red.Str().Set("age", 25)
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseIncrByFloat, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,9 +3,9 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestMGetParse(t *testing.T) {
@@ -34,22 +34,21 @@ func TestMGetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseMGet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.keys, test.want)
be.Equal(t, cmd.keys, test.want)
} else {
testx.AssertEqual(t, cmd, MGet{})
be.Equal(t, cmd, MGet{})
}
})
}
}
func TestMGetExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 25)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 25)
tests := []struct {
cmd string
@@ -83,9 +82,9 @@ func TestMGetExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseMGet, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

View File

@@ -3,8 +3,8 @@ package string
import (
"testing"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestMSetParse(t *testing.T) {
@@ -46,11 +46,11 @@ func TestMSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseMSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.items, test.want.items)
be.Equal(t, cmd.items, test.want.items)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -58,73 +58,69 @@ func TestMSetParse(t *testing.T) {
func TestMSetExec(t *testing.T) {
t.Run("create single", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseMSet, "mset name alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "alice")
})
t.Run("create multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(ParseMSet, "mset name alice age 25")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "alice")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.String(), "25")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "alice")
age, _ := red.Str().Get("age")
be.Equal(t, age.String(), "25")
})
t.Run("create/update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("name", "alice")
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(ParseMSet, "mset name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "bob")
age, _ := red.Str().Get("age")
be.Equal(t, age.String(), "50")
})
t.Run("update multiple", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
_ = db.Str().Set("name", "alice")
_ = db.Str().Set("age", 25)
_ = red.Str().Set("name", "alice")
_ = red.Str().Set("age", 25)
cmd := redis.MustParse(ParseMSet, "mset name bob age 50")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "bob")
age, _ := db.Str().Get("age")
testx.AssertEqual(t, age.String(), "50")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "bob")
age, _ := red.Str().Get("age")
be.Equal(t, age.String(), "50")
})
}

View File

@@ -4,8 +4,8 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestPSetEXParse(t *testing.T) {
@@ -48,13 +48,13 @@ func TestPSetEXParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(parse, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.value, test.want.value)
testx.AssertEqual(t, cmd.ttl, test.want.ttl)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.value, test.want.value)
be.Equal(t, cmd.ttl, test.want.ttl)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
@@ -66,64 +66,59 @@ func TestPSetEXExec(t *testing.T) {
}
t.Run("create", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
cmd := redis.MustParse(parse, "psetex name 60000 alice")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
expireAt := time.Now().Add(60 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "alice")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "alice")
})
t.Run("update", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().Set("name", "alice")
red := getRedka(t)
_ = red.Str().Set("name", "alice")
cmd := redis.MustParse(parse, "psetex name 60000 bob")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
expireAt := time.Now().Add(60 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "bob")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "bob")
})
t.Run("change ttl", func(t *testing.T) {
db, red := getDB(t)
defer db.Close()
_ = db.Str().SetExpires("name", "alice", 60*time.Second)
red := getRedka(t)
_ = red.Str().SetExpires("name", "alice", 60*time.Second)
cmd := redis.MustParse(parse, "psetex name 10000 bob")
conn := redis.NewFakeConn()
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, true)
testx.AssertEqual(t, conn.Out(), "OK")
be.Err(t, err, nil)
be.Equal(t, res, true)
be.Equal(t, conn.Out(), "OK")
expireAt := time.Now().Add(10 * time.Second)
key, _ := db.Key().Get("name")
testx.AssertEqual(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
key, _ := red.Key().Get("name")
be.Equal(t, *key.ETime/1000, expireAt.UnixMilli()/1000)
name, _ := db.Str().Get("name")
testx.AssertEqual(t, name.String(), "bob")
name, _ := red.Str().Get("name")
be.Equal(t, name.String(), "bob")
})
}

View File

@@ -4,9 +4,9 @@ import (
"testing"
"time"
"github.com/nalgeon/be"
"github.com/nalgeon/redka/internal/core"
"github.com/nalgeon/redka/internal/redis"
"github.com/nalgeon/redka/internal/testx"
)
func TestSetParse(t *testing.T) {
@@ -123,23 +123,22 @@ func TestSetParse(t *testing.T) {
for _, test := range tests {
t.Run(test.cmd, func(t *testing.T) {
cmd, err := redis.Parse(ParseSet, test.cmd)
testx.AssertEqual(t, err, test.err)
be.Equal(t, err, test.err)
if err == nil {
testx.AssertEqual(t, cmd.key, test.want.key)
testx.AssertEqual(t, cmd.value, test.want.value)
testx.AssertEqual(t, cmd.ifNX, test.want.ifNX)
testx.AssertEqual(t, cmd.ifXX, test.want.ifXX)
testx.AssertEqual(t, cmd.ttl, test.want.ttl)
be.Equal(t, cmd.key, test.want.key)
be.Equal(t, cmd.value, test.want.value)
be.Equal(t, cmd.ifNX, test.want.ifNX)
be.Equal(t, cmd.ifXX, test.want.ifXX)
be.Equal(t, cmd.ttl, test.want.ttl)
} else {
testx.AssertEqual(t, cmd, test.want)
be.Equal(t, cmd, test.want)
}
})
}
}
func TestSetExec(t *testing.T) {
db, red := getDB(t)
defer db.Close()
red := getRedka(t)
tests := []struct {
cmd string
@@ -203,9 +202,9 @@ func TestSetExec(t *testing.T) {
conn := redis.NewFakeConn()
cmd := redis.MustParse(ParseSet, test.cmd)
res, err := cmd.Run(conn, red)
testx.AssertNoErr(t, err)
testx.AssertEqual(t, res, test.res)
testx.AssertEqual(t, conn.Out(), test.out)
be.Err(t, err, nil)
be.Equal(t, res, test.res)
be.Equal(t, conn.Out(), test.out)
})
}
}

Some files were not shown because too many files have changed in this diff Show More