Vectrum
Sign In
93 lines · 3.0 KB · Go
package statedir

import (
	"os"
	"path/filepath"
	"testing"
)

// Chats are filed under the config directory, one directory per root, and
// never inside the root itself.
func TestChatsLivesUnderTheConfigDirectory(t *testing.T) {
	cfg := t.TempDir()
	t.Setenv("XDG_CONFIG_HOME", cfg)

	got, err := Chats("/home/someone/src/app")
	if err != nil {
		t.Fatal(err)
	}
	if want := filepath.Join(cfg, ChatsDir, "-home-someone-src-app"); got != want {
		t.Errorf("Chats = %q, want %q", got, want)
	}
	other, _ := Chats("/home/someone/src/other")
	if other == got {
		t.Error("two roots share one chats directory")
	}
}

// What an older build left in .codey/ is carried over, so -resume still finds
// yesterday's conversation and ↑ still finds yesterday's command.
func TestMigrateChatsMovesSessionsAndHistory(t *testing.T) {
	root := t.TempDir()
	dir := filepath.Join(t.TempDir(), "chats")
	mkdirWith(t, root, filepath.Join(Dir, SessionsSubdir), "s1.json", `{"id":"s1"}`)
	mkdirWith(t, root, filepath.Join(Dir, SessionsSubdir), "s2.json", `{"id":"s2"}`)
	mkdirWith(t, root, Dir, HistoryFile, "\"go test\"\n")
	mkdirWith(t, root, Dir, "events.jsonl", "{}\n")

	moved, err := MigrateChats(root, dir)
	if err != nil {
		t.Fatalf("MigrateChats: %v", err)
	}
	if moved != 3 {
		t.Errorf("moved = %d, want 3", moved)
	}
	if got := read(t, filepath.Join(dir, "s1.json")); got != `{"id":"s1"}` {
		t.Errorf("s1.json = %q", got)
	}
	if got := read(t, filepath.Join(dir, HistoryFile)); got != "\"go test\"\n" {
		t.Errorf("history = %q", got)
	}
	if _, err := os.Lstat(filepath.Join(root, Dir, SessionsSubdir)); err == nil {
		t.Error("the emptied sessions directory was left behind")
	}
	// The event log is about the repository and stays with it.
	if _, err := os.Lstat(filepath.Join(root, Dir, "events.jsonl")); err != nil {
		t.Errorf("events.jsonl moved or lost: %v", err)
	}
}

// A session at both ends has been written in both places, and neither copy may
// be overwritten.
func TestMigrateChatsLeavesAClashWhereItIs(t *testing.T) {
	root := t.TempDir()
	dir := filepath.Join(t.TempDir(), "chats")
	mkdirWith(t, root, filepath.Join(Dir, SessionsSubdir), "s1.json", "old")
	mkdirWith(t, dir, ".", "s1.json", "new")

	moved, err := MigrateChats(root, dir)
	if err != nil {
		t.Fatalf("MigrateChats: %v", err)
	}
	if moved != 0 {
		t.Errorf("moved = %d, want 0", moved)
	}
	if got := read(t, filepath.Join(dir, "s1.json")); got != "new" {
		t.Errorf("destination = %q, want it untouched", got)
	}
	if got := read(t, filepath.Join(root, Dir, SessionsSubdir, "s1.json")); got != "old" {
		t.Errorf("source = %q, want it left in place", got)
	}
}

// The common case: nothing to move, and nothing created.
func TestMigrateChatsWithNothingToMove(t *testing.T) {
	dir := filepath.Join(t.TempDir(), "chats")
	moved, err := MigrateChats(t.TempDir(), dir)
	if err != nil || moved != 0 {
		t.Fatalf("MigrateChats = %d, %v; want 0, nil", moved, err)
	}
	if _, err := os.Lstat(dir); err == nil {
		t.Error("created a chats directory with nothing to put in it")
	}
}