package policy import ( "os" "path" "testing" "postern/internal/db" "go.starlark.net/starlark" ) func TestKVModule(t *testing.T) { posternDB, err := db.OpenDB(&db.Config{ DBPath: path.Join(t.TempDir(), "meta.db"), }) if err != nil { t.Fatal(err) } defer func(posternDB *db.DB) { err := posternDB.Close() if err != nil { t.Fatal(err) } }(posternDB) policy := ` def init(): return None def test_kv_set(k, v): kv.set(k, v) def test_kv_get(k): return kv.get(k) def test_kv_get_default(k, d): return kv.get(k, default=d) def test_kv_inc_delta(k, d): return kv.inc(k, delta=d) def test_kv_inc(k): return kv.inc(k) def test_kv_pop(k): return kv.pop(k) ` policyFile := path.Join(t.TempDir(), "policy.star") err = os.WriteFile(policyFile, []byte(policy), 0644) if err != nil { t.Fatal(err) } e, err := NewEngine(policyFile, posternDB) if err != nil { t.Fatal(err) } // KV Set initial value hookVal, ok := e.globals["test_kv_set"] if !ok { t.Fatal("test_kv_set not found in engine globals") } k, v := starlark.String("key"), starlark.MakeInt(1) _, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k, v}, nil) if err != nil { t.Fatal(err) } // KV Set unsupported type k, unsupported := starlark.String("key"), &starlark.Dict{} _, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k, unsupported}, nil) if err == nil { t.Fatal("expected unsupported type to throw an error") } // KV get initial value hookVal, ok = e.globals["test_kv_get"] if !ok { t.Fatal("test_kv_get not found in engine globals") } res, err := starlark.Call(e.thread, hookVal, starlark.Tuple{k}, nil) if err != nil { t.Fatal(err) } if res != v { t.Fatalf("got %s, want %s", res, v) } // Get default value for non-existing key hookVal, ok = e.globals["test_kv_get_default"] if !ok { t.Fatal("test_kv_get_default not found in engine globals") } res, err = starlark.Call(e.thread, hookVal, starlark.Tuple{starlark.String("not-exist"), starlark.String("default")}, nil) if err != nil { t.Fatal(err) } if want := starlark.String("default"); res != want { t.Fatalf("got %s, want %s", res, want) } // KV increment initial value by default delta=1 hookVal, ok = e.globals["test_kv_inc"] if !ok { t.Fatal("test_kv_inc not found in engine globals") } res, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k}, nil) if err != nil { t.Fatal(err) } if want := starlark.MakeInt(2); res != want { t.Fatalf("got %s, want %s", res, want) } // KV increment by delta=2 hookVal, ok = e.globals["test_kv_inc_delta"] if !ok { t.Fatal("test_kv_inc not found in engine globals") } res, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k, starlark.MakeInt(2)}, nil) if err != nil { t.Fatal(err) } if want := starlark.MakeInt(4); res != want { t.Fatalf("got %s, want %s", res, want) } // KV pop hookVal, ok = e.globals["test_kv_pop"] if !ok { t.Fatal("test_kv_pop not found in engine globals") } res, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k}, nil) if err != nil { t.Fatal(err) } if want := starlark.MakeInt(4); res != want { t.Fatalf("got %s, want %s", res, want) } // KV pop non-existing res, err = starlark.Call(e.thread, hookVal, starlark.Tuple{k}, nil) if err != nil { t.Fatal(err) } if res != starlark.None { t.Fatalf("got %s, want %s", res, starlark.None) } }