add more image tests, generalize prep for those tests
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
// Package image handles storing, resizing and retrival of images
|
||||
// Package image handles storing, resizing and retrieval of images
|
||||
// Provides Interface with Save and Load and one implementation on top of local file system.
|
||||
package image
|
||||
|
||||
import (
|
||||
@@ -25,9 +26,9 @@ type Interface interface {
|
||||
|
||||
// FileSystem provides image Interface for local files. Saves and loads files from Location, restricts max size
|
||||
type FileSystem struct {
|
||||
Location string
|
||||
MaxSize int
|
||||
Partitons int
|
||||
Location string
|
||||
MaxSize int
|
||||
Partitions int
|
||||
|
||||
crc struct {
|
||||
*crc64.Table
|
||||
@@ -98,13 +99,13 @@ func (f *FileSystem) Load(id string) (io.ReadCloser, int64, error) {
|
||||
// in different subdirectories and avoid too many files in a single place.
|
||||
// the end result is a full path like this - /tmp/images/92. Number of partitions defined by FileSystem.Partitions
|
||||
func (f *FileSystem) location(id string) string {
|
||||
if f.Partitons == 0 {
|
||||
if f.Partitions == 0 {
|
||||
return f.Location
|
||||
}
|
||||
|
||||
f.crc.Do(func() {
|
||||
f.crc.Table = crc64.MakeTable(crc64.ECMA)
|
||||
p := int(math.Round(math.Log10(float64(f.Partitons))))
|
||||
p := int(math.Round(math.Log10(float64(f.Partitions))))
|
||||
f.crc.mask = "%0" + strconv.Itoa(p) + "d"
|
||||
f.crc.divider = uint64(math.Pow(10, float64(p)))
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ package image
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
@@ -13,57 +14,39 @@ import (
|
||||
)
|
||||
|
||||
func TestImage_Save(t *testing.T) {
|
||||
loc, err := ioutil.TempDir("", "test_image_r42")
|
||||
require.NoError(t, err, "failed to make temp dir")
|
||||
defer os.RemoveAll(loc)
|
||||
svc, teardown := prepareImageTest(t)
|
||||
defer teardown()
|
||||
|
||||
svc := FileSystem{
|
||||
Location: loc,
|
||||
Partitons: 100,
|
||||
MaxSize: 50,
|
||||
}
|
||||
id, err := svc.Save("blah_ff1.png", strings.NewReader("blah blah"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "fc77a87ad3c898b9603119711f99305145e272e103c904d85ee2deda.png", id)
|
||||
|
||||
dst := path.Join(loc, "56", id)
|
||||
dst := path.Join(svc.Location, "56", id)
|
||||
data, err := ioutil.ReadFile(dst)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "blah blah", string(data))
|
||||
}
|
||||
|
||||
func TestImage_SaveTooLarge(t *testing.T) {
|
||||
loc, err := ioutil.TempDir("", "test_image_r42")
|
||||
require.NoError(t, err, "failed to make temp dir")
|
||||
defer os.RemoveAll(loc)
|
||||
|
||||
svc := FileSystem{
|
||||
Location: loc,
|
||||
Partitons: 100,
|
||||
MaxSize: 5,
|
||||
}
|
||||
_, err = svc.Save("blah_ff1.png", strings.NewReader("blah blah"))
|
||||
svc, teardown := prepareImageTest(t)
|
||||
defer teardown()
|
||||
svc.MaxSize = 5
|
||||
_, err := svc.Save("blah_ff1.png", strings.NewReader("blah blah"))
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, "file blah_ff1.png is too large")
|
||||
}
|
||||
|
||||
func TestImage_Load(t *testing.T) {
|
||||
loc, err := ioutil.TempDir("", "test_image_r42")
|
||||
require.NoError(t, err, "failed to make temp dir")
|
||||
defer os.RemoveAll(loc)
|
||||
|
||||
// save image
|
||||
svc := FileSystem{
|
||||
Location: loc,
|
||||
Partitons: 100,
|
||||
MaxSize: 50,
|
||||
}
|
||||
svc, teardown := prepareImageTest(t)
|
||||
defer teardown()
|
||||
|
||||
id, err := svc.Save("blah_ff1.png", strings.NewReader("blah blah"))
|
||||
assert.NoError(t, err)
|
||||
|
||||
r, sz, err := svc.Load(id)
|
||||
assert.NoError(t, err)
|
||||
defer r.Close()
|
||||
defer func() { assert.NoError(t, r.Close()) }()
|
||||
data, err := ioutil.ReadAll(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "blah blah", string(data))
|
||||
@@ -83,12 +66,52 @@ func TestImage_location(t *testing.T) {
|
||||
{100, "12345", "/tmp/69"},
|
||||
{100, "xyzz", "/tmp/58"},
|
||||
{100, "6851dcde6024e03258a66705f29e14b506048c74.png", "/tmp/02"},
|
||||
{5, "6851dcde6024e03258a66705f29e14b506048c74.png", "/tmp/2"},
|
||||
{5, "xxxyz.png", "/tmp/0"},
|
||||
{0, "12345", "/tmp"},
|
||||
}
|
||||
for n, tt := range tbl {
|
||||
t.Run(strconv.Itoa(n), func(t *testing.T) {
|
||||
svc := FileSystem{Location: "/tmp", Partitons: tt.partitions}
|
||||
svc := FileSystem{Location: "/tmp", Partitions: tt.partitions}
|
||||
assert.Equal(t, tt.res, svc.location(tt.id))
|
||||
})
|
||||
}
|
||||
|
||||
// generate random names and make sure partition never runs out of allowed
|
||||
letterRunes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
randomString := func(n int) string {
|
||||
b := make([]rune, n)
|
||||
for i := range b {
|
||||
b[i] = letterRunes[rand.Intn(len(letterRunes))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
svc := FileSystem{Location: "/tmp", Partitions: 10}
|
||||
for i := 0; i < 1000; i++ {
|
||||
v := randomString(rand.Intn(64))
|
||||
parts := strings.Split(svc.location(v), "/")
|
||||
p, err := strconv.Atoi(parts[len(parts)-1])
|
||||
require.NoError(t, err)
|
||||
assert.True(t, p >= 0 && p < 10)
|
||||
}
|
||||
}
|
||||
|
||||
func prepareImageTest(t *testing.T) (svc FileSystem, teardown func()) {
|
||||
loc, err := ioutil.TempDir("", "test_image_r42")
|
||||
require.NoError(t, err, "failed to make temp dir")
|
||||
|
||||
svc = FileSystem{
|
||||
Location: loc,
|
||||
Partitions: 100,
|
||||
MaxSize: 50,
|
||||
}
|
||||
|
||||
teardown = func() {
|
||||
defer func() {
|
||||
assert.NoError(t, os.RemoveAll(loc))
|
||||
}()
|
||||
}
|
||||
|
||||
return svc, teardown
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user