v0.10.0: ports and adapters refactor
- Extract shared manifest types into internal/manifest/types leaf package. - Extract SQLite adapter into internal/manifest/sqlite. - Extract JSONL adapter into internal/manifest/jsonl. - Isolate modernc.org/sqlite import to sqlite/adapter.go. - Add adapter-backed registry with manifest.Default. - Adapter-agnostic ConvertManifest in types/. - MemoryAdapter for in-memory manifest testing. - CLI uses manifest.Default registry directly. - SQLite LogWriter type assertion moved into SQLiteAdapter. - Manifest interface includes Entries(); EntryReader removed. - No behavior changes. 100% coverage across all 6 packages.
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
|
||||
"gitea.k3s.k0.nu/tools/photocli/internal/manifest/types"
|
||||
)
|
||||
|
||||
func TestAdapter(t *testing.T) {
|
||||
a := Adapter{}
|
||||
if a.Format() != types.FormatSQLite {
|
||||
t.Fatal("expected SQLite format")
|
||||
}
|
||||
if len(a.Aliases()) != 2 {
|
||||
t.Fatal("expected 2 aliases")
|
||||
}
|
||||
dir := t.TempDir()
|
||||
if a.Path(dir) != Path(dir) {
|
||||
t.Fatal("expected path match")
|
||||
}
|
||||
if a.Exists(dir) {
|
||||
t.Fatal("expected not to exist in empty dir")
|
||||
}
|
||||
m, err := a.Open(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
w, err := a.OpenLogWriter(nil, dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Close()
|
||||
}
|
||||
|
||||
func TestAdapterOpenLogWriterSQLite(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := Load(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer m.Close()
|
||||
w, err := Adapter{}.OpenLogWriter(m, dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer w.Close()
|
||||
if _, ok := w.(*LogWriter); !ok {
|
||||
t.Fatalf("expected sqlite log writer, got %T", w)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreLoadEmpty(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m == nil {
|
||||
t.Fatal("expected non-nil store")
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreLoadNonexistent(t *testing.T) {
|
||||
m, err := Load("/nonexistent/path")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m == nil {
|
||||
t.Fatal("expected non-nil store")
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreAddHasSaveClose(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("sid1", "sfile.jpg", 99, "azure")
|
||||
if !m.Has("sid1") {
|
||||
t.Fatal("expected Has to return true")
|
||||
}
|
||||
if m.Has("nope") {
|
||||
t.Fatal("expected Has to return false")
|
||||
}
|
||||
if err := m.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreRoundTrip(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := Load(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("rid1", "rfile1.jpg", 10, "aws")
|
||||
m.Add("rid2", "rfile2.jpg", 20, "gcs")
|
||||
if err := m.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
|
||||
m2, err := Load(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m2.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer m2.Close()
|
||||
if !m2.Has("rid1") {
|
||||
t.Fatal("expected rid1 after reload")
|
||||
}
|
||||
if !m2.Has("rid2") {
|
||||
t.Fatal("expected rid2 after reload")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreEntries(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer m.Close()
|
||||
m.Add("se1", "sf1.jpg", 1, "sc1")
|
||||
m.Add("se2", "sf2.jpg", 2, "sc2")
|
||||
entries := m.Entries()
|
||||
if len(entries) != 2 {
|
||||
t.Fatalf("expected 2 entries, got %d", len(entries))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreCloseIdempotent(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreOpenAppendIdempotent(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreManifestFormat(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.ManifestFormat() != types.FormatSQLite {
|
||||
t.Fatal("expected SQLite format")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreSave(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.Save(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreOpenAppendCreateDir(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
subdir := filepath.Join(dir, "subdir")
|
||||
m, err := Load(subdir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreCloseWithoutOpen(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestStoreEntriesWithoutOpen(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
entries := m.Entries()
|
||||
if entries != nil {
|
||||
t.Errorf("Entries without open should return nil, got %v", entries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreHasWithoutOpen(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.Has("x") {
|
||||
t.Fatal("Has should return false without open")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreAddEntryWithoutOpen(t *testing.T) {
|
||||
m, err := Load(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.AddEntry(types.Entry{ID: "x", Filename: "f.jpg"})
|
||||
}
|
||||
|
||||
func TestSetOpener(t *testing.T) {
|
||||
old := SetOpener(func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
return nil, fmt.Errorf("test")
|
||||
})
|
||||
if old != nil {
|
||||
t.Fatal("expected nil old opener")
|
||||
}
|
||||
restore := SetOpener(old)
|
||||
if restore == nil {
|
||||
t.Fatal("expected non-nil restore")
|
||||
}
|
||||
SetOpener(nil)
|
||||
}
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
if FileExists(dir) {
|
||||
t.Fatal("expected false for directory")
|
||||
}
|
||||
if FileExists("/nonexistent/file") {
|
||||
t.Fatal("expected false for nonexistent")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogWriterClose(t *testing.T) {
|
||||
w := &LogWriter{}
|
||||
w.Close()
|
||||
}
|
||||
|
||||
func TestOpenerWithOverride(t *testing.T) {
|
||||
SetOpener(func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
return nil, nil
|
||||
})
|
||||
if opener() == nil {
|
||||
t.Fatal("expected override")
|
||||
}
|
||||
SetOpener(nil)
|
||||
}
|
||||
|
||||
func TestLogWriterCloseDirect(t *testing.T) {
|
||||
(&LogWriter{}).Close()
|
||||
}
|
||||
Reference in New Issue
Block a user