Esempio n. 1
0
func TestDiskPaths(t *testing.T) {
	t.Parallel()
	idx := &types.ObjectIndex{
		ObjID: types.NewObjectID("1.2", "/somewhere2"),
		Part:  33,
	}

	diskPath := "/some/path"
	disk := &Disk{path: diskPath}

	hash := idx.ObjID.StrHash()
	expectedHash := "052fb8b15a7737b1e7b70546b1c5023f0bd00a7d"
	if hash != expectedHash {
		t.Errorf("Incorrect ObjectID hash. Exected %s, got %s", expectedHash, hash)
	}

	objIDPath := disk.getObjectIDPath(idx.ObjID)
	expectedObjIDPath := filepath.Join(diskPath, idx.ObjID.CacheKey(), expectedHash[:2], expectedHash[2:4], expectedHash)
	if objIDPath != expectedObjIDPath {
		t.Errorf("Incorrect ObjectID path. Exected %s, got %s", expectedObjIDPath, objIDPath)
	}

	objIdxPath := disk.getObjectIndexPath(idx)
	expectedObjIdxPath := filepath.Join(expectedObjIDPath, "000033")
	if objIdxPath != expectedObjIdxPath {
		t.Errorf("Incorrect ObjectIndex path. Exected %s, got %s", expectedObjIdxPath, objIdxPath)
	}

	objMetadataPath := disk.getObjectMetadataPath(idx.ObjID)
	expectedObjMetadataPath := filepath.Join(expectedObjIDPath, objectMetadataFileName)
	if objMetadataPath != expectedObjMetadataPath {
		t.Errorf("Incorrect ObjectMetadata path. Exected %s, got %s", expectedObjMetadataPath, objMetadataPath)
	}
}
Esempio n. 2
0
func getFullLruCache(t *testing.T) *TieredLRUCache {
	cz := getCacheZone()
	lru := New(cz, mockRemove, mock.NewLogger())

	storateObjects := (cz.StorageObjects / uint64(cacheTiers)) * uint64(cacheTiers)

	for i := uint64(0); i < storateObjects; i++ {

		oi := &types.ObjectIndex{
			Part:  uint32(i),
			ObjID: types.NewObjectID("1.1", "/path/to/many/objects"),
		}

		for k := 0; k < cacheTiers; k++ {
			lru.PromoteObject(oi)
		}
	}

	if objects := lru.Stats().Objects(); objects != storateObjects {
		t.Errorf("The cache was not full. Expected %d objects but it had %d",
			storateObjects, objects)
	}

	return lru
}
Esempio n. 3
0
func TestPromotionToTheFrontOfTheList(t *testing.T) {
	t.Parallel()
	lru := getFullLruCache(t)

	testOiFirst := &types.ObjectIndex{
		Part:  0,
		ObjID: types.NewObjectID("1.1", "/path/to/tested/object"),
	}

	testOiSecond := &types.ObjectIndex{
		Part:  1,
		ObjID: types.NewObjectID("1.1", "/path/to/tested/object"),
	}

	for currentTier := cacheTiers - 1; currentTier >= 0; currentTier-- {
		lru.PromoteObject(testOiFirst)
		lru.PromoteObject(testOiSecond)
	}

	// First promoting the first object to the front of the list
	lru.PromoteObject(testOiFirst)

	lruEl, ok := lru.lookup[testOiFirst.Hash()]

	if !ok {
		t.Fatal("Recently added object was not in the lookup table")
	}

	if lru.tiers[0].Front() != lruEl.ListElem {
		t.Error("The expected element was not at the front of the top list")
	}

	// Then promoting the second one
	lru.PromoteObject(testOiSecond)

	lruEl, ok = lru.lookup[testOiSecond.Hash()]

	if !ok {
		t.Fatal("Recently added object was not in the lookup table")
	}

	if lru.tiers[0].Front() != lruEl.ListElem {
		t.Error("The expected element was not at the front of the top list")
	}
}
func TestDiskReload(t *testing.T) {
	t.Parallel()
	tempDir, cleanup := testutils.GetTestFolder(t)
	defer cleanup()

	app, err := New(types.AppVersion{}, getConfigGetter(tempDir))
	if err != nil {
		t.Fatalf("Could not create an application: %s", err)
	}

	stor, err := disk.New(app.cfg.CacheZones["default"], mock.NewLogger())
	if err != nil {
		t.Fatalf("Could not initialize a storage: %s", err)
	}

	objIDNew := types.NewObjectID("key", "new")
	objIDOld := types.NewObjectID("key", "old")
	testutils.ShouldntFail(t,
		stor.SaveMetadata(&types.ObjectMetadata{ID: objIDNew, ExpiresAt: time.Now().Unix() + 600}),
		stor.SaveMetadata(&types.ObjectMetadata{ID: objIDOld, ExpiresAt: time.Now().Unix() - 600}),
		stor.SavePart(&types.ObjectIndex{ObjID: objIDNew, Part: 0}, strings.NewReader("test1-1")),
		stor.SavePart(&types.ObjectIndex{ObjID: objIDNew, Part: 1}, strings.NewReader("test1-2")),
		stor.SavePart(&types.ObjectIndex{ObjID: objIDOld, Part: 0}, strings.NewReader("test2-1")),
	)

	if err := app.initFromConfig(); err != nil {
		t.Fatalf("Could not init from config: %s", err)
	}
	defer app.ctxCancel()
	time.Sleep(1 * time.Second)

	const expectedObjects = 2
	cacheObjects := app.cacheZones["default"].Algorithm.Stats().Objects()
	if cacheObjects != expectedObjects {
		t.Errorf("Expected object count in cache to be %d but it was %d", expectedObjects, cacheObjects)
	}
}
Esempio n. 5
0
func TestResizeUp(t *testing.T) {
	t.Parallel()

	lru := getFullLruCache(t)

	testOi := &types.ObjectIndex{
		Part:  0,
		ObjID: types.NewObjectID("1.1", "/path/to/tested/object"),
	}
	oldSize := lru.Stats().Objects()
	lru.ChangeConfig(10, 50, oldSize+20, lru.logger)
	lru.PromoteObject(testOi)
	if lru.Stats().Objects() != oldSize+1 {
		t.Errorf("It was expected that after resize more objects could be added but that wasn't true")
	}
}
Esempio n. 6
0
func TestBreakInIndexes(t *testing.T) {
	t.Parallel()
	id := types.NewObjectID("test", "mest")
	for index, test := range breakInIndexesMatrix {
		var result = BreakInIndexes(id, test.start, test.end, test.partSize)
		if len(result) != len(test.result) {
			t.Errorf("Wrong len (%d != %d) on test index %d", len(result), len(test.result), index)
		}

		for resultIndex, value := range result {
			if value.Part != test.result[resultIndex] {
				t.Errorf("Wrong part for test index %d, wanted %d in position %d but got %d", index, test.result[resultIndex], resultIndex, value.Part)
			}
		}
	}
}
Esempio n. 7
0
func fillCache(t testing.TB, lru *TieredLRUCache) {
	storateObjects := (lru.cfg.StorageObjects / uint64(cacheTiers)) * uint64(cacheTiers)
	for i := uint64(0); i < storateObjects; i++ {

		oi := &types.ObjectIndex{
			Part:  uint32(i),
			ObjID: types.NewObjectID("1.1", "/path/to/many/objects"),
		}

		for k := uint64(0); k < cacheTiers-(i/(storateObjects/cacheTiers)); k++ {
			lru.PromoteObject(oi)
		}
	}

	if objects := lru.Stats().Objects(); objects != storateObjects {
		t.Errorf("The cache was not full. Expected %d objects but it had %d",
			storateObjects, objects)
	}
}
Esempio n. 8
0
func TestResizeDown(t *testing.T) {
	t.Parallel()
	lru := getFullLruCache(t)
	oldSize := lru.Stats().Objects()
	lru.ChangeConfig(1, 1, oldSize/2, lru.logger)
	var ch = make(chan struct{})
	var wg sync.WaitGroup
	for i := 0; 30 > i; i++ {
		wg.Add(1)
		go func(i int) {
			defer wg.Done()
			oi := &types.ObjectIndex{Part: uint32(i), ObjID: types.NewObjectID("1.1", "/path/to/some")}
			timer := time.NewTimer(time.Millisecond)

			for {
				select {
				case <-ch:
					return
				default:
					timer.Reset(time.Millisecond)
					<-timer.C
					lru.PromoteObject(oi)
				}
			}
		}(i)
	}
	var testSize = func() {
		if oldSize/2 < lru.Stats().Objects() {
			t.Errorf("It was expected that after resize down the size will be less than or equal to %d but it's %d",
				oldSize/2, lru.Stats().Objects())
		}
	}

	testSize()

	time.Sleep(50 * time.Millisecond) // give time for the Resize down to remove objects
	close(ch)
	wg.Wait()

	testSize()
}
Esempio n. 9
0
func TestPromotionInFullCache(t *testing.T) {
	t.Parallel()

	lru := getFullLruCache(t)

	testOi := &types.ObjectIndex{
		Part:  0,
		ObjID: types.NewObjectID("1.1", "/path/to/tested/object"),
	}

	for currentTier := cacheTiers - 1; currentTier >= 0; currentTier-- {
		lru.PromoteObject(testOi)
		lruEl, ok := lru.lookup[testOi.Hash()]
		if !ok {
			t.Fatalf("Lost object while promoting it to tier %d", currentTier)
		}

		if lruEl.ListTier != currentTier {
			t.Errorf("Tested LRU was not in the expected tier. It was suppsed to be"+
				" in tier %d but it was in %d", currentTier, lruEl.ListTier)
		}
	}
}
Esempio n. 10
0
func TestSize(t *testing.T) {
	t.Parallel()
	cz := getCacheZone()
	oi := getObjectIndex()
	lru := New(cz, nil, mock.NewLogger())

	if err := lru.AddObject(oi); err != nil {
		t.Errorf("Error adding object into the cache. %s", err)
	}

	if objects := lru.Stats().Objects(); objects != 1 {
		t.Errorf("Expec 1 object but found %d", objects)
	}

	if err := lru.AddObject(oi); err == nil {
		t.Error("Exepected error when adding object for the second time")
	}

	for i := 0; i < 16; i++ {
		oii := &types.ObjectIndex{
			Part:  uint32(i),
			ObjID: types.NewObjectID("1.1", "/path/to/other/object"),
		}

		if err := lru.AddObject(oii); err != nil {
			t.Errorf("Adding object in cache. %s", err)
		}
	}

	if objects := lru.Stats().Objects(); objects != 17 {
		t.Errorf("Expec 17 objects but found %d", objects)
	}

	if size, expected := lru.ConsumedSize(), 17*cz.PartSize; size != expected {
		t.Errorf("Expected total size to be %d but it was %d", expected, size)
	}
}
Esempio n. 11
0
func getObjectIndex() *types.ObjectIndex {
	return &types.ObjectIndex{
		Part:  3,
		ObjID: types.NewObjectID("1.1", "/path"),
	}
}
Esempio n. 12
0
package mock

import (
	"errors"
	"testing"

	"github.com/ironsmile/nedomi/types"
)

var idx = &types.ObjectIndex{
	ObjID: types.NewObjectID("test", "/path/to/object"),
	Part:  14,
}

var _ types.CacheAlgorithm = new(CacheAlgorithm) // make sure the mock implements the interface

func TestMockCacheAlgorithm(t *testing.T) {
	t.Parallel()
	d := NewCacheAlgorithm(nil)
	if d.Defaults.Lookup(idx) || d.Defaults.ShouldKeep(idx) || d.Defaults.AddObject(idx) != nil {
		t.Errorf("Invalid default default replies %#v", d.Defaults)
	}

	c1 := NewCacheAlgorithm(&CacheAlgorithmRepliers{
		Lookup: func(*types.ObjectIndex) bool { return true },
	})
	if !c1.Defaults.Lookup(idx) || c1.Defaults.ShouldKeep(idx) || c1.Defaults.AddObject(idx) != nil {
		t.Error("Invalid partial custom default replies")
	}

	promoted := false
func getObjectIndexFor(part uint32, key, path string) *types.ObjectIndex {
	return &types.ObjectIndex{
		ObjID: types.NewObjectID(key, path),
		Part:  part,
	}
}
Esempio n. 14
0
	"os"
	"testing"
	"time"

	"github.com/ironsmile/nedomi/mock"
	"github.com/ironsmile/nedomi/types"
	"github.com/ironsmile/nedomi/utils"
	"github.com/ironsmile/nedomi/utils/httputils"
)

const (
	input     = "The input of the test"
	inputSize = uint64(len(input))
)

var oid = types.NewObjectID("testKey1", "testPathA")

var oMeta = &types.ObjectMetadata{
	ID:                oid,
	ResponseTimestamp: time.Now().Unix(),
	Code:              200,
	Size:              inputSize,
	Headers:           nil,
}

func TestPartWriter(t *testing.T) {
	t.Parallel()
	test := func(start, length, partSize uint64) {
		cz := &types.CacheZone{
			ID:      "TestCZ",
			Storage: mock.NewStorage(partSize),
Esempio n. 15
0
	"sync"
	"testing"
	"time"

	"github.com/ironsmile/nedomi/config"
	"github.com/ironsmile/nedomi/mock"
	"github.com/ironsmile/nedomi/types"
	"github.com/ironsmile/nedomi/utils/testutils"
)

func init() {
	rand.Seed(time.Now().Unix())
}

var obj1 = &types.ObjectMetadata{
	ID:                types.NewObjectID("testkey", "/lorem/ipsum"),
	ResponseTimestamp: time.Now().Unix(),
	Headers:           http.Header{"test": []string{"mest"}},
}
var obj2 = &types.ObjectMetadata{
	ID:                types.NewObjectID("concern", "/doge?so=scare&very_parameters"),
	ResponseTimestamp: time.Now().Unix(),
	Headers:           http.Header{"how-to": []string{"header"}},
}
var obj3 = &types.ObjectMetadata{
	ID:                types.NewObjectID("concern", "/very/space**"),
	ResponseTimestamp: time.Now().Unix(),
	Headers:           http.Header{"so": []string{"galaxy", "amaze"}},
}

func checkFile(t *testing.T, d *Disk, filePath, expectedContents string) {
Esempio n. 16
0
const (
	cacheKey1, cacheKey2 = "testkey1", "testkey2"
	testURL              = "http://example.com/more/path*!:@#>"
	host1, host2, host3  = "example.org:1232", "example.net:8080", "notexample.net:8080"
	path1, path2, path3  = "/path/to/object", "/path/to/an/object", "/path/to/no/object"
	url1, url2, url3     = "http://" + host1 + path1, "http://" + host2 + path2, "http://" + host3 + path3
	host4, host5, host6  = "example.org:1232", "example.org:notPOrt", "notexample.net:8080"
	path4, path5, path6  = "/path/to/no/object", "/path/to/object", "/path/to/no/object"
	url4, url5, url6     = "http://" + host4 + path4, "http://" + host5 + path5, "http://" + host6 + path6
	requestText          = `[ "` + url1 + `", "` + url2 + `", "` + url3 + `", "` + url4 + `", "` + url5 + `", "` + url6 + `" ]`
	badRequestText       = `Bad request`
)

var (
	obj1 = types.NewObjectID(cacheKey1, path1)
	obj2 = types.NewObjectID(cacheKey2, path2)
)

func testCode(t *testing.T, code, expected int) {
	if code != expected {
		t.Fatalf("wrong response code %d expected %d", code, expected)
	}
}

func removeFunctionMock(t *testing.T) func(parts ...*types.ObjectIndex) {
	return func(parts ...*types.ObjectIndex) {
		for _, part := range parts {
			switch part.ObjID.Path() {
			case obj1.Path(), obj2.Path():
			default:
Esempio n. 17
0
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"testing"
	"time"

	"github.com/ironsmile/nedomi/types"
	"github.com/ironsmile/nedomi/utils/testutils"
)

// make sure that NewStorage implements types.Storage
var _ types.Storage = (*Storage)(nil)

var obj1 = &types.ObjectMetadata{
	ID:                types.NewObjectID("testkey", "/lorem/ipsum"),
	ResponseTimestamp: time.Now().Unix(),
	Headers:           http.Header{"test": []string{"mest"}},
}

var obj2 = &types.ObjectMetadata{
	ID:                types.NewObjectID("testkey", "/lorem/ipsum/2"),
	ResponseTimestamp: time.Now().Unix(),
	Headers:           http.Header{},
}

func TestMockStorageExpectedErrors(t *testing.T) {
	t.Parallel()
	s := NewStorage(10)

	idx := &types.ObjectIndex{ObjID: obj1.ID, Part: 5}