v0.5.0: manifests, filters, logging, docs
This commit is contained in:
@@ -0,0 +1,402 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func TestSetJSONLSaveHook(t *testing.T) {
|
||||
old := SetJSONLSaveHook(func() error { return fmt.Errorf("hook error") })
|
||||
if old != nil {
|
||||
t.Error("expected nil old hook")
|
||||
}
|
||||
restore := SetJSONLSaveHook(old)
|
||||
if restore == nil {
|
||||
t.Error("expected non-nil restore function")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONLSaveHookError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m := LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
old := SetJSONLSaveHook(func() error { return fmt.Errorf("hook error") })
|
||||
defer SetJSONLSaveHook(old)
|
||||
if err := m.Save(); err == nil {
|
||||
t.Error("expected hook error from Save")
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestJSONLSyncFuncError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m := LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.syncFunc = func() error { return fmt.Errorf("sync func error") }
|
||||
if err := m.Save(); err == nil {
|
||||
t.Error("expected syncFunc error from Save")
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestSQLiteOpenAppendSQLError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.open = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
return nil, fmt.Errorf("simulated open error")
|
||||
}
|
||||
if err := m.OpenAppend(); err == nil {
|
||||
t.Error("expected error from sql.Open failure")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteOpenAppendCreateTableError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
realOpen := m.open
|
||||
m.open = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
db, err := realOpen(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.Close()
|
||||
return db, nil
|
||||
}
|
||||
if err := m.OpenAppend(); err == nil {
|
||||
t.Error("expected error from closed DB CREATE TABLE")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteHasAfterClose(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.Close()
|
||||
if m.Has("x1") {
|
||||
t.Error("Has should return false after Close")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteEntriesAfterClose(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.Close()
|
||||
entries := m.Entries()
|
||||
if entries != nil {
|
||||
t.Errorf("Entries should return nil after Close, got %d entries", len(entries))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteOpenAppendMkdirAllError(t *testing.T) {
|
||||
m, err := LoadSQLite("/proc/cannot-write")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err == nil {
|
||||
t.Error("expected error creating dir under /proc")
|
||||
m.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteOpenAppendNilOpener(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.open = nil
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Errorf("expected nil opener to use sql.Open fallback, got err: %v", err)
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestSQLiteOpenAppendCreateIndexError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
realOpen := m.open
|
||||
m.open = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
db, err := realOpen(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.Close()
|
||||
return db, nil
|
||||
}
|
||||
if err := m.OpenAppend(); err == nil {
|
||||
t.Error("expected error from closed DB")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteHasQueryError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
closedDB := m.db
|
||||
closedDB.Close()
|
||||
result := m.Has("x1")
|
||||
if result {
|
||||
t.Error("Has should return false with broken DB connection")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteEntriesQueryError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
closedDB := m.db
|
||||
closedDB.Close()
|
||||
entries := m.Entries()
|
||||
if entries == nil {
|
||||
t.Error("Entries should return non-nil map with broken DB connection")
|
||||
}
|
||||
if len(entries) != 0 {
|
||||
t.Errorf("Entries should be empty with broken DB connection, got %d", len(entries))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteHasQueryErrorWithOpenDB(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
closedDB := m.db
|
||||
closedDB.Close()
|
||||
if m.Has("x1") {
|
||||
t.Error("Has should return false with closed DB")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteEntriesQueryErrorWithOpenDB(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
closedDB := m.db
|
||||
closedDB.Close()
|
||||
entries := m.Entries()
|
||||
if entries != nil && len(entries) != 0 {
|
||||
t.Errorf("Entries should be empty with closed DB, got %d", len(entries))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSQLiteCreateIndexError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
realOpen := m.open
|
||||
callCount := 0
|
||||
m.open = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
db, err := realOpen(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m.execFunc = func(query string, args ...any) (sql.Result, error) {
|
||||
callCount++
|
||||
if callCount == 2 {
|
||||
return nil, fmt.Errorf("injected CREATE INDEX error")
|
||||
}
|
||||
return db.Exec(query, args...)
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
if err := m.OpenAppend(); err == nil {
|
||||
t.Error("expected error from CREATE INDEX")
|
||||
m.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromJSONLOpenAppendSQLError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m := LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.Close()
|
||||
oldOpen := sqliteOpenFunc
|
||||
sqliteOpenFunc = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
return nil, fmt.Errorf("simulated sqlite open error")
|
||||
}
|
||||
defer func() { sqliteOpenFunc = oldOpen }()
|
||||
_, err := ConvertFromJSONL(dir)
|
||||
if err == nil {
|
||||
t.Error("expected error from dst.OpenAppend during ConvertFromJSONL")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromJSONLDstOpenAppendError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m := LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.Close()
|
||||
realOpen := defaultSQLOpener()
|
||||
oldOpen := sqliteOpenFunc
|
||||
sqliteOpenFunc = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
db, err := realOpen(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db.Close()
|
||||
return db, nil
|
||||
}
|
||||
defer func() { sqliteOpenFunc = oldOpen }()
|
||||
_, err := ConvertFromJSONL(dir)
|
||||
if err == nil {
|
||||
t.Error("expected error from dst.OpenAppend during ConvertFromJSONL")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromSQLiteSrcOpenAppendError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
src, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := src.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
src.Add("x1", "photo.jpg", 1024, "local")
|
||||
src.Close()
|
||||
realOpen := defaultSQLOpener()
|
||||
callCount := 0
|
||||
oldOpen := sqliteOpenFunc
|
||||
sqliteOpenFunc = func(driverName, dataSourceName string) (*sql.DB, error) {
|
||||
callCount++
|
||||
db, err := realOpen(driverName, dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if callCount > 0 {
|
||||
db.Close()
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
defer func() { sqliteOpenFunc = oldOpen }()
|
||||
_, err = ConvertFromSQLite(dir)
|
||||
if err == nil {
|
||||
t.Error("expected error from src.OpenAppend during ConvertFromSQLite")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromSQLiteDstOpenAppendError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
src, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := src.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
src.Add("x1", "photo.jpg", 1024, "local")
|
||||
src.Close()
|
||||
jsonlPath := JSONLPath(dir)
|
||||
f, err := os.Create(jsonlPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
os.Chmod(jsonlPath, 0444)
|
||||
defer os.Chmod(jsonlPath, 0644)
|
||||
_, err = ConvertFromSQLite(dir)
|
||||
if err == nil {
|
||||
t.Error("expected error from dst.OpenAppend during ConvertFromSQLite")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONLSaveError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
m := LoadJSONL(dir)
|
||||
if err := m.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m.Add("x1", "photo.jpg", 1024, "local")
|
||||
m.file.Close()
|
||||
if err := m.Save(); err == nil {
|
||||
t.Error("expected Sync error on closed file")
|
||||
}
|
||||
m.Close()
|
||||
}
|
||||
|
||||
func TestConvertFromSQLiteSaveError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
src, err := LoadSQLite(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := src.OpenAppend(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
src.Add("x1", "photo.jpg", 1024, "local")
|
||||
src.Close()
|
||||
oldHook := jsonlSaveHook
|
||||
jsonlSaveHook = func() error { return fmt.Errorf("simulated sync error") }
|
||||
defer func() { jsonlSaveHook = oldHook }()
|
||||
_, err = ConvertFromSQLite(dir)
|
||||
if err == nil {
|
||||
t.Error("expected error from dst.Save during ConvertFromSQLite")
|
||||
}
|
||||
if err != nil && !strings.Contains(err.Error(), "save jsonl") {
|
||||
t.Errorf("expected save jsonl error, got: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user