Sybren A. Stüvel 01c45afc20 Manager: explicitly store timestamps as UTC
SQLite doesn't handle timezones by default, when you just use something
like `date1 < date2`, for example. This makes GORM explicitly use UTC
timestamps for the `CreatedAt`, `UpdatedAt`, and `DeletedAt` fields.
Our own code should also use UTC when saving timestamps. That way all
datetimes in the database are in the same timezone, and can be compared
naievely.
2022-06-13 12:10:11 +02:00

170 lines
5.5 KiB
Go

// Package persistence provides the database interface for Flamenco Manager.
package persistence
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"git.blender.org/flamenco/internal/uuid"
"git.blender.org/flamenco/pkg/api"
)
func TestCreateFetchWorker(t *testing.T) {
ctx, cancel, db := persistenceTestFixtures(t, 1*time.Second)
defer cancel()
// Test fetching non-existent worker
fetchedWorker, err := db.FetchWorker(ctx, "dabf67a1-b591-4232-bf73-0b8de2a9488e")
assert.ErrorIs(t, err, ErrWorkerNotFound)
assert.Nil(t, fetchedWorker)
// Test existing worker
w := Worker{
UUID: uuid.New(),
Name: "дрон",
Address: "fe80::5054:ff:fede:2ad7",
Platform: "linux",
Software: "3.0",
Status: api.WorkerStatusAwake,
SupportedTaskTypes: "blender,ffmpeg,file-management",
}
err = db.CreateWorker(ctx, &w)
assert.NoError(t, err)
fetchedWorker, err = db.FetchWorker(ctx, w.UUID)
assert.NoError(t, err)
assert.NotNil(t, fetchedWorker)
// Test contents of fetched job
assert.Equal(t, w.UUID, fetchedWorker.UUID)
assert.Equal(t, w.Name, fetchedWorker.Name)
assert.Equal(t, w.Address, fetchedWorker.Address)
assert.Equal(t, w.Platform, fetchedWorker.Platform)
assert.Equal(t, w.Software, fetchedWorker.Software)
assert.Equal(t, w.Status, fetchedWorker.Status)
assert.EqualValues(t, w.SupportedTaskTypes, fetchedWorker.SupportedTaskTypes)
}
func TestSaveWorker(t *testing.T) {
ctx, cancel, db := persistenceTestFixtures(t, 1*time.Second)
defer cancel()
w := Worker{
UUID: uuid.New(),
Name: "дрон",
Address: "fe80::5054:ff:fede:2ad7",
Platform: "linux",
Software: "3.0",
Status: api.WorkerStatusAwake,
SupportedTaskTypes: "blender,ffmpeg,file-management",
}
err := db.CreateWorker(ctx, &w)
assert.NoError(t, err)
fetchedWorker, err := db.FetchWorker(ctx, w.UUID)
assert.NoError(t, err)
assert.NotNil(t, fetchedWorker)
// Update all updatable fields of the Worker
updatedWorker := *fetchedWorker
updatedWorker.Name = "7 မှ 9"
updatedWorker.Address = "fe80::cafe:f00d"
updatedWorker.Platform = "windows"
updatedWorker.Software = "3.1"
updatedWorker.Status = api.WorkerStatusAsleep
updatedWorker.SupportedTaskTypes = "blender,ffmpeg,file-management,misc"
// Saving only the status should just do that.
err = db.SaveWorkerStatus(ctx, &updatedWorker)
assert.NoError(t, err)
assert.Equal(t, "7 မှ 9", updatedWorker.Name, "Saving status should not touch the name")
// Check saved worker
fetchedWorker, err = db.FetchWorker(ctx, w.UUID)
assert.NoError(t, err)
assert.NotNil(t, fetchedWorker)
assert.Equal(t, updatedWorker.Status, fetchedWorker.Status, "new status should have been saved")
assert.NotEqual(t, updatedWorker.Name, fetchedWorker.Name, "non-status fields should not have been updated")
// Saving the entire worker should save everything.
err = db.SaveWorker(ctx, &updatedWorker)
assert.NoError(t, err)
// Check saved worker
fetchedWorker, err = db.FetchWorker(ctx, w.UUID)
assert.NoError(t, err)
assert.NotNil(t, fetchedWorker)
assert.Equal(t, updatedWorker.Status, fetchedWorker.Status, "new status should have been saved")
assert.Equal(t, updatedWorker.Name, fetchedWorker.Name, "non-status fields should also have been updated")
assert.Equal(t, updatedWorker.Software, fetchedWorker.Software, "non-status fields should also have been updated")
}
func TestFetchWorkers(t *testing.T) {
ctx, cancel, db := persistenceTestFixtures(t, 1*time.Second)
defer cancel()
// No workers
workers, err := db.FetchWorkers(ctx)
if !assert.NoError(t, err) {
t.Fatal("error fetching empty list of workers, no use in continuing the test")
}
assert.Empty(t, workers)
linuxWorker := Worker{
UUID: uuid.New(),
Name: "дрон",
Address: "fe80::5054:ff:fede:2ad7",
Platform: "linux",
Software: "3.0",
Status: api.WorkerStatusAwake,
SupportedTaskTypes: "blender,ffmpeg,file-management",
}
// One worker:
err = db.CreateWorker(ctx, &linuxWorker)
assert.NoError(t, err)
assert.Equal(t, time.Now().UTC().Location(), linuxWorker.CreatedAt.Location(),
"Timestamps should be using UTC timezone")
workers, err = db.FetchWorkers(ctx)
assert.NoError(t, err)
if assert.Len(t, workers, 1) {
// FIXME: this fails, because the fetched timestamps have nil location instead of UTC.
// assert.Equal(t, time.Now().UTC().Location(), workers[0].CreatedAt.Location(),
// "Timestamps should be using UTC timezone")
assert.Equal(t, linuxWorker.UUID, workers[0].UUID)
assert.Equal(t, linuxWorker.Name, workers[0].Name)
assert.Equal(t, linuxWorker.Address, workers[0].Address)
assert.Equal(t, linuxWorker.Status, workers[0].Status)
assert.Equal(t, linuxWorker.SupportedTaskTypes, workers[0].SupportedTaskTypes)
}
// Two workers:
windowsWorker := Worker{
UUID: uuid.New(),
Name: "очиститель окон",
Address: "fe80::c000:d000:::3",
Platform: "windows",
Software: "3.0",
Status: api.WorkerStatusOffline,
SupportedTaskTypes: "blender,ffmpeg,file-management",
}
err = db.CreateWorker(ctx, &windowsWorker)
assert.NoError(t, err)
workers, err = db.FetchWorkers(ctx)
assert.NoError(t, err)
if assert.Len(t, workers, 2) {
assert.Equal(t, linuxWorker.UUID, workers[0].UUID)
assert.Equal(t, windowsWorker.UUID, workers[1].UUID)
}
}