|
| 1 | +package order |
| 2 | + |
| 3 | +import ( |
| 4 | + "os" |
| 5 | + "path/filepath" |
| 6 | + "strings" |
| 7 | + "testing" |
| 8 | + "time" |
| 9 | + |
| 10 | + loggerHandler "github.com/HyperloopUPV-H8/h9-backend/pkg/logger" |
| 11 | + "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/packet/data" |
| 12 | +) |
| 13 | + |
| 14 | +func createLoggerForTest(t *testing.T) *Logger { |
| 15 | + |
| 16 | + t.Helper() // Marks this function as a test helper, avoids cluttering test output |
| 17 | + |
| 18 | + logger := NewLogger() |
| 19 | + return logger |
| 20 | +} |
| 21 | + |
| 22 | +// chdirTemp changes the current working directory to a temporary directory for the duration of the test. |
| 23 | +func chdirTemp(t *testing.T) string { |
| 24 | + t.Helper() |
| 25 | + tmp := t.TempDir() |
| 26 | + old, err := os.Getwd() |
| 27 | + if err != nil { |
| 28 | + t.Fatal(err) |
| 29 | + } |
| 30 | + if err := os.Chdir(tmp); err != nil { |
| 31 | + t.Fatal(err) |
| 32 | + } |
| 33 | + t.Cleanup(func() { _ = os.Chdir(old) }) |
| 34 | + return tmp |
| 35 | +} |
| 36 | + |
| 37 | +func splitPath(p string) []string { |
| 38 | + p = filepath.Clean(p) |
| 39 | + return strings.Split(p, string(os.PathSeparator)) |
| 40 | +} |
| 41 | + |
| 42 | +/******* |
| 43 | +* Start * |
| 44 | +*******/ |
| 45 | + |
| 46 | +func TestStart(t *testing.T) { |
| 47 | + |
| 48 | + _ = chdirTemp(t) // Change to a temporary directory |
| 49 | + |
| 50 | + logger := createLoggerForTest(t) |
| 51 | + |
| 52 | + // Sample data |
| 53 | + |
| 54 | + var startTime int64 |
| 55 | + |
| 56 | + t.Run("Start (first time)", func(t *testing.T) { |
| 57 | + |
| 58 | + // First start should succeed |
| 59 | + out := logger.Start() |
| 60 | + |
| 61 | + if out != nil { |
| 62 | + t.Fatalf("expected nil, got %v", out) |
| 63 | + } |
| 64 | + // Capture start time |
| 65 | + startTime = logger.StartTime |
| 66 | + |
| 67 | + }) |
| 68 | + |
| 69 | + t.Run("Start (not first time)", func(t *testing.T) { |
| 70 | + |
| 71 | + // El test Start (first time) debe haber tenido éxito y haber establecido startTime |
| 72 | + if startTime == 0 { |
| 73 | + t.Fatal("precondition failed: StartTime should be set from the first start") |
| 74 | + } |
| 75 | + |
| 76 | + // Subsequent starts shouldn't change startTime |
| 77 | + out := logger.Start() |
| 78 | + if out != nil { |
| 79 | + t.Fatalf("expected nil, got %v", out) |
| 80 | + } |
| 81 | + if logger.StartTime != startTime { |
| 82 | + t.Fatalf("expected startTime to be %d, got %d", startTime, logger.StartTime) |
| 83 | + } |
| 84 | + }) |
| 85 | + |
| 86 | +} |
| 87 | + |
| 88 | +/*********************************************** |
| 89 | +* Push Record (toggling between Start and Stop) * |
| 90 | +***********************************************/ |
| 91 | + |
| 92 | +func TestPushRecord(t *testing.T) { |
| 93 | + |
| 94 | + _ = chdirTemp(t) // Change to a temporary directory |
| 95 | + |
| 96 | + logger := createLoggerForTest(t) |
| 97 | + |
| 98 | + packet := data.NewPacket(1) |
| 99 | + |
| 100 | + record := Record{ |
| 101 | + Packet: packet, |
| 102 | + From: "test-BOARD", |
| 103 | + To: "Logger", |
| 104 | + Timestamp: time.Now(), |
| 105 | + } |
| 106 | + |
| 107 | + t.Run("Write when log is not started", func(t *testing.T) { |
| 108 | + |
| 109 | + // Push logger |
| 110 | + logger.PushRecord(&record) |
| 111 | + |
| 112 | + // Verify that the logger was not created |
| 113 | + |
| 114 | + if _, err := os.Stat("logger"); err == nil { |
| 115 | + // El archivo SÍ existe |
| 116 | + t.Fatalf("expected file to not exist, but it does") |
| 117 | + } |
| 118 | + |
| 119 | + }) |
| 120 | + |
| 121 | + // Starts the order log |
| 122 | + logger.Start() |
| 123 | + |
| 124 | + // Start the logger |
| 125 | + t.Run("Write when log is started", func(t *testing.T) { |
| 126 | + logger.PushRecord(&record) |
| 127 | + filePath := filepath.Join( |
| 128 | + "logger", |
| 129 | + loggerHandler.Timestamp.Format(loggerHandler.TimestampFormat), |
| 130 | + "order", |
| 131 | + "order.csv") |
| 132 | + time.Sleep(2 * time.Second) |
| 133 | + |
| 134 | + // reads the file |
| 135 | + data, err := os.ReadFile(filePath) |
| 136 | + if err != nil { |
| 137 | + t.Fatalf("file could not be read: %v", err) |
| 138 | + } |
| 139 | + |
| 140 | + line := strings.TrimSpace(string(data)) |
| 141 | + if line == "" { |
| 142 | + t.Fatalf("file %s is empty", filePath) |
| 143 | + } |
| 144 | + |
| 145 | + // split the line by commas |
| 146 | + fields := strings.Split(line, ",") |
| 147 | + if len(fields) < 6 { |
| 148 | + t.Fatalf("CSV line has fewer than 6 fields: %s", line) |
| 149 | + } |
| 150 | + |
| 151 | + // Check that the log contains the right data (impossible to check first and last field) |
| 152 | + if !strings.Contains(line, "test-BOARD,Logger,1,map[],") { |
| 153 | + t.Errorf("test-BOARD,Logger,1,map[], was not found inside the logger/orden file") |
| 154 | + } |
| 155 | + |
| 156 | + }) |
| 157 | + |
| 158 | +} |
| 159 | + |
| 160 | +/************* |
| 161 | +* Create File * |
| 162 | +*************/ |
| 163 | + |
| 164 | +func TestCreateFile(t *testing.T) { |
| 165 | + |
| 166 | + // Try to create the file sucessfully |
| 167 | + t.Run("Success", func(t *testing.T) { |
| 168 | + |
| 169 | + _ = chdirTemp(t) // Change to a temporary directory |
| 170 | + |
| 171 | + logger := createLoggerForTest(t) |
| 172 | + |
| 173 | + file, err := logger.createFile() |
| 174 | + |
| 175 | + if err != nil { |
| 176 | + t.Fatalf("expected no error, got %v", err) |
| 177 | + } |
| 178 | + |
| 179 | + defer file.Close() |
| 180 | + |
| 181 | + // Check if the file was sucessfully created |
| 182 | + path := file.Name() |
| 183 | + parts := splitPath(path) |
| 184 | + |
| 185 | + nParts := 4 |
| 186 | + |
| 187 | + // Check number of directories |
| 188 | + if len(parts) != nParts { |
| 189 | + t.Fatalf("unexpected path format: %v (len=%d, want=%d)", parts, len(parts), nParts) |
| 190 | + } |
| 191 | + |
| 192 | + // Logger |
| 193 | + if parts[0] != "logger" { |
| 194 | + t.Fatalf("expected prefix 'logger', got %q", parts[0]) |
| 195 | + } |
| 196 | + |
| 197 | + // Date |
| 198 | + |
| 199 | + excepetedDate := loggerHandler.Timestamp.Format(loggerHandler.TimestampFormat) |
| 200 | + |
| 201 | + if parts[1] != excepetedDate { |
| 202 | + t.Fatalf("expected folder '%s', got %q", excepetedDate, parts[2]) |
| 203 | + } |
| 204 | + |
| 205 | + // Filename |
| 206 | + |
| 207 | + fileName := "order" |
| 208 | + if parts[3] != fileName+".csv" { |
| 209 | + t.Fatalf("expected filename '%s.csv', got %q", fileName, parts[3]) |
| 210 | + } |
| 211 | + |
| 212 | + // File must exist |
| 213 | + if _, err := os.Stat(path); err != nil { |
| 214 | + t.Fatalf("expected file to exist, but got: %v", err) |
| 215 | + } |
| 216 | + |
| 217 | + }) |
| 218 | + |
| 219 | + t.Run("Failed", func(t *testing.T) { |
| 220 | + |
| 221 | + _ = chdirTemp(t) // Change to a clean temporary working directory |
| 222 | + |
| 223 | + logger := createLoggerForTest(t) |
| 224 | + |
| 225 | + // Create a file named "logger" to block the directory creation. |
| 226 | + // This forces createFile to fail when trying to build the folder hierarchy. |
| 227 | + if err := os.WriteFile("logger", []byte("blocking file"), 0644); err != nil { |
| 228 | + t.Fatalf("precondition failed logger file could not be created: %v", err) |
| 229 | + } |
| 230 | + |
| 231 | + file, err := logger.createFile() |
| 232 | + |
| 233 | + // We expect an error |
| 234 | + if err == nil { |
| 235 | + if file != nil { |
| 236 | + file.Close() |
| 237 | + } |
| 238 | + t.Fatalf("expected error, got nil") |
| 239 | + } |
| 240 | + |
| 241 | + // When there is an error, the returned file must be nil |
| 242 | + if file != nil { |
| 243 | + file.Close() |
| 244 | + t.Fatalf("expected returned file to be nil on error") |
| 245 | + } |
| 246 | + |
| 247 | + }) |
| 248 | +} |
0 commit comments