PiwigoDirectoryUploader/internal/pkg/datastore/datastore_test.go

492 lines
13 KiB
Go

/*
* Copyright (C) 2019 Philipp Haefelfinger (http://www.haefelfinger.ch/). All Rights Reserved.
* This application is licensed under GPLv2. See the LICENSE file in the root directory of the project.
*/
package datastore
import (
"os"
"strings"
"testing"
"time"
)
var databaseFile = "./metadatatest.db"
var dbinitOk bool
func TestDataStoreInitialize(t *testing.T) {
_ = setupDatabase(t)
cleanupDatabase(t)
}
func Test_save_and_load_metadata(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
filePath := "blah/foo/bar.jpg"
img := getExampleImageMetadata(filePath)
saveImageShouldNotFail("insert", dataStore, img, t)
img.ImageId = 1
imgLoad := loadMetadataShouldNotFail("insert", dataStore, filePath, t)
ensureMetadataAreEqual("insert", img, imgLoad, t)
// updated the image again
img.Md5Sum = "123456"
saveImageShouldNotFail("update", dataStore, img, t)
imgLoad = loadMetadataShouldNotFail("update", dataStore, filePath, t)
ensureMetadataAreEqual("update", img, imgLoad, t)
}
func Test_save_and_query_for_all_entries(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img1 := getExampleImageMetadata("blah/foo/bar.jpg")
img2 := getExampleImageMetadata("blah/foo/bar2.jpg")
img2.DeleteRequired = true
saveImageShouldNotFail("allimages", dataStore, img1, t)
img1.ImageId = 1
saveImageShouldNotFail("allimages", dataStore, img2, t)
img2.ImageId = 2
images, err := dataStore.ImageMetadataAll()
if err != nil {
t.Fatalf("Could not query images to upload! %s", err)
}
if len(images) != 2 {
t.Fatalf("Got incorrect number of images (%d). Expected two.", len(images))
}
imgLoad := images[0]
ensureMetadataAreEqual("allimages", img1, imgLoad, t)
}
func Test_save_and_query_for_upload_records(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img := getExampleImageMetadata("blah/foo/bar.jpg")
saveImageShouldNotFail("toupload", dataStore, img, t)
img.ImageId = 1
images, err := dataStore.ImageMetadataToUpload()
if err != nil {
t.Fatalf("Could not query images to upload! %s", err)
}
if len(images) != 1 {
t.Fatal("Did not get any saved images to upload!")
}
imgLoad := images[0]
ensureMetadataAreEqual("toupload", img, imgLoad, t)
}
func Test_save_and_query_for_upload_records_do_not_contain_images_to_delete(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img1 := getExampleImageMetadata("blah/foo/bar.jpg")
img2 := getExampleImageMetadata("blah/foo/bar2.jpg")
img2.DeleteRequired = true
saveImageShouldNotFail("toupload1", dataStore, img1, t)
img1.ImageId = 1
saveImageShouldNotFail("toupload2", dataStore, img2, t)
img2.ImageId = 2
images, err := dataStore.ImageMetadataToUpload()
if err != nil {
t.Fatalf("Could not query images to upload! %s", err)
}
if len(images) > 1 {
t.Fatal("Got more than one image to upload but only one is expected")
}
if len(images) != 1 {
t.Fatal("Did not get the saved images to upload!")
}
imgLoad := images[0]
ensureMetadataAreEqual("toupload", img1, imgLoad, t)
}
func Test_save_and_query_for_deleted_records_do_contain_images(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img1 := getExampleImageMetadata("blah/foo/bar.jpg")
img1.UploadRequired = false
img1.DeleteRequired = true
saveImageShouldNotFail("todelete", dataStore, img1, t)
img1.ImageId = 1
images, err := dataStore.ImageMetadataToDelete()
if err != nil {
t.Fatalf("Could not query images to delete! %s", err)
}
if len(images) > 1 {
t.Fatal("Got more than one image to delete but only one is expected")
}
if len(images) < 1 {
t.Fatal("Got no image to delete but one is expected!")
}
imgLoad := images[0]
ensureMetadataAreEqual("todelete", img1, imgLoad, t)
}
func Test_load_metadata_not_found(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
filePath := "blah/foo/bar.jpg"
imgLoad, err := dataStore.ImageMetadata(filePath)
if err != ErrorRecordNotFound {
t.Errorf("Unexpected error on loading non existing file %s: %s", filePath, err)
}
if imgLoad.ImageId > 0 {
t.Error("Found an image metadata that should not exist on an emtpy database.")
}
}
func Test_unique_index_on_relativeFilePath(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img := getExampleImageMetadata("blah/foo/bar.jpg")
saveImageShouldNotFail("insert", dataStore, img, t)
err := dataStore.SaveImageMetadata(img)
if err == nil {
t.Errorf("Could save duplicated image metadata. Expected error but got none!")
}
// check if the error contains the expected column as name. If not, this indicates another problem than
// the expected duplicated insert error.
if !strings.Contains(err.Error(), "fullImagePath") {
t.Errorf("Got a unexpected error on saving duplicate records: %s", err)
}
}
func Test_update_piwigoId_by_checksum(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
filePath := "blah/foo/bar.jpg"
img := getExampleImageMetadata(filePath)
saveImageShouldNotFail("SavePiwigoIdAndUpdateUploadFlag", dataStore, img, t)
img.ImageId = 1
img.PiwigoId = 1234
img.UploadRequired = false
err := dataStore.SavePiwigoIdAndUpdateUploadFlag(img.Md5Sum, img.PiwigoId)
if err != nil {
t.Errorf("SavePiwigoIdAndUpdateUploadFlag: Could not update piwigo id: %s", err)
}
imgLoad := loadMetadataShouldNotFail("update", dataStore, filePath, t)
ensureMetadataAreEqual("SavePiwigoIdAndUpdateUploadFlag", img, imgLoad, t)
}
func Test_update_piwigoId_by_checksum_found_no_image(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
filePath := "blah/foo/bar.jpg"
img := getExampleImageMetadata(filePath)
saveImageShouldNotFail("SavePiwigoIdAndUpdateUploadFlag", dataStore, img, t)
img.ImageId = 1
img.PiwigoId = 0
img.UploadRequired = true
err := dataStore.SavePiwigoIdAndUpdateUploadFlag(img.Md5Sum, img.PiwigoId)
if err != nil {
t.Errorf("SavePiwigoIdAndUpdateUploadFlag: Could not update piwigo id: %s", err)
}
imgLoad := loadMetadataShouldNotFail("update", dataStore, filePath, t)
ensureMetadataAreEqual("SavePiwigoIdAndUpdateUploadFlag", img, imgLoad, t)
}
func Test_deleteMarkedImages_should_remove_records(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
img1 := getExampleImageMetadata("blah/foo/bar.jpg")
img2 := getExampleImageMetadata("blah/foo/bar2.jpg")
img2.DeleteRequired = true
saveImageShouldNotFail("allimages", dataStore, img1, t)
img1.ImageId = 1
saveImageShouldNotFail("allimages", dataStore, img2, t)
img2.ImageId = 2
err := dataStore.DeleteMarkedImages()
if err != nil {
t.Fatalf("Could not delete marked records! %s", err)
}
images, err := dataStore.ImageMetadataAll()
if err != nil {
t.Fatalf("Could not query images! %s", err)
}
if len(images) != 1 {
t.Fatalf("Got incorrect number of images (%d). Expected one.", len(images))
}
}
func Test_saveCategory_should_store_records(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
category := getExampleCategoryData("2019")
saveCategoryShouldNotFail("addcategory", dataStore, category, t)
category.CategoryId = 1
_, err := dataStore.GetCategoryByKey(category.Key)
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
}
func Test_saveCategory_should_store_multiple_records_with_piwigoid_zero(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
category1 := getExampleCategoryData("2019")
category1.PiwigoId = 0
category2 := getExampleCategoryData("2020")
category2.PiwigoId = 0
saveCategoryShouldNotFail("addcategory", dataStore, category1, t)
category1.CategoryId = 1
saveCategoryShouldNotFail("addcategory", dataStore, category2, t)
category2.CategoryId = 2
_, err := dataStore.GetCategoryByKey(category1.Key)
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
_, err = dataStore.GetCategoryByKey(category2.Key)
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
}
func Test_saveCategory_should_update_records(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
category := getExampleCategoryData("2019")
saveCategoryShouldNotFail("addcategory", dataStore, category, t)
category.CategoryId = 1
category.Name = "2019-1"
category.Key = category.Name
category.PiwigoId = 2
category.PiwigoParentId = 3
saveCategoryShouldNotFail("updatecategory", dataStore, category, t)
loadedCategory, err := dataStore.GetCategoryByKey(category.Key)
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
ensureLoadedCategoryIsExpectedCategory(loadedCategory, category, t)
}
func Test_GetCategoryByPiwigoId_should_return_category(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
category := getExampleCategoryData("2019")
saveCategoryShouldNotFail("getCategoryByPiwigoId", dataStore, category, t)
category.CategoryId = 1
loadedCategory, err := dataStore.GetCategoryByPiwigoId(category.PiwigoId)
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
ensureLoadedCategoryIsExpectedCategory(loadedCategory, category, t)
}
func Test_GetCategoriesToCreate(t *testing.T) {
if !dbinitOk {
t.Skip("Skipping test as TestDataStoreInitialize failed!")
}
dataStore := setupDatabase(t)
defer cleanupDatabase(t)
category := getExampleCategoryData("2019")
category.PiwigoId = 0
saveCategoryShouldNotFail("getCategoriesToCreate", dataStore, category, t)
category.CategoryId = 1
categories, err := dataStore.GetCategoriesToCreate()
if err != nil {
t.Fatalf("Could not query category! %s", err)
}
if len(categories) != 1 {
t.Error("Did not load categories to create correctly!")
}
ensureLoadedCategoryIsExpectedCategory(categories[0], category, t)
}
func saveImageShouldNotFail(action string, dataStore *LocalDataStore, img ImageMetaData, t *testing.T) {
err := dataStore.SaveImageMetadata(img)
if err != nil {
t.Errorf("%s: Could not save Metadata: %s", action, err)
}
}
func saveCategoryShouldNotFail(action string, dataStore *LocalDataStore, cat CategoryData, t *testing.T) {
err := dataStore.SaveCategory(cat)
if err != nil {
t.Errorf("%s: Could not save category: %s", action, err)
}
}
func loadMetadataShouldNotFail(action string, dataStore *LocalDataStore, filePath string, t *testing.T) ImageMetaData {
imgLoad, err := dataStore.ImageMetadata(filePath)
if err != nil {
t.Errorf("%s: Could not load saved Metadata: %s - %s", action, filePath, err)
}
return imgLoad
}
func ensureMetadataAreEqual(action string, img ImageMetaData, imgLoad ImageMetaData, t *testing.T) {
// check if both instances serialize to the same string representation
if img.String() != imgLoad.String() {
t.Errorf("%s: Invalid image loaded! expected (ignore ImageId) %s but got %s", action, img.String(), imgLoad.String())
}
}
func getExampleCategoryData(key string) CategoryData {
return CategoryData{
CategoryId: 0,
PiwigoId: 1,
Key: key,
Name: key,
PiwigoParentId: 0,
}
}
func getExampleImageMetadata(filePath string) ImageMetaData {
return ImageMetaData{
FullImagePath: filePath,
PiwigoId: 1,
Md5Sum: "aabbccddeeff",
LastChange: time.Now().UTC(),
Filename: "bar.jpg",
CategoryPath: "blah/foo",
CategoryPiwigoId: 100,
UploadRequired: true,
}
}
func cleanupDatabase(t *testing.T) {
err := os.Remove(databaseFile)
if err != nil {
t.Errorf("Failed remove test database %s: %s", databaseFile, err)
}
}
func setupDatabase(t *testing.T) *LocalDataStore {
dataStore := &LocalDataStore{}
err := dataStore.Initialize(databaseFile)
if err != nil {
t.Errorf("Failed to init datastore: %s", err)
return nil
}
dbinitOk = true
return dataStore
}
func ensureLoadedCategoryIsExpectedCategory(loaded CategoryData, expected CategoryData, t *testing.T) {
if loaded.Name != expected.Name {
t.Errorf("category update failed. Got: %s - want: %s", loaded.Name, expected.Name)
}
if loaded.Key != expected.Key {
t.Errorf("category update failed. Got: %s - want: %s", loaded.Key, expected.Key)
}
if loaded.PiwigoId != expected.PiwigoId {
t.Errorf("category update failed. Got: %d - want: %d", loaded.PiwigoId, expected.PiwigoId)
}
if loaded.PiwigoParentId != expected.PiwigoParentId {
t.Errorf("category update failed. Got: %d - want: %d", loaded.PiwigoParentId, expected.PiwigoParentId)
}
}