mirror of
https://github.com/jimeh/ozu.io.git
synced 2026-02-19 08:06:39 +00:00
163 lines
3.0 KiB
Go
163 lines
3.0 KiB
Go
package shortner
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/jimeh/ozu.io/storage"
|
|
"github.com/stretchr/testify/suite"
|
|
)
|
|
|
|
// Test Cases
|
|
|
|
var shortenExamples = []struct {
|
|
uid string
|
|
url string
|
|
normalized string
|
|
}{
|
|
{uid: "ig", url: "google.com", normalized: "http://google.com/"},
|
|
{uid: "ih", url: "https://google.com", normalized: "https://google.com/"},
|
|
{uid: "ig", url: "http://google.com", normalized: "http://google.com/"},
|
|
{uid: "ih", url: "https://google.com/"},
|
|
{uid: "ig", url: "google.com/", normalized: "http://google.com/"},
|
|
{uid: "ii", url: "https://github.com/"},
|
|
{uid: "ij", url: "https://gist.github.com/"},
|
|
}
|
|
|
|
// Mocks
|
|
|
|
func NewMockStore() *MockStore {
|
|
return &MockStore{
|
|
Data: map[string][]byte{},
|
|
Sequence: 1000,
|
|
}
|
|
}
|
|
|
|
type MockStore struct {
|
|
sync.RWMutex
|
|
Data map[string][]byte
|
|
Sequence int
|
|
}
|
|
|
|
func (s *MockStore) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (s *MockStore) Get(key []byte) ([]byte, error) {
|
|
s.RLock()
|
|
defer s.RUnlock()
|
|
value := s.Data[string(key)]
|
|
if value == nil {
|
|
return nil, errors.New("not found")
|
|
}
|
|
return value, nil
|
|
}
|
|
|
|
func (s *MockStore) Set(key []byte, value []byte) error {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
s.Data[string(key)] = value
|
|
return nil
|
|
}
|
|
|
|
func (s *MockStore) Delete(key []byte) error {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
delete(s.Data, string(key))
|
|
return nil
|
|
}
|
|
|
|
func (s *MockStore) NextSequence() (int, error) {
|
|
s.Lock()
|
|
defer s.Unlock()
|
|
s.Sequence++
|
|
return s.Sequence, nil
|
|
}
|
|
|
|
// Setup Suite
|
|
|
|
type ShortnerSuite struct {
|
|
suite.Suite
|
|
shortner *Shortner
|
|
store storage.Store
|
|
}
|
|
|
|
func (s *ShortnerSuite) SetupTest() {
|
|
s.store = NewMockStore()
|
|
s.shortner = New(s.store)
|
|
}
|
|
|
|
func (s *ShortnerSuite) Seed() {
|
|
r := s.Require()
|
|
|
|
for _, e := range shortenExamples {
|
|
uid, url, err := s.shortner.Shorten([]byte(e.url))
|
|
r.Equal([]byte(e.uid), uid)
|
|
if e.normalized != "" {
|
|
r.Equal([]byte(e.normalized), url)
|
|
} else {
|
|
r.Equal([]byte(e.url), url)
|
|
}
|
|
r.NoError(err)
|
|
}
|
|
}
|
|
|
|
// Tests
|
|
|
|
func (s *ShortnerSuite) TestShorten() {
|
|
for _, e := range shortenExamples {
|
|
uid, url, err := s.shortner.Shorten([]byte(e.url))
|
|
s.Equal(nil, err)
|
|
s.Equal([]byte(e.uid), uid)
|
|
if e.normalized != "" {
|
|
s.Equal([]byte(e.normalized), url)
|
|
} else {
|
|
s.Equal([]byte(e.url), url)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *ShortnerSuite) TestLookup() {
|
|
s.Seed()
|
|
|
|
for _, e := range shortenExamples {
|
|
url, err := s.shortner.Lookup([]byte(e.uid))
|
|
s.NoError(err)
|
|
|
|
if e.normalized != "" {
|
|
s.Equal([]byte(e.normalized), url)
|
|
} else {
|
|
s.Equal([]byte(e.url), url)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run Suite
|
|
|
|
func TestShortnerSuite(t *testing.T) {
|
|
suite.Run(t, new(ShortnerSuite))
|
|
}
|
|
|
|
// Benchmarks
|
|
|
|
func BenchmarkShorten(b *testing.B) {
|
|
shortner := New(NewMockStore())
|
|
rawURL := []byte("https://google.com/")
|
|
|
|
for n := 0; n < b.N; n++ {
|
|
_, _, _ = shortner.Shorten(append(rawURL, strconv.Itoa(n)...))
|
|
}
|
|
}
|
|
|
|
func BenchmarkLookup(b *testing.B) {
|
|
shortner := New(NewMockStore())
|
|
rawURL := []byte("https://google.com/")
|
|
uid, _, _ := shortner.Shorten(rawURL)
|
|
|
|
for n := 0; n < b.N; n++ {
|
|
_, _ = shortner.Lookup(uid)
|
|
}
|
|
}
|