Skip to content

Commit 080259c

Browse files
committed
fix(tests): isolate test databases to prevent production data loss
CRITICAL BUG FIX: Tests were using production database and deleting all data The root cause was in storage_test.go line 26: defer os.RemoveAll(os.ExpandEnv("$HOME/.local/share/codeme")) This caused complete data loss when running 'go test ./...'. Tests would: 1. Use OpenDB() which opened the PRODUCTION database 2. Execute DELETE FROM heartbeats to "clean up" 3. Delete the entire production database directory on exit Changes made to prevent this: - Created OpenDBWithPath() to allow custom database location - Added shared setupTestDB() helper in testhelper_test.go - Updated all test files to use isolated temporary databases via t.TempDir() - Removed dangerous os.RemoveAll() calls - Removed unnecessary DELETE cleanup (temp dirs auto-cleanup) Tests now use completely isolated databases that are automatically cleaned up by Go's testing framework. Production database is never touched during tests. Verified: - All tests pass with isolated databases - Production database remains intact after running tests - No data loss occurs when running go test ./...
1 parent e8225f7 commit 080259c

File tree

6 files changed

+41
-61
lines changed

6 files changed

+41
-61
lines changed

core/integration_test.go

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,9 @@ import (
77

88
func TestEndToEnd(t *testing.T) {
99
// Create test database
10-
db, err := OpenDB()
11-
if err != nil {
12-
t.Fatalf("Failed to open database: %v", err)
13-
}
10+
db := setupTestDB(t)
1411
defer db.Close()
1512

16-
// Clear any existing data
17-
db.Exec("DELETE FROM heartbeats")
18-
1913
// Simulate a coding session
2014
session := []struct {
2115
file string
@@ -106,21 +100,12 @@ func TestEndToEnd(t *testing.T) {
106100
if stats.TodayLines != expectedTotalLines {
107101
t.Errorf("TodayLines = %d, want %d", stats.TodayLines, expectedTotalLines)
108102
}
109-
110-
// Clean up
111-
db.Exec("DELETE FROM heartbeats")
112103
}
113104

114105
func TestMultipleDayStats(t *testing.T) {
115-
db, err := OpenDB()
116-
if err != nil {
117-
t.Fatalf("Failed to open database: %v", err)
118-
}
106+
db := setupTestDB(t)
119107
defer db.Close()
120108

121-
// Clear any existing data
122-
db.Exec("DELETE FROM heartbeats")
123-
124109
// Simulate activity over 3 consecutive days
125110
now := time.Now()
126111
today := time.Date(now.Year(), now.Month(), now.Day(), 10, 0, 0, 0, now.Location())
@@ -176,7 +161,4 @@ func TestMultipleDayStats(t *testing.T) {
176161
if len(stats.DailyActivity) != 3 {
177162
t.Errorf("DailyActivity count = %d, want 3", len(stats.DailyActivity))
178163
}
179-
180-
// Clean up
181-
db.Exec("DELETE FROM heartbeats")
182164
}

core/stats_test.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,9 @@ func TestCalculateLongestStreak(t *testing.T) {
101101

102102
func TestCalculateStats(t *testing.T) {
103103
// Create test database
104-
db, err := OpenDB()
105-
if err != nil {
106-
t.Fatalf("Failed to open database: %v", err)
107-
}
104+
db := setupTestDB(t)
108105
defer db.Close()
109106

110-
// Clear any existing data
111-
db.Exec("DELETE FROM heartbeats")
112-
113107
// Insert test data
114108
now := time.Now()
115109
testData := []Heartbeat{
@@ -188,7 +182,4 @@ func TestCalculateStats(t *testing.T) {
188182
if stats.TotalTime < expectedTime-tolerance || stats.TotalTime > expectedTime+tolerance {
189183
t.Errorf("TotalTime = %d, want ~%d (±%d)", stats.TotalTime, expectedTime, tolerance)
190184
}
191-
192-
// Clean up
193-
db.Exec("DELETE FROM heartbeats")
194185
}

core/storage.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,19 @@ func MigrateSchema(db *sql.DB) error {
7070
}
7171

7272
func OpenDB() (*sql.DB, error) {
73-
home, _ := os.UserHomeDir()
74-
dbPath := filepath.Join(home, ".local", "share", "codeme", "codeme.db")
73+
return OpenDBWithPath("")
74+
}
75+
76+
// OpenDBWithPath opens a database at the specified path, or uses default if empty
77+
func OpenDBWithPath(customPath string) (*sql.DB, error) {
78+
var dbPath string
79+
80+
if customPath != "" {
81+
dbPath = customPath
82+
} else {
83+
home, _ := os.UserHomeDir()
84+
dbPath = filepath.Join(home, ".local", "share", "codeme", "codeme.db")
85+
}
7586

7687
os.MkdirAll(filepath.Dir(dbPath), 0755)
7788

core/storage_test.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
package core
22

33
import (
4-
"os"
54
"testing"
65
)
76

87
func TestOpenDB(t *testing.T) {
9-
db, err := OpenDB()
10-
if err != nil {
11-
t.Fatalf("OpenDB() error = %v", err)
12-
}
8+
db := setupTestDB(t)
139
defer db.Close()
1410

1511
// Verify table exists
1612
var count int
17-
err = db.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='heartbeats'").Scan(&count)
13+
err := db.QueryRow("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='heartbeats'").Scan(&count)
1814
if err != nil || count != 1 {
1915
t.Errorf("heartbeats table not created")
2016
}
2117
}
2218

2319
func TestSaveHeartbeat(t *testing.T) {
24-
db, _ := OpenDB()
20+
db := setupTestDB(t)
2521
defer db.Close()
26-
defer os.RemoveAll(os.ExpandEnv("$HOME/.local/share/codeme"))
2722

2823
hb := Heartbeat{
2924
File: "/test/file.go",

core/testhelper_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package core
2+
3+
import (
4+
"database/sql"
5+
"path/filepath"
6+
"testing"
7+
)
8+
9+
// setupTestDB creates an isolated test database in a temporary directory
10+
// This helper is shared across all test files in the core package
11+
func setupTestDB(t *testing.T) *sql.DB {
12+
tmpDir := t.TempDir()
13+
testDB := filepath.Join(tmpDir, "test.db")
14+
db, err := OpenDBWithPath(testDB)
15+
if err != nil {
16+
t.Fatalf("Failed to create test database: %v", err)
17+
}
18+
return db
19+
}

core/tracker_test.go

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@ import (
55
)
66

77
func TestTrack(t *testing.T) {
8-
db, err := OpenDB()
9-
if err != nil {
10-
t.Fatalf("Failed to open database: %v", err)
11-
}
8+
db := setupTestDB(t)
129
defer db.Close()
1310

14-
// Clear existing data
15-
db.Exec("DELETE FROM heartbeats")
16-
1711
tests := []struct {
1812
name string
1913
file string
@@ -77,23 +71,14 @@ func TestTrack(t *testing.T) {
7771
}
7872
})
7973
}
80-
81-
// Clean up
82-
db.Exec("DELETE FROM heartbeats")
8374
}
8475

8576
func TestTrackWithChangedLines(t *testing.T) {
86-
db, err := OpenDB()
87-
if err != nil {
88-
t.Fatalf("Failed to open database: %v", err)
89-
}
77+
db := setupTestDB(t)
9078
defer db.Close()
9179

92-
// Clear existing data
93-
db.Exec("DELETE FROM heartbeats")
94-
9580
// Track initial file
96-
err = Track(db, "/test/evolving.go", "Go", 100, 100)
81+
err := Track(db, "/test/evolving.go", "Go", 100, 100)
9782
if err != nil {
9883
t.Fatalf("First Track() error = %v", err)
9984
}
@@ -122,7 +107,4 @@ func TestTrackWithChangedLines(t *testing.T) {
122107
if linesTotal != 110 {
123108
t.Errorf("lines_total = %d, want 110", linesTotal)
124109
}
125-
126-
// Clean up
127-
db.Exec("DELETE FROM heartbeats")
128110
}

0 commit comments

Comments
 (0)