Repository: allegro/bigcache (go)

Issue:
support mocking clock in other projects
I'm doing unit testing, and I cannot find a way to mock `Bigcache#clock`.

* the `Bigcache#clock` attribute is unexported
* the `newBigcache(...)` is unexported
* the methods in `clock interface` is unexported, and the [reflect#implements](https://github.com/golang/go/blob/dfdc3880b01d46d1d8125ab9eea0606b2fa5b819/src/reflect/type.go#L1501) rejects due to difference packages. 

I proposal that we export `clock#Epoch`, and it seems have no side effects.

Any suggestions? I'm glad to contribute a patch for this.

Pull request:
export clock method to allow assignable in other packages
For example:

```
cache := bigcache.NewBigCache(bigcache.DefaultConfig(time.Minute))
clock := &mockedClock{}
rf := reflect.ValueOf(cache).Elem().FieldByName("clock")
reflect.NewAt(rf.Type(), unsafe.Pointer(rf.UnsafeAddr())).Elem().Set(reflect.ValueOf(clock))
```

Without this change, it panics with `value of type *cache_test.mockedClock is not assignable to type bigcache.clock`

And it goes to `*cache_test.mockedClock cannot implement bigcache.Clock as it has a non-exported method and is defined in a difference package` if we only export clock interface.

Fix #241 

Patch:
diff --git a/clock.go b/clock.go
index f8b535e..195d01a 100644
--- a/clock.go
+++ b/clock.go
@@ -3,12 +3,12 @@ package bigcache
 import "time"
 
 type clock interface {
-	epoch() int64
+	Epoch() int64
 }
 
 type systemClock struct {
 }
 
-func (c systemClock) epoch() int64 {
+func (c systemClock) Epoch() int64 {
 	return time.Now().Unix()
 }
diff --git a/shard.go b/shard.go
index b432b33..470742d 100644
--- a/shard.go
+++ b/shard.go
@@ -33,7 +33,7 @@ type cacheShard struct {
 }
 
 func (s *cacheShard) getWithInfo(key string, hashedKey uint64) (entry []byte, resp Response, err error) {
-	currentTime := uint64(s.clock.epoch())
+	currentTime := uint64(s.clock.Epoch())
 	s.lock.RLock()
 	wrappedEntry, err := s.getWrappedEntry(hashedKey)
 	if err != nil {
@@ -117,7 +117,7 @@ func (s *cacheShard) getWrappedEntry(hashedKey uint64) ([]byte, error) {
 }
 
 func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error {
-	currentTimestamp := uint64(s.clock.epoch())
+	currentTimestamp := uint64(s.clock.Epoch())
 
 	s.lock.Lock()
 
@@ -147,7 +147,7 @@ func (s *cacheShard) set(key string, hashedKey uint64, entry []byte) error {
 }
 
 func (s *cacheShard) setWithoutLock(key string, hashedKey uint64, entry []byte) error {
-	currentTimestamp := uint64(s.clock.epoch())
+	currentTimestamp := uint64(s.clock.Epoch())
 
 	if previousIndex := s.hashmap[hashedKey]; previousIndex != 0 {
 		if previousEntry, err := s.entries.Get(int(previousIndex)); err == nil {


Test patch:
diff --git a/bigcache_test.go b/bigcache_test.go
index 4433ffa..d6249a4 100644
--- a/bigcache_test.go
+++ b/bigcache_test.go
@@ -389,7 +389,7 @@ func TestOnRemoveFilterExpired(t *testing.T) {
 
 	cache.Set("key", []byte("value"))
 	clock.set(5)
-	cache.cleanUp(uint64(clock.epoch()))
+	cache.cleanUp(uint64(clock.Epoch()))
 
 	err = cache.Delete("key")
 
@@ -406,7 +406,7 @@ func TestOnRemoveFilterExpired(t *testing.T) {
 	cache.Set("key2", []byte("value2"))
 	err = cache.Delete("key2")
 	clock.set(5)
-	cache.cleanUp(uint64(clock.epoch()))
+	cache.cleanUp(uint64(clock.Epoch()))
 	// then
 
 	assertEqual(t, err, nil)
@@ -1079,7 +1079,7 @@ type mockedClock struct {
 	value int64
 }
 
-func (mc *mockedClock) epoch() int64 {
+func (mc *mockedClock) Epoch() int64 {
 	return mc.value
 }