-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
1,024 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
package cache | ||
|
||
import ( | ||
"fmt" | ||
"github.com/pquerna/cachecontrol/cacheobject" | ||
"github.com/stretchr/testify/assert" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
type hashCall struct { | ||
method string | ||
url string | ||
requestHeader http.Header | ||
} | ||
|
||
func Test_CacheStrategy_FetchDefinitionHash(t *testing.T) { | ||
a := assert.New(t) | ||
tests := []struct { | ||
strategy *CacheStrategy | ||
call1 hashCall | ||
call2 hashCall | ||
equal bool | ||
}{ | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", nil}, | ||
hashCall{"GET", "/foo", nil}, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", http.Header{"Accept": {"text/html"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", http.Header{"Cookie": {"foo=bar; bi=bo"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
true, | ||
}, | ||
{ | ||
NewCacheStrategy(nil, []string{"foo"}, nil), | ||
hashCall{"GET", "/foo", http.Header{"Cookie": {"cname=bar; bi=bo"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", nil}, | ||
hashCall{"GET", "/bar", nil}, | ||
false, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", nil}, | ||
hashCall{"POST", "/foo", nil}, | ||
false, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", http.Header{"Authorization": {"Basic: foo"}}}, | ||
hashCall{"GET", "/foo", http.Header{"Authorization": {"Basic: bar"}}}, | ||
false, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
hashCall{"GET", "/foo", http.Header{"Accept-Encoding": {"gzip"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
false, | ||
}, | ||
{ | ||
NewCacheStrategy(nil, []string{"cname"}, nil), | ||
hashCall{"GET", "/foo", http.Header{"Cookie": {"cname=bar"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
false, | ||
}, | ||
{ | ||
NewCacheStrategy([]string{"Accept"}, nil, nil), | ||
hashCall{"GET", "/foo", http.Header{"Accept": {"text/html"}}}, | ||
hashCall{"GET", "/foo", http.Header{}}, | ||
false, | ||
}, | ||
} | ||
|
||
for _, t := range tests { | ||
hash1 := t.strategy.Hash(t.call1.method, t.call1.url, t.call1.requestHeader) | ||
hash2 := t.strategy.Hash(t.call2.method, t.call2.url, t.call2.requestHeader) | ||
if t.equal { | ||
a.Equal(hash1, hash2) | ||
} else { | ||
a.NotEqual(hash1, hash2) | ||
} | ||
} | ||
} | ||
|
||
func Test_CacheStrategy_IsCachable(t *testing.T) { | ||
a := assert.New(t) | ||
tests := []struct { | ||
strategy *CacheStrategy | ||
method string | ||
statusCode int | ||
requestHeader http.Header | ||
responseHeader http.Header | ||
isCacheable bool | ||
}{ | ||
{ | ||
DefaultCacheStrategy, | ||
"GET", | ||
200, | ||
http.Header{ | ||
"Accept": {"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}, | ||
"Cache-Control": {"max-age=0"}, | ||
"Connection": {"keep-alive"}, | ||
}, | ||
http.Header{ | ||
"Content-Type": {"text/html; charset=utf-8"}, | ||
"Date": {"Wed, 22 Jun 2016 12:03:25 GMT"}, | ||
}, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
"GET", | ||
200, | ||
nil, | ||
http.Header{ | ||
"Authorization": {"Basic sdcsad"}, | ||
}, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
"POST", | ||
200, | ||
nil, | ||
nil, | ||
false, | ||
}, | ||
{ | ||
NewCacheStrategy(nil, nil, []cacheobject.Reason{cacheobject.ReasonRequestMethodPOST}), | ||
"POST", | ||
200, | ||
nil, | ||
nil, | ||
true, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
"GET", | ||
500, | ||
nil, | ||
nil, | ||
false, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
"GET", | ||
200, | ||
http.Header{"Cache-Control": {"max-age=-1"}}, // error case of lib cacheobject | ||
nil, | ||
false, | ||
}, | ||
{ | ||
DefaultCacheStrategy, | ||
"GET", | ||
200, | ||
nil, | ||
http.Header{ | ||
"Cache-Control": {"no-store"}, | ||
}, | ||
false, | ||
}, | ||
} | ||
|
||
for _, t := range tests { | ||
cacheable := t.strategy.IsCachable(t.method, "", t.statusCode, t.requestHeader, t.responseHeader) | ||
message := fmt.Sprintf("%v = isCacheable(%q, %q, %v, %v, %v)", cacheable, t.method, "", t.statusCode, t.requestHeader, t.responseHeader) | ||
if t.isCacheable { | ||
a.True(cacheable, message) | ||
} else { | ||
a.False(cacheable, message) | ||
} | ||
} | ||
} | ||
|
||
func Test_CacheStrategy_readCookieValue(t *testing.T) { | ||
a := assert.New(t) | ||
|
||
v, found := readCookieValue(http.Header{"Cookie": {"foo=bar"}}, "foo") | ||
a.True(found) | ||
a.Equal("bar", v) | ||
|
||
v, found = readCookieValue(http.Header{"Cookie": {`foo="bar"`}}, "foo") | ||
a.True(found) | ||
a.Equal("bar", v) | ||
|
||
v, found = readCookieValue(http.Header{"Cookie": {"foo"}}, "foo") | ||
a.True(found) | ||
a.Equal("", v) | ||
|
||
v, found = readCookieValue(http.Header{"Cookie": {";"}}, "foo") | ||
a.False(found) | ||
|
||
v, found = readCookieValue(http.Header{"Cookie": {""}}, "foo") | ||
a.False(found) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package cache | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func Test_Cache_PanicsOnCreateWithWrongSize(t *testing.T) { | ||
a := assert.New(t) | ||
a.Panics(func() { | ||
NewCache(-1, 0, time.Millisecond) | ||
}) | ||
} | ||
|
||
func Test_Cache_TTL(t *testing.T) { | ||
a := assert.New(t) | ||
|
||
// given a cache 1ms ttl | ||
c := NewCache(5, 100, time.Millisecond) | ||
|
||
// when i store an entry | ||
c.Set("foo", "", 0, "bar") | ||
|
||
// then I can retrieve it | ||
v, found := c.Get("foo") | ||
a.True(found) | ||
a.Equal("bar", v.(string)) | ||
|
||
// but when I wait for the TTL | ||
time.Sleep(time.Millisecond) | ||
|
||
// then it is not found any more | ||
_, found = c.Get("foo") | ||
a.False(found) | ||
} | ||
|
||
func Test_Cache_LRU_MaxEntries(t *testing.T) { | ||
a := assert.New(t) | ||
|
||
// given a cache of size 3 | ||
// with 3 entries | ||
c := NewCache(3, 100, time.Hour) | ||
c.Set("a", "", 0, "a") | ||
c.Set("b", "", 0, "b") | ||
c.Set("c", "", 0, "c") | ||
a.Equal(3, c.Len()) | ||
|
||
// when I and access the oldest | ||
v, found := c.Get("a") | ||
a.True(found) | ||
a.Equal("a", v.(string)) | ||
|
||
// and add one more | ||
c.Set("newcommer", "", 0, "newcommer") | ||
|
||
// then the recently used are in | ||
_, found = c.Get("a") | ||
a.True(found) | ||
_, found = c.Get("c") | ||
a.True(found) | ||
_, found = c.Get("newcommer") | ||
a.True(found) | ||
|
||
// but one is out | ||
_, found = c.Get("b") | ||
a.False(found) | ||
} | ||
|
||
func Test_Cache_MaxBytes(t *testing.T) { | ||
a := assert.New(t) | ||
|
||
// given a cache with max 10 bytes, filled with 8 bytes | ||
c := NewCache(100, 10, time.Hour) | ||
c.Set("a", "", 4, "a") | ||
c.Set("b", "", 4, "b") | ||
a.Equal(8, c.SizeByte()) | ||
a.Equal(2, c.Len()) | ||
|
||
// when I add and 2 more bytes | ||
c.Set("c", "", 2, "c") | ||
|
||
// then they fit | ||
a.Equal(10, c.SizeByte()) | ||
a.Equal(3, c.Len()) | ||
|
||
// but when i add even more | ||
c.Set("d", "", 2, "c") | ||
|
||
// then the last accessed entry was taken out | ||
a.Equal(8, c.SizeByte()) | ||
a.Equal(3, c.Len()) | ||
_, found := c.Get("b") | ||
a.True(found) | ||
_, found = c.Get("c") | ||
a.True(found) | ||
_, found = c.Get("d") | ||
a.True(found) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package composition | ||
|
||
import ( | ||
"github.com/golang/mock/gomock" | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func Test_CacheLoader_Found(t *testing.T) { | ||
ctrl := gomock.NewController(t) | ||
defer ctrl.Finish() | ||
a := assert.New(t) | ||
|
||
// given: | ||
fd := NewFetchDefinition("/foo") | ||
c := NewMemoryContent() | ||
c.url = "/foo" | ||
|
||
// and a cache returning the memory content by the hash | ||
cacheMocK := NewMockCache(ctrl) | ||
cacheMocK.EXPECT().Get(fd.Hash()).Return(c, true) | ||
|
||
// when: we load the object | ||
loader := NewCachingContentLoader() | ||
loader.cache = cacheMocK | ||
|
||
// it is returned | ||
result, err := loader.Load(fd) | ||
a.NoError(err) | ||
a.Equal(c, result) | ||
} | ||
|
||
func Test_CacheLoader_NotFound(t *testing.T) { | ||
tests := []struct { | ||
url string | ||
method string | ||
cachable bool | ||
}{ | ||
{"http://example.de", "GET", true}, | ||
{"file:///some/file", "GET", true}, | ||
{"http://example.de", "POST", false}, | ||
} | ||
for _, test := range tests { | ||
ctrl := gomock.NewController(t) | ||
a := assert.New(t) | ||
|
||
// given: | ||
c := NewMemoryContent() | ||
c.url = test.url | ||
c.httpStatusCode = 200 | ||
fd := NewFetchDefinition(c.url) | ||
fd.Method = test.method | ||
|
||
// and a cache returning nothing | ||
cacheMocK := NewMockCache(ctrl) | ||
cacheMocK.EXPECT().Get(gomock.Any()).Return(nil, false) | ||
if test.cachable { | ||
cacheMocK.EXPECT().Set(fd.Hash(), fd.URL, c.MemorySize(), c) | ||
} | ||
// and a loader delegating to | ||
loaderMock := NewMockContentLoader(ctrl) | ||
loaderMock.EXPECT().Load(gomock.Any()).Return(c, nil) | ||
|
||
// when: we load the object | ||
loader := NewCachingContentLoader() | ||
loader.cache = cacheMocK | ||
if test.url == "file:///some/file" { | ||
loader.fileContentLoader = loaderMock | ||
} else { | ||
loader.httpContentLoader = loaderMock | ||
} | ||
|
||
// it is returned | ||
result, err := loader.Load(fd) | ||
a.NoError(err) | ||
a.Equal(c, result) | ||
ctrl.Finish() | ||
} | ||
} |
Oops, something went wrong.