mirror of
https://github.com/StarFleetCPTN/GoMFT.git
synced 2026-09-08 15:41:20 +02:00
- Add Google Drive as a source and destination option in the configuration forms. - Implement Google Drive authentication flow and token management. - Update job and configuration handlers to support Google Drive-specific settings. - Enhance UI components to include Google Drive configuration templates. - Introduce new tests for Google Drive integration and ensure proper handling of authentication and configuration. - Update database migrations to accommodate new fields related to Google Drive configurations.
251 lines
6.9 KiB
Go
251 lines
6.9 KiB
Go
package db
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// TestDeleteTransferConfigEdgeCases tests edge cases for the DeleteTransferConfig function
|
|
func TestDeleteTransferConfigEdgeCases(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
// Create a test user
|
|
testUser := &User{
|
|
Email: "config-edge-test@example.com",
|
|
PasswordHash: "hashed_password",
|
|
LastPasswordChange: time.Now(),
|
|
}
|
|
err := db.CreateUser(testUser)
|
|
assert.NoError(t, err)
|
|
|
|
// Create multiple configs
|
|
configs := make([]*TransferConfig, 5)
|
|
for i := 0; i < 5; i++ {
|
|
config := &TransferConfig{
|
|
Name: fmt.Sprintf("Edge Config %d", i),
|
|
SourceType: "local",
|
|
SourcePath: fmt.Sprintf("/source/path/%d", i),
|
|
DestinationType: "local",
|
|
DestinationPath: fmt.Sprintf("/destination/path/%d", i),
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateTransferConfig(config)
|
|
assert.NoError(t, err)
|
|
configs[i] = config
|
|
}
|
|
|
|
// Delete them in reverse order
|
|
for i := 4; i >= 0; i-- {
|
|
err = db.DeleteTransferConfig(configs[i].ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify deletion
|
|
_, err = db.GetTransferConfig(configs[i].ID)
|
|
assert.Error(t, err, "Config should be deleted")
|
|
}
|
|
|
|
// Test deleting a config that has a job associated with it
|
|
configWithJob := &TransferConfig{
|
|
Name: "Config with Job",
|
|
SourceType: "local",
|
|
SourcePath: "/source/path/job",
|
|
DestinationType: "local",
|
|
DestinationPath: "/destination/path/job",
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateTransferConfig(configWithJob)
|
|
assert.NoError(t, err)
|
|
|
|
// Create a job for this config
|
|
job := &Job{
|
|
Name: "Job for Config",
|
|
ConfigID: configWithJob.ID,
|
|
Schedule: "0 * * * *",
|
|
Enabled: BoolPtr(true),
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateJob(job)
|
|
assert.NoError(t, err)
|
|
|
|
// Try to delete the config - this should fail due to foreign key constraint
|
|
err = db.DeleteTransferConfig(configWithJob.ID)
|
|
assert.Error(t, err, "Should not be able to delete config with associated jobs")
|
|
assert.Contains(t, err.Error(), "jobs are using this configuration", "Error should mention jobs")
|
|
|
|
// Delete the job first
|
|
err = db.DeleteJob(job.ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Now delete the config - this should succeed
|
|
err = db.DeleteTransferConfig(configWithJob.ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify deletion
|
|
_, err = db.GetTransferConfig(configWithJob.ID)
|
|
assert.Error(t, err, "Config should be deleted")
|
|
}
|
|
|
|
// TestDeleteJobEdgeCases tests edge cases for the DeleteJob function
|
|
func TestDeleteJobEdgeCases(t *testing.T) {
|
|
db := setupTestDB(t)
|
|
|
|
// Create a test user
|
|
testUser := &User{
|
|
Email: "job-edge-test@example.com",
|
|
PasswordHash: "hashed_password",
|
|
LastPasswordChange: time.Now(),
|
|
}
|
|
err := db.CreateUser(testUser)
|
|
assert.NoError(t, err)
|
|
|
|
// Create a test config
|
|
config := &TransferConfig{
|
|
Name: "Config for Job Edge Cases",
|
|
SourceType: "local",
|
|
SourcePath: "/source/path",
|
|
DestinationType: "local",
|
|
DestinationPath: "/destination/path",
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateTransferConfig(config)
|
|
assert.NoError(t, err)
|
|
|
|
// Create multiple jobs
|
|
jobs := make([]*Job, 5)
|
|
for i := 0; i < 5; i++ {
|
|
job := &Job{
|
|
Name: fmt.Sprintf("Edge Job %d", i),
|
|
ConfigID: config.ID,
|
|
Schedule: "0 * * * *",
|
|
Enabled: BoolPtr(true),
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateJob(job)
|
|
assert.NoError(t, err)
|
|
jobs[i] = job
|
|
}
|
|
|
|
// Delete them in reverse order
|
|
for i := 4; i >= 0; i-- {
|
|
err = db.DeleteJob(jobs[i].ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify deletion
|
|
_, err = db.GetJob(jobs[i].ID)
|
|
assert.Error(t, err, "Job should be deleted")
|
|
}
|
|
|
|
// Create a job with history records
|
|
jobWithHistory := &Job{
|
|
Name: "Job with History",
|
|
ConfigID: config.ID,
|
|
Schedule: "0 * * * *",
|
|
Enabled: BoolPtr(true),
|
|
CreatedBy: testUser.ID,
|
|
}
|
|
err = db.CreateJob(jobWithHistory)
|
|
assert.NoError(t, err)
|
|
|
|
// Create history records
|
|
for i := 0; i < 3; i++ {
|
|
startTime := time.Now().Add(time.Duration(-i) * time.Hour)
|
|
endTime := startTime.Add(30 * time.Minute)
|
|
history := &JobHistory{
|
|
JobID: jobWithHistory.ID,
|
|
StartTime: startTime,
|
|
EndTime: &endTime,
|
|
Status: "completed",
|
|
BytesTransferred: int64(1024 * (i + 1)),
|
|
FilesTransferred: i + 1,
|
|
}
|
|
err = db.CreateJobHistory(history)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
// Now delete the job - this should succeed even with history records
|
|
// (due to foreign key constraints in the database)
|
|
err = db.DeleteJob(jobWithHistory.ID)
|
|
assert.NoError(t, err)
|
|
|
|
// Verify deletion
|
|
_, err = db.GetJob(jobWithHistory.ID)
|
|
assert.Error(t, err, "Job should be deleted")
|
|
}
|
|
|
|
// TestInitializeEdgeCases tests edge cases for the Initialize function
|
|
func TestInitializeEdgeCases(t *testing.T) {
|
|
// Test with a read-only directory (if possible)
|
|
tempDir, err := os.MkdirTemp("", "gomft_test_readonly")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
// Try to make the directory read-only
|
|
// Note: This may not work on all systems due to permissions
|
|
origPerms, err := os.Stat(tempDir)
|
|
if err != nil {
|
|
t.Fatalf("Failed to stat directory: %v", err)
|
|
}
|
|
|
|
// Try to make it read-only
|
|
err = os.Chmod(tempDir, 0400) // read-only
|
|
if err != nil {
|
|
t.Logf("Warning: Could not set directory to read-only: %v", err)
|
|
t.Skip("Could not set directory to read-only, skipping test")
|
|
}
|
|
defer os.Chmod(tempDir, origPerms.Mode()) // restore original permissions
|
|
|
|
dbPath := filepath.Join(tempDir, "readonly.db")
|
|
// This might fail because the directory is read-only
|
|
db, err := Initialize(dbPath)
|
|
if err != nil {
|
|
// Expected error due to read-only directory
|
|
t.Logf("Got expected error for read-only directory: %v", err)
|
|
} else {
|
|
// If it succeeded, clean up
|
|
t.Logf("Warning: DB initialization succeeded even with read-only directory!")
|
|
err = db.Close()
|
|
assert.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
// TestCloseEdgeCases tests edge cases for the Close function
|
|
func TestCloseEdgeCases(t *testing.T) {
|
|
// Create a temporary database
|
|
tempDir, err := os.MkdirTemp("", "gomft_test_close_edge")
|
|
assert.NoError(t, err)
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
dbPath := filepath.Join(tempDir, "close_edge.db")
|
|
db, err := Initialize(dbPath)
|
|
assert.NoError(t, err)
|
|
|
|
// Test calling methods after close
|
|
sqlDB, err := db.DB.DB()
|
|
assert.NoError(t, err)
|
|
|
|
// Get initial stats
|
|
stats := sqlDB.Stats()
|
|
t.Logf("Initial stats: MaxOpenConnections=%d, OpenConnections=%d, InUse=%d",
|
|
stats.MaxOpenConnections, stats.OpenConnections, stats.InUse)
|
|
|
|
// Close the DB
|
|
err = db.Close()
|
|
assert.NoError(t, err)
|
|
|
|
// Try to get stats again - this might fail
|
|
stats = sqlDB.Stats()
|
|
t.Logf("After close stats: MaxOpenConnections=%d, OpenConnections=%d, InUse=%d",
|
|
stats.MaxOpenConnections, stats.OpenConnections, stats.InUse)
|
|
|
|
// Verify that DB operations fail after close
|
|
_, err = db.GetUserByEmail("test@example.com")
|
|
assert.Error(t, err, "DB operations should fail after close")
|
|
}
|