From 2f718206f9b35e7543cb6759b4ec1d403f2f8c49 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 25 Feb 2026 09:42:40 +0100 Subject: [PATCH] fix: add TestMain to caldav tests and fix session conflicts Add a proper main_test.go for the caldav test package that initializes the logger, config, test database, and event system. Previously, these were initialized inline in TestSubTask_Create and TestSubTask_Update relied on running after it (fragile test ordering). Fix session handling in TestSubTask_Update: close the read session before calling UpdateResource (which creates its own internal session) to avoid SQLite lock conflicts from concurrent transactions. --- pkg/routes/caldav/listStorageProvider_test.go | 49 ++++++++++++------- pkg/routes/caldav/main_test.go | 39 +++++++++++++++ 2 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 pkg/routes/caldav/main_test.go diff --git a/pkg/routes/caldav/listStorageProvider_test.go b/pkg/routes/caldav/listStorageProvider_test.go index 9ac292e71..caa92fec7 100644 --- a/pkg/routes/caldav/listStorageProvider_test.go +++ b/pkg/routes/caldav/listStorageProvider_test.go @@ -21,9 +21,7 @@ package caldav import ( "testing" - "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/db" - "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/user" @@ -40,11 +38,6 @@ func TestSubTask_Create(t *testing.T) { Email: "user15@example.com", } - config.InitDefaultConfig() - files.InitTests() - user.InitTests() - models.SetupTests() - // // Create a subtask // @@ -255,8 +248,6 @@ func TestSubTask_Update(t *testing.T) { // t.Run("edit subtask", func(t *testing.T) { db.LoadAndAssertFixtures(t) - s := db.NewSession() - defer s.Close() // Edit the subtask: const taskUID = "uid-caldav-test-child-task" @@ -274,9 +265,15 @@ LAST-MODIFIED:20230301T073337Z RELATED-TO;RELTYPE=PARENT:uid-caldav-test-parent-task END:VTODO END:VCALENDAR` + + // Read the task in its own session, then close it before UpdateResource + // which creates its own internal session (avoids SQLite lock conflict) + s := db.NewSession() tasks, err := models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task := tasks[0] + s.Close() + storage := &VikunjaCaldavProjectStorage{ project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: 36}}, task: task, @@ -292,7 +289,9 @@ END:VCALENDAR` assert.Contains(t, content, "UID:"+taskUID) assert.Contains(t, content, "RELATED-TO;RELTYPE=PARENT:uid-caldav-test-parent-task") - // Get the task from the DB: + // Get the task from the DB with a new session: + s = db.NewSession() + defer s.Close() tasks, err = models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task = tasks[0] @@ -308,8 +307,6 @@ END:VCALENDAR` // t.Run("edit parent", func(t *testing.T) { db.LoadAndAssertFixtures(t) - s := db.NewSession() - defer s.Close() // Edit the parent task: const taskUID = "uid-caldav-test-parent-task" @@ -328,9 +325,13 @@ RELATED-TO;RELTYPE=CHILD:uid-caldav-test-child-task RELATED-TO;RELTYPE=CHILD:uid-caldav-test-child-task-2 END:VTODO END:VCALENDAR` + + s := db.NewSession() tasks, err := models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task := tasks[0] + s.Close() + storage := &VikunjaCaldavProjectStorage{ project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: 36}}, task: task, @@ -341,7 +342,9 @@ END:VCALENDAR` _, err = storage.UpdateResource(taskUID, taskContent) require.NoError(t, err) - // Get the task from the DB: + // Get the task from the DB with a new session: + s = db.NewSession() + defer s.Close() tasks, err = models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task = tasks[0] @@ -359,8 +362,6 @@ END:VCALENDAR` // t.Run("edit subtask change parent", func(t *testing.T) { db.LoadAndAssertFixtures(t) - s := db.NewSession() - defer s.Close() // Edit the subtask: const taskUID = "uid-caldav-test-child-task" @@ -378,9 +379,13 @@ LAST-MODIFIED:20230301T073337Z RELATED-TO;RELTYPE=PARENT:uid-caldav-test-parent-task-2 END:VTODO END:VCALENDAR` + + s := db.NewSession() tasks, err := models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task := tasks[0] + s.Close() + storage := &VikunjaCaldavProjectStorage{ project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: 36}}, task: task, @@ -396,7 +401,9 @@ END:VCALENDAR` assert.Contains(t, content, "UID:"+taskUID) assert.Contains(t, content, "RELATED-TO;RELTYPE=PARENT:uid-caldav-test-parent-task-2") - // Get the task from the DB: + // Get the task from the DB with a new session: + s = db.NewSession() + defer s.Close() tasks, err = models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task = tasks[0] @@ -421,8 +428,6 @@ END:VCALENDAR` // t.Run("edit subtask remove parent", func(t *testing.T) { db.LoadAndAssertFixtures(t) - s := db.NewSession() - defer s.Close() // Edit the subtask: const taskUID = "uid-caldav-test-child-task" @@ -439,9 +444,13 @@ CREATED:20230301T073337Z LAST-MODIFIED:20230301T073337Z END:VTODO END:VCALENDAR` + + s := db.NewSession() tasks, err := models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task := tasks[0] + s.Close() + storage := &VikunjaCaldavProjectStorage{ project: &models.ProjectWithTasksAndBuckets{Project: models.Project{ID: 36}}, task: task, @@ -457,7 +466,9 @@ END:VCALENDAR` assert.Contains(t, content, "UID:"+taskUID) assert.NotContains(t, content, "RELATED-TO;RELTYPE=PARENT:uid-caldav-test-parent-task") - // Get the task from the DB: + // Get the task from the DB with a new session: + s = db.NewSession() + defer s.Close() tasks, err = models.GetTasksByUIDs(s, []string{taskUID}, u) require.NoError(t, err) task = tasks[0] diff --git a/pkg/routes/caldav/main_test.go b/pkg/routes/caldav/main_test.go new file mode 100644 index 000000000..d97456b6b --- /dev/null +++ b/pkg/routes/caldav/main_test.go @@ -0,0 +1,39 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-present Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package caldav + +import ( + "os" + "testing" + + "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/files" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" + "code.vikunja.io/api/pkg/user" +) + +func TestMain(m *testing.M) { + log.InitLogger() + config.InitDefaultConfig() + files.InitTests() + user.InitTests() + models.SetupTests() + events.Fake() + os.Exit(m.Run()) +}