mirror of
https://github.com/gofiber/storage.git
synced 2025-10-05 00:33:03 +08:00
feat: add mockstorage
This commit is contained in:
28
.github/workflows/test-mockstorage.yml
vendored
Normal file
28
.github/workflows/test-mockstorage.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'mockstorage/**'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'mockstorage/**'
|
||||||
|
name: "Tests Local Storage"
|
||||||
|
jobs:
|
||||||
|
Tests:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version:
|
||||||
|
- 1.21.x
|
||||||
|
- 1.22.x
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Fetch Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '${{ matrix.go-version }}'
|
||||||
|
- name: Test Mockstorage
|
||||||
|
run: cd ./mockstorage && go test ./... -v -race
|
131
mockstorage/README.md
Normal file
131
mockstorage/README.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
---
|
||||||
|
id: memory
|
||||||
|
title: Memory
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
[](https://gofiber.io/discord)
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
A mock storage implementation for Fiber. This storage is not persistent and is only used for testing purposes.
|
||||||
|
|
||||||
|
**Note: Requires Go 1.21 and above**
|
||||||
|
|
||||||
|
### Table of Contents
|
||||||
|
- [Signatures](#signatures)
|
||||||
|
- [Installation](#installation)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Config](#config)
|
||||||
|
- [Default Config](#default-config)
|
||||||
|
|
||||||
|
|
||||||
|
### Signatures
|
||||||
|
```go
|
||||||
|
func New(config ...Config) *Storage
|
||||||
|
func (s *Storage) Get(key string) ([]byte, error)
|
||||||
|
func (s *Storage) Set(key string, val []byte, exp time.Duration) error
|
||||||
|
func (s *Storage) Delete(key string) error
|
||||||
|
func (s *Storage) Reset() error
|
||||||
|
func (s *Storage) Close() error
|
||||||
|
func (s *Storage) Conn() map[string]entry
|
||||||
|
func (s *Storage) Keys() ([][]byte, error)
|
||||||
|
|
||||||
|
func SetCustomFuncs(custom *CustomFuncs)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
Mockstorage is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet:
|
||||||
|
```bash
|
||||||
|
go mod init github.com/<user>/<repo>
|
||||||
|
```
|
||||||
|
And then install the mockstorage implementation:
|
||||||
|
```bash
|
||||||
|
go get github.com/gofiber/storage/mockstorage
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
Import the storage package.
|
||||||
|
```go
|
||||||
|
import "github.com/gofiber/storage/mockstorage"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the following possibilities to create a storage:
|
||||||
|
```go
|
||||||
|
// Initialize default config
|
||||||
|
store := mockstorage.New()
|
||||||
|
|
||||||
|
// Initialize custom config
|
||||||
|
store := mockstorage.New(mockstorage.Config{
|
||||||
|
CustomFuncs: &mockstorage.CustomFuncs{
|
||||||
|
&CustomFuncs{
|
||||||
|
GetFunc: func(key string) ([]byte, error) {
|
||||||
|
if key == "customKey" {
|
||||||
|
return []byte("customValue"), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("custom key not found")
|
||||||
|
},
|
||||||
|
SetFunc: func(key string, val []byte, exp time.Duration) error {
|
||||||
|
if key == "readonly" {
|
||||||
|
return errors.New("cannot set readonly key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
DeleteFunc: func(key string) error {
|
||||||
|
if key == "protectedKey" {
|
||||||
|
return errors.New("cannot delete protected key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set custom functions after initialization
|
||||||
|
store.SetCustomFuncs(&mockstorage.CustomFuncs{
|
||||||
|
GetFunc: func(key string) ([]byte, error) {
|
||||||
|
if key == "customKey" {
|
||||||
|
return []byte("customValue"), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("custom key not found")
|
||||||
|
},
|
||||||
|
SetFunc: func(key string, val []byte, exp time.Duration) error {
|
||||||
|
if key == "readonly" {
|
||||||
|
return errors.New("cannot set readonly key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
DeleteFunc: func(key string) error {
|
||||||
|
if key == "protectedKey" {
|
||||||
|
return errors.New("cannot delete protected key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
// ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Config
|
||||||
|
```go
|
||||||
|
type Config struct {
|
||||||
|
CustomFuncs *CustomFuncs
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Default Config
|
||||||
|
```go
|
||||||
|
var ConfigDefault = Config{
|
||||||
|
CustomFuncs: &CustomFuncs{
|
||||||
|
GetFunc: nil,
|
||||||
|
SetFunc: nil,
|
||||||
|
DeleteFunc: nil,
|
||||||
|
ResetFunc: nil,
|
||||||
|
CloseFunc: nil,
|
||||||
|
ConnFunc: nil,
|
||||||
|
KeysFunc: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
3
mockstorage/go.mod
Normal file
3
mockstorage/go.mod
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module mockstorage
|
||||||
|
|
||||||
|
go 1.21
|
0
mockstorage/go.sum
Normal file
0
mockstorage/go.sum
Normal file
170
mockstorage/mockstorage.go
Normal file
170
mockstorage/mockstorage.go
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
package mockstorage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config defines the config for mock storage.
|
||||||
|
type Config struct {
|
||||||
|
CustomFuncs *CustomFuncs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage is the mock storage adapter.
|
||||||
|
type Storage struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
data map[string]entry
|
||||||
|
custom *CustomFuncs
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry struct to hold value and expiration time.
|
||||||
|
type entry struct {
|
||||||
|
value []byte
|
||||||
|
exp time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomFuncs allows injecting custom behaviors for testing.
|
||||||
|
type CustomFuncs struct {
|
||||||
|
GetFunc func(key string) ([]byte, error)
|
||||||
|
SetFunc func(key string, val []byte, exp time.Duration) error
|
||||||
|
DeleteFunc func(key string) error
|
||||||
|
ResetFunc func() error
|
||||||
|
CloseFunc func() error
|
||||||
|
ConnFunc func() map[string]entry
|
||||||
|
KeysFunc func() ([][]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new mock storage with optional configuration.
|
||||||
|
func New(config ...Config) *Storage {
|
||||||
|
s := &Storage{
|
||||||
|
data: make(map[string]entry),
|
||||||
|
custom: &CustomFuncs{
|
||||||
|
GetFunc: nil,
|
||||||
|
SetFunc: nil,
|
||||||
|
DeleteFunc: nil,
|
||||||
|
ResetFunc: nil,
|
||||||
|
CloseFunc: nil,
|
||||||
|
ConnFunc: nil,
|
||||||
|
KeysFunc: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a config is provided and it has CustomFuncs, use them
|
||||||
|
if len(config) > 0 && config[0].CustomFuncs != nil {
|
||||||
|
s.custom = config[0].CustomFuncs
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get retrieves the value for a given key.
|
||||||
|
func (s *Storage) Get(key string) ([]byte, error) {
|
||||||
|
if s.custom.GetFunc != nil {
|
||||||
|
return s.custom.GetFunc(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
|
||||||
|
e, ok := s.data[key]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("key not found")
|
||||||
|
}
|
||||||
|
if !e.exp.IsZero() && time.Now().After(e.exp) {
|
||||||
|
delete(s.data, key)
|
||||||
|
return nil, errors.New("key expired")
|
||||||
|
}
|
||||||
|
return e.value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the value for a given key with an expiration time.
|
||||||
|
func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
|
||||||
|
if s.custom.SetFunc != nil {
|
||||||
|
return s.custom.SetFunc(key, val, exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
var expTime time.Time
|
||||||
|
if exp > 0 {
|
||||||
|
expTime = time.Now().Add(exp)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.data[key] = entry{value: val, exp: expTime}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes a key from the storage.
|
||||||
|
func (s *Storage) Delete(key string) error {
|
||||||
|
if s.custom.DeleteFunc != nil {
|
||||||
|
return s.custom.DeleteFunc(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
delete(s.data, key)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset clears all keys from the storage.
|
||||||
|
func (s *Storage) Reset() error {
|
||||||
|
if s.custom.ResetFunc != nil {
|
||||||
|
return s.custom.ResetFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
s.data = make(map[string]entry)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the storage (no-op for mock).
|
||||||
|
func (s *Storage) Close() error {
|
||||||
|
if s.custom.CloseFunc != nil {
|
||||||
|
return s.custom.CloseFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// No resources to clean up in mock
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conn returns the internal data map (for testing purposes).
|
||||||
|
func (s *Storage) Conn() map[string]entry {
|
||||||
|
if s.custom.ConnFunc != nil {
|
||||||
|
return s.custom.ConnFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
|
||||||
|
copyData := make(map[string]entry)
|
||||||
|
for k, v := range s.data {
|
||||||
|
copyData[k] = v
|
||||||
|
}
|
||||||
|
return copyData
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns all keys in the storage.
|
||||||
|
func (s *Storage) Keys() ([][]byte, error) {
|
||||||
|
if s.custom.KeysFunc != nil {
|
||||||
|
return s.custom.KeysFunc()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.mu.RLock()
|
||||||
|
defer s.mu.RUnlock()
|
||||||
|
|
||||||
|
keys := make([][]byte, 0, len(s.data))
|
||||||
|
for k := range s.data {
|
||||||
|
keys = append(keys, []byte(k))
|
||||||
|
}
|
||||||
|
return keys, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCustomFuncs allows setting custom function implementations.
|
||||||
|
func (s *Storage) SetCustomFuncs(custom *CustomFuncs) {
|
||||||
|
s.custom = custom
|
||||||
|
}
|
276
mockstorage/mockstorage_test.go
Normal file
276
mockstorage/mockstorage_test.go
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
package mockstorage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStorageDefaultBehavior(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
// Test Set and Get
|
||||||
|
err := store.Set("key1", []byte("value1"), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := store.Get("key1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(val, []byte("value1")) {
|
||||||
|
t.Errorf("Get() = %v, want %v", val, []byte("value1"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Delete
|
||||||
|
err = store.Delete("key1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Delete() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = store.Get("key1")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Get() error = %v, wantErr %v", err, "key not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Reset
|
||||||
|
err = store.Set("key2", []byte("value2"), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.Reset()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Reset() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = store.Get("key2")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Get() error = %v, wantErr %v", err, "key not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Expiry
|
||||||
|
err = store.Set("key3", []byte("value3"), time.Millisecond*100)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 200)
|
||||||
|
|
||||||
|
_, err = store.Get("key3")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Get() error = %v, wantErr %v", err, "key expired")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStorageConnFunc(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
customFuncs := &CustomFuncs{
|
||||||
|
ConnFunc: func() map[string]entry {
|
||||||
|
return map[string]entry{
|
||||||
|
"customKey1": {value: []byte("customValue1"), exp: time.Time{}},
|
||||||
|
"customKey2": {value: []byte("customValue2"), exp: time.Now().Add(1 * time.Hour)},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
store.SetCustomFuncs(customFuncs)
|
||||||
|
|
||||||
|
// Test custom Conn
|
||||||
|
conn := store.Conn()
|
||||||
|
expectedConn := map[string]entry{
|
||||||
|
"customKey1": {value: []byte("customValue1"), exp: time.Time{}},
|
||||||
|
"customKey2": {value: []byte("customValue2"), exp: time.Now().Add(1 * time.Hour)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range expectedConn {
|
||||||
|
if val, ok := conn[k]; !ok || !bytes.Equal(val.value, v.value) {
|
||||||
|
t.Errorf("Conn() = %v, want %v", conn, expectedConn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResetFunc(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
customFuncs := &CustomFuncs{
|
||||||
|
ResetFunc: func() error {
|
||||||
|
return errors.New("reset error")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
store.SetCustomFuncs(customFuncs)
|
||||||
|
|
||||||
|
err := store.Reset()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Reset() error = %v, wantErr %v", err, "reset error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStorageCloseFunc(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
customFuncs := &CustomFuncs{
|
||||||
|
CloseFunc: func() error {
|
||||||
|
return errors.New("close error")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
store.SetCustomFuncs(customFuncs)
|
||||||
|
|
||||||
|
err := store.Close()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Close() error = %v, wantErr %v", err, "close error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStorageKeysFunc(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
customFuncs := &CustomFuncs{
|
||||||
|
KeysFunc: func() ([][]byte, error) {
|
||||||
|
return [][]byte{[]byte("customKey1"), []byte("customKey2")}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
store.SetCustomFuncs(customFuncs)
|
||||||
|
|
||||||
|
// Test custom Keys
|
||||||
|
keys, err := store.Keys()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Keys() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
expectedKeys := [][]byte{[]byte("customKey1"), []byte("customKey2")}
|
||||||
|
if len(keys) != len(expectedKeys) {
|
||||||
|
t.Fatalf("Keys() = %v, want %v", keys, expectedKeys)
|
||||||
|
}
|
||||||
|
for i, key := range expectedKeys {
|
||||||
|
if !bytes.Equal(keys[i], key) {
|
||||||
|
t.Errorf("Keys() = %v, want %v", keys, expectedKeys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStorageCustomBehavior(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
customFuncs := &CustomFuncs{
|
||||||
|
GetFunc: func(key string) ([]byte, error) {
|
||||||
|
if key == "customKey" {
|
||||||
|
return []byte("customValue"), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("custom key not found")
|
||||||
|
},
|
||||||
|
SetFunc: func(key string, val []byte, exp time.Duration) error {
|
||||||
|
if key == "readonly" {
|
||||||
|
return errors.New("cannot set readonly key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
DeleteFunc: func(key string) error {
|
||||||
|
if key == "protectedKey" {
|
||||||
|
return errors.New("cannot delete protected key")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
ConnFunc: func() map[string]entry {
|
||||||
|
return map[string]entry{
|
||||||
|
"customKey1": {value: []byte("customValue1"), exp: time.Time{}},
|
||||||
|
"customKey2": {value: []byte("customValue2"), exp: time.Now().Add(1 * time.Hour)},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
KeysFunc: func() ([][]byte, error) {
|
||||||
|
return [][]byte{[]byte("customKey1"), []byte("customKey2")}, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
store.SetCustomFuncs(customFuncs)
|
||||||
|
|
||||||
|
// Test custom Get
|
||||||
|
val, err := store.Get("customKey")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Get() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(val, []byte("customValue")) {
|
||||||
|
t.Errorf("Get() = %v, want %v", val, []byte("customValue"))
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = store.Get("unknownKey")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Get() error = %v, wantErr %v", err, "custom key not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test custom Set
|
||||||
|
err = store.Set("readonly", []byte("value"), 0)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Set() error = %v, wantErr %v", err, "cannot set readonly key")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.Set("regularKey", []byte("value"), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test custom Delete
|
||||||
|
err = store.Delete("protectedKey")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Delete() error = %v, wantErr %v", err, "cannot delete protected key")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = store.Delete("regularKey")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Delete() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test custom Conn
|
||||||
|
conn := store.Conn()
|
||||||
|
expectedConn := map[string]entry{
|
||||||
|
"customKey1": {value: []byte("customValue1"), exp: time.Time{}},
|
||||||
|
"customKey2": {value: []byte("customValue2"), exp: time.Now().Add(1 * time.Hour)},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range expectedConn {
|
||||||
|
if val, ok := conn[k]; !ok || !bytes.Equal(val.value, v.value) {
|
||||||
|
t.Errorf("Conn() = %v, want %v", conn, expectedConn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test custom Keys
|
||||||
|
keys, err := store.Keys()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Keys() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
expectedKeys := [][]byte{[]byte("customKey1"), []byte("customKey2")}
|
||||||
|
if len(keys) != len(expectedKeys) {
|
||||||
|
t.Fatalf("Keys() = %v, want %v", keys, expectedKeys)
|
||||||
|
}
|
||||||
|
for i, key := range expectedKeys {
|
||||||
|
if !bytes.Equal(keys[i], key) {
|
||||||
|
t.Errorf("Keys() = %v, want %v", keys, expectedKeys)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStorageConnAndKeys(t *testing.T) {
|
||||||
|
store := New()
|
||||||
|
|
||||||
|
// Test Conn
|
||||||
|
err := store.Set("key1", []byte("value1"), 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
conn := store.Conn()
|
||||||
|
if val, ok := conn["key1"]; !ok || !bytes.Equal(val.value, []byte("value1")) {
|
||||||
|
t.Errorf("Conn() = %v, want %v", conn, map[string]entry{"key1": {value: []byte("value1"), exp: time.Time{}}})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test Keys
|
||||||
|
keys, err := store.Keys()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Keys() error = %v, wantErr %v", err, nil)
|
||||||
|
}
|
||||||
|
if len(keys) != 1 || !bytes.Equal(keys[0], []byte("key1")) {
|
||||||
|
t.Errorf("Keys() = %v, want %v", keys, [][]byte{[]byte("key1")})
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user