internal/memory/stores_test.go
Rama main · réplica de lectura del repositorio original.
package memory_test
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
"github.com/yeomyeonggeori/blueclaw/internal/memory"
"github.com/yeomyeonggeori/blueclaw/internal/memory/memorytest"
"github.com/yeomyeonggeori/blueclaw/internal/policy"
"github.com/yeomyeonggeori/blueclaw/internal/security"
"github.com/yeomyeonggeori/bluememo"
"github.com/yeomyeonggeori/bluememo/bluememotest"
)
func TestMergePersonRenamesTheLosingFileWhenTheSurvivorHasNone(t *testing.T) {
stores := memorytest.Open(t)
ctx := context.Background()
memorytest.Remember(t, stores, memory.PersonScope("legacy-person"), "이샘플 prefers the morning slot.")
if errorValue := stores.MergePerson(ctx, "legacy-person", "person-1"); errorValue != nil {
t.Fatalf("merge: %v", errorValue)
}
if held := memorytest.Count(t, stores, memory.PersonScope("person-1")); held != 1 {
t.Errorf("the survivor holds %d memories, want the one that moved", held)
}
if left := memorytest.Count(t, stores, memory.PersonScope("legacy-person")); left != 0 {
t.Errorf("the merged-away person still holds %d memories, want none", left)
}
}
func TestMergePersonCarriesTheMemoriesWhenBothFilesExist(t *testing.T) {
stores := memorytest.Open(t)
ctx := context.Background()
memorytest.Remember(t, stores, memory.PersonScope("legacy-person"), "이샘플 prefers the morning slot.")
memorytest.Remember(t, stores, memory.PersonScope("person-1"), "이샘플 chairs the safety review.")
if errorValue := stores.MergePerson(ctx, "legacy-person", "person-1"); errorValue != nil {
t.Fatalf("merge: %v", errorValue)
}
if held := memorytest.Count(t, stores, memory.PersonScope("person-1")); held != 2 {
t.Errorf("the survivor holds %d memories, want both", held)
}
if left := memorytest.Count(t, stores, memory.PersonScope("legacy-person")); left != 0 {
t.Errorf("the merged-away person still holds %d memories, want none", left)
}
}
func TestMergePersonIsQuietWhenThereIsNothingToMove(t *testing.T) {
stores := memorytest.Open(t)
ctx := context.Background()
if errorValue := stores.MergePerson(ctx, "legacy-person", "person-1"); errorValue != nil {
t.Fatalf("merge with no file: %v", errorValue)
}
if errorValue := stores.MergePerson(ctx, "person-1", "person-1"); errorValue != nil {
t.Fatalf("merge into itself: %v", errorValue)
}
}
func TestASubjectsMemorySitsInTheirOwnWorkspaceUnderProtected(t *testing.T) {
stores := memorytest.Open(t)
for name, expectation := range map[string]struct {
scope memory.Scope
suffix string
}{
"a person": {memory.PersonScope("person-1"), "/private/protected/person-1/memory.db"},
"a circle": {memory.CircleScope("member"), "/circles/member/.protected/memory.db"},
"everyone": {memory.WorkspaceScope(), "/shared/.protected/memory.db"},
} {
t.Run(name, func(t *testing.T) {
path, errorValue := stores.Path(expectation.scope)
if errorValue != nil {
t.Fatalf("path: %v", errorValue)
}
if !strings.HasSuffix(path, expectation.suffix) {
t.Fatalf("memory for %s sits at %q, which does not end in %q", name, path, expectation.suffix)
}
})
}
}
func TestAMemoryFileIsReadableByItsSubjectAndWritableByNobodyElse(t *testing.T) {
stores := memorytest.Open(t)
scope := memory.PersonScope("person-1")
memorytest.Remember(t, stores, scope, "박예시 keeps the quarterly ledger")
path, errorValue := stores.Path(scope)
if errorValue != nil {
t.Fatalf("path: %v", errorValue)
}
information, errorValue := os.Stat(path)
if errorValue != nil {
t.Fatalf("stat: %v", errorValue)
}
if mode := information.Mode().Perm(); mode != 0o640 {
t.Fatalf("a memory file carries mode %04o; the subject's group must read it and only the service write it", mode)
}
}
func TestAMemoryNobodyWroteRecallsNothingRatherThanFailing(t *testing.T) {
stores := memorytest.Open(t)
recalled, errorValue := stores.RecallAcross(
context.Background(),
policy.PersonAccess{PersonID: "person-nobody-wrote-for"},
[]memory.Scope{memory.PersonScope("person-nobody-wrote-for"), memory.WorkspaceScope()},
"anything",
10,
)
if errorValue != nil {
t.Fatalf("a recall of files nobody has written failed: %v", errorValue)
}
if len(recalled.Facts) != 0 {
t.Fatalf("a recall of files nobody has written answered with %d facts", len(recalled.Facts))
}
}
func TestARefusedReadFailsTheRecallRatherThanThinningIt(t *testing.T) {
stores := memory.NewStores(t.TempDir(), bluememo.Configuration{
Embedder: &bluememotest.HashEmbedder{},
}, refusingActor{})
t.Cleanup(func() { _ = stores.Close() })
if _, errorValue := stores.Store(context.Background(), memory.PersonScope("person-1")); errorValue != nil {
t.Fatalf("open the file the read is refused: %v", errorValue)
}
_, errorValue := stores.RecallAcross(
context.Background(),
policy.PersonAccess{PersonID: "person-1"},
[]memory.Scope{memory.PersonScope("person-1")},
"anything",
10,
)
if errorValue == nil {
t.Fatal("a recall whose read was refused reported success, so a refusal would read as an empty memory")
}
if !strings.Contains(errorValue.Error(), "refused") {
t.Fatalf("a refused recall failed with something else: %v", errorValue)
}
}
type refusingActor struct {
security.WorkspaceActor
}
func (refusingActor) Requester(context.Context, security.WorkspaceActorRequest) (security.WorkspaceActor, error) {
return refusingActor{}, nil
}
func (refusingActor) CanListDirectory(context.Context) bool { return false }
func (refusingActor) Run(context.Context, security.CommandRequest) (security.CommandResult, error) {
return security.CommandResult{ExitCode: 1, Stderr: "permission denied"}, nil
}
func TestEveryScopeAnAdministratorReachesSitsInADeclaredDirectory(t *testing.T) {
stores, root := memorytest.OpenWithRoot(t)
administrator := policy.PersonPolicy{PersonID: "person-1", Circles: []string{"sales"}, IsAdmin: true}
document := policy.CanonicalizePolicyDocument(policy.PolicyDocument{
People: []policy.PersonPolicy{administrator},
Circles: []policy.CirclePolicy{{CircleID: "sales"}},
})
declared := map[string]bool{}
const hostRoot = "/workspace"
for _, directory := range security.POSIXStateForPolicy(document, hostRoot).Directories {
declared[directory.Path] = true
}
personAccess := policy.PolicyProjectionService{}.ReplacePolicyProjectionTransactionally(document).PersonAccessByPersonID["person-1"]
for _, scope := range memory.ScopesToSearch(personAccess, nil) {
path, errorValue := stores.Path(scope)
if errorValue != nil {
t.Fatalf("path for %+v: %v", scope, errorValue)
}
directory := strings.Replace(filepath.Dir(path), root, hostRoot, 1)
if !declared[directory] {
t.Fatalf("memory for %s %q sits in %s, which no POSIX declaration sets up, so the person cannot open it", scope.Kind, scope.ID, directory)
}
}
}