commit db4c7bc4cb26ba349e8bff534bf0d29809049651
parent a4198d48b46a1e8f4d0917a1de1c3a2972e28a47
Author: lash <dev@holbrook.no>
Date: Wed, 11 Sep 2024 02:33:06 +0100
Reach 85% coverage on cache tests
Diffstat:
5 files changed, 134 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
@@ -29,3 +29,7 @@ intro:
doc:
make -C doc
+
+cov:
+ go test -cover ./... -coverprofile=cover.out
+ go tool cover -html=cover.out
diff --git a/cache/cache.go b/cache/cache.go
@@ -58,8 +58,7 @@ func(ca *Cache) Add(key string, value string, sizeLimit uint16) error {
if checkFrame > -1 {
thisFrame := len(ca.Cache) - 1
if checkFrame == thisFrame {
- logg.Debugf("Ignoring load request on frame that has symbol already loaded")
- return nil
+ return ErrDup
}
return fmt.Errorf("key %v already defined in frame %v, this is frame %v", key, checkFrame, thisFrame)
}
diff --git a/cache/cache_test.go b/cache/cache_test.go
@@ -2,6 +2,7 @@ package cache
import (
"testing"
+ "slices"
)
func TestNewCache(t *testing.T) {
@@ -15,7 +16,7 @@ func TestNewCache(t *testing.T) {
}
}
-func TestStateCacheUse(t *testing.T) {
+func TestCacheUse(t *testing.T) {
ca := NewCache()
ca = ca.WithCacheSize(10)
ca.Push()
@@ -31,6 +32,74 @@ func TestStateCacheUse(t *testing.T) {
if err == nil {
t.Errorf("expected capacity error")
}
+ v := ca.Check("inky")
+ if v {
+ t.Fatal("expected true")
+ }
+ v = ca.Check("blinky")
+ if !v {
+ t.Fatal("expected false")
+ }
+}
+
+func TestCacheUpdate(t *testing.T) {
+ ca := NewCache()
+ ca = ca.WithCacheSize(10)
+ ca.Add("foo", "bar", 0)
+ err := ca.Add("foo", "barbarbar", 0)
+ if err != ErrDup {
+ t.Error(err)
+ }
+ v, err := ca.Get("foo")
+ if err != nil {
+ t.Error(err)
+ }
+ if v != "bar" {
+ t.Fatalf("expected 'bar', got '%s'", v)
+ }
+ err = ca.Update("foo", "barbarbar")
+ v, err = ca.Get("foo")
+ if err != nil {
+ t.Error(err)
+ }
+ if v != "barbarbar" {
+ t.Fatalf("expected 'barbarbar', got '%s'", v)
+ }
+ err = ca.Update("foo", "barbarbarbar")
+ if err == nil {
+ t.Fatalf("expect error")
+ }
+}
+
+func TestCacheLimits(t *testing.T) {
+ ca := NewCache()
+ ca = ca.WithCacheSize(8)
+ err := ca.Add("foo", "bar", 2)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ err = ca.Add("foo", "barbarbar", 0)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ err = ca.Add("foo", "bar", 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ca.Add("baz", "barbar", 0)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ ca.Reset()
+ err = ca.Add("baz", "barbar", 0)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ ca.Pop()
+ err = ca.Add("baz", "barbar", 0)
+ if err != nil {
+ t.Fatal(err)
+ }
}
func TestStateDownUp(t *testing.T) {
@@ -82,12 +151,13 @@ func TestCacheReset(t *testing.T) {
if err != nil {
t.Error(err)
}
+ ca.Push()
err = ca.Add("baz", "xyzzy", 0)
if err != nil {
t.Error(err)
}
ca.Reset()
- if ca.CacheUseSize != 0 {
+ if ca.CacheUseSize != 3 {
t.Errorf("expected cache use size 0, got %v", ca.CacheUseSize)
}
}
@@ -103,14 +173,55 @@ func TestCacheLoadDup(t *testing.T) {
t.Error(err)
}
err = ca.Push()
+ if err != nil {
+ t.Error(err)
+ }
err = ca.Add("foo", "baz", 0)
if err == nil {
- t.Errorf("expected fail on duplicate load")
+ t.Errorf("expect duplicate key in different frame")
}
ca.Pop()
err = ca.Add("foo", "baz", 0)
+ if err != ErrDup {
+ t.Error(err)
+ }
+}
+
+func TestCacheLast(t *testing.T) {
+ ca := NewCache()
+ v := ca.Last()
+ if v != "" {
+ t.Fatal("expected empty")
+ }
+ err := ca.Add("foo", "bar", 0)
+ if err != nil {
+ t.Error(err)
+ }
+ ca.Push()
+ err = ca.Add("baz", "xyzzy", 0)
if err != nil {
t.Error(err)
}
+ v = ca.Last()
+ if v != "xyzzy" {
+ t.Fatalf("expected 'xyzzy', got: '%s'", v)
+ }
}
+func TestCacheKeys(t *testing.T) {
+ ca := NewCache()
+ ca.Add("inky", "tinkywinky", 0)
+ ca.Push()
+ ca.Add("pinky", "dipsy", 0)
+ ca.Push()
+ ca.Push()
+ ca.Add("blinky", "lala", 0)
+ ca.Add("clyde", "pu", 0)
+ ks := ca.Keys(3)
+ if !slices.Contains(ks, "blinky") {
+ t.Fatalf("Missing 'blinky'")
+ }
+ if !slices.Contains(ks, "clyde") {
+ t.Fatalf("Missing 'clyde'")
+ }
+}
diff --git a/cache/error.go b/cache/error.go
@@ -0,0 +1,9 @@
+package cache
+
+import (
+ "fmt"
+)
+
+var (
+ ErrDup = fmt.Errorf("duplicate key")
+)
diff --git a/vm/runner.go b/vm/runner.go
@@ -276,6 +276,12 @@ func(vm *Vm) runLoad(ctx context.Context, b []byte) ([]byte, error) {
return b, err
}
err = vm.ca.Add(sym, r, uint16(sz))
+ if err != nil {
+ if err == cache.ErrDup {
+ logg.DebugCtxf(ctx, "Ignoring load request on frame that has symbol already loaded", "sym", sym)
+ err = nil
+ }
+ }
return b, err
}