362 lines
7.9 KiB
Go
362 lines
7.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestSyncServerAuthentication(t *testing.T) {
|
|
server := &SyncServer{authToken: "test-token"}
|
|
|
|
tests := []struct {
|
|
name string
|
|
token string
|
|
expected bool
|
|
}{
|
|
{"Valid token", "test-token", true},
|
|
{"Invalid token", "wrong-token", false},
|
|
{"Empty token", "", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Test the authentication logic directly without HTTP
|
|
result := strings.Compare(tt.token, server.authToken) == 0
|
|
if result != tt.expected {
|
|
t.Errorf("authenticate() = %v, want %v", result, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadDataNonExistentFile(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
server := &SyncServer{
|
|
dataFile: filepath.Join(tempDir, "nonexistent.json"),
|
|
}
|
|
|
|
backup, err := server.loadData()
|
|
if err != nil {
|
|
t.Errorf("loadData() error = %v, want nil", err)
|
|
}
|
|
|
|
if backup == nil {
|
|
t.Error("Expected backup to be non-nil")
|
|
}
|
|
|
|
if len(backup.Gyms) != 0 || len(backup.Problems) != 0 || len(backup.Sessions) != 0 || len(backup.Attempts) != 0 {
|
|
t.Error("Expected empty backup data")
|
|
}
|
|
|
|
if backup.Version != "2.0" || backup.FormatVersion != "2.0" {
|
|
t.Error("Expected version and format version to be 2.0")
|
|
}
|
|
}
|
|
|
|
func TestSaveAndLoadData(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
server := &SyncServer{
|
|
dataFile: filepath.Join(tempDir, "test.json"),
|
|
imagesDir: filepath.Join(tempDir, "images"),
|
|
}
|
|
|
|
testData := &ClimbDataBackup{
|
|
Version: "2.0",
|
|
FormatVersion: "2.0",
|
|
Gyms: []BackupGym{
|
|
{
|
|
ID: "gym1",
|
|
Name: "Test Gym",
|
|
},
|
|
},
|
|
Problems: []BackupProblem{
|
|
{
|
|
ID: "problem1",
|
|
GymID: "gym1",
|
|
ClimbType: "BOULDER",
|
|
Difficulty: DifficultyGrade{
|
|
System: "V",
|
|
Grade: "V5",
|
|
NumericValue: 5,
|
|
},
|
|
IsActive: true,
|
|
},
|
|
},
|
|
Sessions: []BackupClimbSession{},
|
|
Attempts: []BackupAttempt{},
|
|
}
|
|
|
|
err := server.saveData(testData)
|
|
if err != nil {
|
|
t.Errorf("saveData() error = %v", err)
|
|
}
|
|
|
|
loadedData, err := server.loadData()
|
|
if err != nil {
|
|
t.Errorf("loadData() error = %v", err)
|
|
}
|
|
|
|
if len(loadedData.Gyms) != 1 || loadedData.Gyms[0].ID != "gym1" {
|
|
t.Error("Loaded gym data doesn't match saved data")
|
|
}
|
|
|
|
if len(loadedData.Problems) != 1 || loadedData.Problems[0].ID != "problem1" {
|
|
t.Error("Loaded problem data doesn't match saved data")
|
|
}
|
|
}
|
|
|
|
func TestMinFunction(t *testing.T) {
|
|
tests := []struct {
|
|
a, b, expected int
|
|
}{
|
|
{5, 3, 3},
|
|
{2, 8, 2},
|
|
{4, 4, 4},
|
|
{0, 1, 0},
|
|
{-1, 2, -1},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
result := min(tt.a, tt.b)
|
|
if result != tt.expected {
|
|
t.Errorf("min(%d, %d) = %d, want %d", tt.a, tt.b, result, tt.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestClimbDataBackupValidation(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
backup ClimbDataBackup
|
|
isValid bool
|
|
}{
|
|
{
|
|
name: "Valid backup",
|
|
backup: ClimbDataBackup{
|
|
Version: "2.0",
|
|
FormatVersion: "2.0",
|
|
Gyms: []BackupGym{},
|
|
Problems: []BackupProblem{},
|
|
Sessions: []BackupClimbSession{},
|
|
Attempts: []BackupAttempt{},
|
|
},
|
|
isValid: true,
|
|
},
|
|
{
|
|
name: "Missing version",
|
|
backup: ClimbDataBackup{
|
|
FormatVersion: "2.0",
|
|
Gyms: []BackupGym{},
|
|
Problems: []BackupProblem{},
|
|
Sessions: []BackupClimbSession{},
|
|
Attempts: []BackupAttempt{},
|
|
},
|
|
isValid: false,
|
|
},
|
|
{
|
|
name: "Missing format version",
|
|
backup: ClimbDataBackup{
|
|
Version: "2.0",
|
|
Gyms: []BackupGym{},
|
|
Problems: []BackupProblem{},
|
|
Sessions: []BackupClimbSession{},
|
|
Attempts: []BackupAttempt{},
|
|
},
|
|
isValid: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Test basic validation logic
|
|
hasVersion := tt.backup.Version != ""
|
|
hasFormatVersion := tt.backup.FormatVersion != ""
|
|
isValid := hasVersion && hasFormatVersion
|
|
|
|
if isValid != tt.isValid {
|
|
t.Errorf("validation = %v, want %v", isValid, tt.isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBackupDataStructures(t *testing.T) {
|
|
t.Run("BackupGym", func(t *testing.T) {
|
|
gym := BackupGym{
|
|
ID: "gym1",
|
|
Name: "Test Gym",
|
|
SupportedClimbTypes: []string{"BOULDER", "ROPE"},
|
|
DifficultySystems: []string{"V", "YDS"},
|
|
CustomDifficultyGrades: []string{},
|
|
CreatedAt: "2024-01-01T10:00:00Z",
|
|
UpdatedAt: "2024-01-01T10:00:00Z",
|
|
}
|
|
|
|
if gym.ID != "gym1" {
|
|
t.Errorf("Expected gym ID 'gym1', got %s", gym.ID)
|
|
}
|
|
|
|
if len(gym.SupportedClimbTypes) != 2 {
|
|
t.Errorf("Expected 2 climb types, got %d", len(gym.SupportedClimbTypes))
|
|
}
|
|
})
|
|
|
|
t.Run("BackupProblem", func(t *testing.T) {
|
|
problem := BackupProblem{
|
|
ID: "problem1",
|
|
GymID: "gym1",
|
|
ClimbType: "BOULDER",
|
|
Difficulty: DifficultyGrade{
|
|
System: "V",
|
|
Grade: "V5",
|
|
NumericValue: 5,
|
|
},
|
|
IsActive: true,
|
|
CreatedAt: "2024-01-01T10:00:00Z",
|
|
UpdatedAt: "2024-01-01T10:00:00Z",
|
|
}
|
|
|
|
if problem.ClimbType != "BOULDER" {
|
|
t.Errorf("Expected climb type 'BOULDER', got %s", problem.ClimbType)
|
|
}
|
|
|
|
if problem.Difficulty.Grade != "V5" {
|
|
t.Errorf("Expected difficulty 'V5', got %s", problem.Difficulty.Grade)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestDifficultyGrade(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
grade DifficultyGrade
|
|
expectedGrade string
|
|
expectedValue int
|
|
}{
|
|
{
|
|
name: "V-Scale grade",
|
|
grade: DifficultyGrade{
|
|
System: "V",
|
|
Grade: "V5",
|
|
NumericValue: 5,
|
|
},
|
|
expectedGrade: "V5",
|
|
expectedValue: 5,
|
|
},
|
|
{
|
|
name: "YDS grade",
|
|
grade: DifficultyGrade{
|
|
System: "YDS",
|
|
Grade: "5.10a",
|
|
NumericValue: 10,
|
|
},
|
|
expectedGrade: "5.10a",
|
|
expectedValue: 10,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.grade.Grade != tt.expectedGrade {
|
|
t.Errorf("Expected grade %s, got %s", tt.expectedGrade, tt.grade.Grade)
|
|
}
|
|
|
|
if tt.grade.NumericValue != tt.expectedValue {
|
|
t.Errorf("Expected numeric value %d, got %d", tt.expectedValue, tt.grade.NumericValue)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestJSONSerialization(t *testing.T) {
|
|
backup := ClimbDataBackup{
|
|
Version: "2.0",
|
|
FormatVersion: "2.0",
|
|
Gyms: []BackupGym{
|
|
{
|
|
ID: "gym1",
|
|
Name: "Test Gym",
|
|
},
|
|
},
|
|
Problems: []BackupProblem{
|
|
{
|
|
ID: "problem1",
|
|
GymID: "gym1",
|
|
ClimbType: "BOULDER",
|
|
Difficulty: DifficultyGrade{
|
|
System: "V",
|
|
Grade: "V5",
|
|
NumericValue: 5,
|
|
},
|
|
IsActive: true,
|
|
},
|
|
},
|
|
Sessions: []BackupClimbSession{},
|
|
Attempts: []BackupAttempt{},
|
|
}
|
|
|
|
// Test JSON marshaling
|
|
jsonData, err := json.Marshal(backup)
|
|
if err != nil {
|
|
t.Errorf("Failed to marshal JSON: %v", err)
|
|
}
|
|
|
|
// Test JSON unmarshaling
|
|
var unmarshaledBackup ClimbDataBackup
|
|
err = json.Unmarshal(jsonData, &unmarshaledBackup)
|
|
if err != nil {
|
|
t.Errorf("Failed to unmarshal JSON: %v", err)
|
|
}
|
|
|
|
if unmarshaledBackup.Version != backup.Version {
|
|
t.Errorf("Version mismatch after JSON round-trip")
|
|
}
|
|
|
|
if len(unmarshaledBackup.Gyms) != len(backup.Gyms) {
|
|
t.Errorf("Gyms count mismatch after JSON round-trip")
|
|
}
|
|
}
|
|
|
|
func TestTimestampHandling(t *testing.T) {
|
|
now := time.Now().UTC()
|
|
timestamp := now.Format(time.RFC3339)
|
|
|
|
// Test that timestamp is in correct format
|
|
parsedTime, err := time.Parse(time.RFC3339, timestamp)
|
|
if err != nil {
|
|
t.Errorf("Failed to parse timestamp: %v", err)
|
|
}
|
|
|
|
if parsedTime.Year() != now.Year() {
|
|
t.Errorf("Year mismatch in timestamp")
|
|
}
|
|
}
|
|
|
|
func TestFilePathHandling(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
|
|
tests := []struct {
|
|
name string
|
|
filename string
|
|
isValid bool
|
|
}{
|
|
{"Valid filename", "test.json", true},
|
|
{"Valid path", filepath.Join(tempDir, "data.json"), true},
|
|
{"Empty filename", "", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
isEmpty := tt.filename == ""
|
|
isValid := !isEmpty
|
|
|
|
if isValid != tt.isValid {
|
|
t.Errorf("File path validation = %v, want %v", isValid, tt.isValid)
|
|
}
|
|
})
|
|
}
|
|
}
|