chrly/mojangtextures/in_memory_textures_storage_test.go
2020-05-01 20:11:49 +03:00

165 lines
5.1 KiB
Go

package mojangtextures
import (
"testing"
"time"
assert "github.com/stretchr/testify/require"
"github.com/elyby/chrly/api/mojang"
)
var texturesWithSkin = &mojang.SignedTexturesResponse{
Id: "dead24f9a4fa4877b7b04c8c6c72bb46",
Name: "mock",
Props: []*mojang.Property{
{
Name: "textures",
Value: mojang.EncodeTextures(&mojang.TexturesProp{
Timestamp: time.Now().UnixNano() / 10e5,
ProfileID: "dead24f9a4fa4877b7b04c8c6c72bb46",
ProfileName: "mock",
Textures: &mojang.TexturesResponse{
Skin: &mojang.SkinTexturesResponse{
Url: "http://textures.minecraft.net/texture/74d1e08b0bb7e9f590af27758125bbed1778ac6cef729aedfcb9613e9911ae75",
},
},
}),
},
},
}
var texturesWithoutSkin = &mojang.SignedTexturesResponse{
Id: "dead24f9a4fa4877b7b04c8c6c72bb46",
Name: "mock",
Props: []*mojang.Property{
{
Name: "textures",
Value: mojang.EncodeTextures(&mojang.TexturesProp{
Timestamp: time.Now().UnixNano() / 10e5,
ProfileID: "dead24f9a4fa4877b7b04c8c6c72bb46",
ProfileName: "mock",
Textures: &mojang.TexturesResponse{},
}),
},
},
}
func TestInMemoryTexturesStorage_GetTextures(t *testing.T) {
t.Run("should return nil, nil when textures are unavailable", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
result, err := storage.GetTextures("b5d58475007d4f9e9ddd1403e2497579")
assert.Nil(t, result)
assert.Nil(t, err)
})
t.Run("get textures object, when uuid is stored in the storage", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithSkin)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.Equal(t, texturesWithSkin, result)
assert.Nil(t, err)
})
t.Run("should return nil, nil when textures are exists, but cache duration is expired", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
storage.Duration = 10 * time.Millisecond
storage.GCPeriod = time.Minute
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithSkin)
time.Sleep(storage.Duration * 2)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.Nil(t, result)
assert.Nil(t, err)
})
}
func TestInMemoryTexturesStorage_StoreTextures(t *testing.T) {
t.Run("store textures for previously not existed uuid", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithSkin)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.Equal(t, texturesWithSkin, result)
assert.Nil(t, err)
})
t.Run("override already existed textures for uuid", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithoutSkin)
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithSkin)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.NotEqual(t, texturesWithoutSkin, result)
assert.Equal(t, texturesWithSkin, result)
assert.Nil(t, err)
})
t.Run("store textures with empty properties", func(t *testing.T) {
texturesWithEmptyProps := &mojang.SignedTexturesResponse{
Id: "dead24f9a4fa4877b7b04c8c6c72bb46",
Name: "mock",
Props: []*mojang.Property{},
}
storage := NewInMemoryTexturesStorage()
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", texturesWithEmptyProps)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.Exactly(t, texturesWithEmptyProps, result)
assert.Nil(t, err)
})
t.Run("store nil textures", func(t *testing.T) {
storage := NewInMemoryTexturesStorage()
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", nil)
result, err := storage.GetTextures("dead24f9a4fa4877b7b04c8c6c72bb46")
assert.Nil(t, result)
assert.Nil(t, err)
})
}
func TestInMemoryTexturesStorage_GarbageCollection(t *testing.T) {
storage := NewInMemoryTexturesStorage()
defer storage.Stop()
storage.GCPeriod = 10 * time.Millisecond
storage.Duration = 9 * time.Millisecond
textures1 := &mojang.SignedTexturesResponse{
Id: "dead24f9a4fa4877b7b04c8c6c72bb46",
Name: "mock1",
Props: []*mojang.Property{},
}
textures2 := &mojang.SignedTexturesResponse{
Id: "b5d58475007d4f9e9ddd1403e2497579",
Name: "mock2",
Props: []*mojang.Property{},
}
storage.StoreTextures("dead24f9a4fa4877b7b04c8c6c72bb46", textures1)
// Store another texture a bit later to avoid it removing by GC after the first iteration
time.Sleep(2 * time.Millisecond)
storage.StoreTextures("b5d58475007d4f9e9ddd1403e2497579", textures2)
storage.lock.RLock()
assert.Len(t, storage.data, 2, "the GC period has not yet reached")
storage.lock.RUnlock()
time.Sleep(storage.GCPeriod) // Let it perform the first GC iteration
storage.lock.RLock()
assert.Len(t, storage.data, 1, "the first texture should be cleaned by GC")
assert.Contains(t, storage.data, "b5d58475007d4f9e9ddd1403e2497579")
storage.lock.RUnlock()
time.Sleep(storage.GCPeriod) // Let another iteration happen
storage.lock.RLock()
assert.Len(t, storage.data, 0)
storage.lock.RUnlock()
}