1package disk
2
3import (
4 "testing"
5)
6
7// Encryption Tests
8
9func TestNewEncryptionConfig_None(t *testing.T) {
10 enc, err := NewEncryptionConfig(EncryptionTypeNone, "")
11
12 if err != nil {
13 t.Fatalf("expected no error, got %v", err)
14 }
15
16 if enc.IsEncrypted() {
17 t.Error("expected not encrypted")
18 }
19
20 if enc.EncryptionType().String() != "None" {
21 t.Errorf("expected type 'None'")
22 }
23}
24
25func TestNewEncryptionConfig_LUKS(t *testing.T) {
26 password := "test-password-12345"
27 enc, err := NewEncryptionConfig(EncryptionTypeLUKS, password)
28
29 if err != nil {
30 t.Fatalf("expected no error, got %v", err)
31 }
32
33 if !enc.IsEncrypted() {
34 t.Error("expected encrypted")
35 }
36
37 if enc.HasPassword() != true {
38 t.Error("expected to have password")
39 }
40}
41
42func TestNewEncryptionConfig_MissingPassword(t *testing.T) {
43 _, err := NewEncryptionConfig(EncryptionTypeLUKS, "")
44
45 if err == nil {
46 t.Error("expected error for missing encryption password")
47 }
48}
49
50func TestNewEncryptionConfig_WeakPassword(t *testing.T) {
51 _, err := NewEncryptionConfig(EncryptionTypeLUKS, "wee")
52
53 if err == nil {
54 t.Error("expected error for weak password")
55 }
56}
57
58func TestEncryptionType_String(t *testing.T) {
59 tests := []struct {
60 encType EncryptionType
61 want string
62 }{
63 {EncryptionTypeNone, "None"},
64 {EncryptionTypeLUKS, "LUKS"},
65 {EncryptionTypeLUKSLVM, "LUKS+LVM"},
66 }
67
68 for _, tt := range tests {
69 if got := tt.encType.String(); got != tt.want {
70 t.Errorf("expected %s, got %s", tt.want, got)
71 }
72 }
73}
74
75// Partition Tests
76
77func TestNewPartition_Valid(t *testing.T) {
78 partition, err := NewPartition("/dev/sda1", 50*1024, FilesystemExt4, "/", false)
79
80 if err != nil {
81 t.Fatalf("expected no error, got %v", err)
82 }
83
84 if partition.Device() != "/dev/sda1" {
85 t.Errorf("expected device /dev/sda1")
86 }
87
88 if !partition.IsRootPartition() {
89 t.Error("expected to be root partition")
90 }
91}
92
93func TestNewPartition_InvalidDevice(t *testing.T) {
94 _, err := NewPartition("", 50*1024, FilesystemExt4, "/", false)
95
96 if err == nil {
97 t.Error("expected error for empty device")
98 }
99}
100
101func TestNewPartition_InvalidSize(t *testing.T) {
102 _, err := NewPartition("/dev/sda1", 0, FilesystemExt4, "/", false)
103
104 if err == nil {
105 t.Error("expected error for zero size")
106 }
107}
108
109func TestNewPartition_InvalidMountPoint(t *testing.T) {
110 _, err := NewPartition("/dev/sda1", 50*1024, FilesystemExt4, "not-absolute", false)
111
112 if err == nil {
113 t.Error("expected error for non-absolute mount point")
114 }
115}
116
117func TestNewPartition_FAT32NotForRoot(t *testing.T) {
118 _, err := NewPartition("/dev/sda1", 50*1024, FilesystemFAT32, "/", false)
119
120 if err == nil {
121 t.Error("expected error for FAT32 on root partition")
122 }
123}
124
125func TestPartition_IsBootPartition(t *testing.T) {
126 tests := []struct {
127 name string
128 mount string
129 isBoot bool
130 }{
131 {"boot partition", "/boot", true},
132 {"efi boot partition", "/boot/efi", true},
133 {"root partition", "/", false},
134 {"home partition", "/home", false},
135 }
136
137 for _, tt := range tests {
138 t.Run(tt.name, func(t *testing.T) {
139 p, _ := NewPartition("/dev/sda1", 10*1024, FilesystemExt4, tt.mount, false)
140 if p.IsBootPartition() != tt.isBoot {
141 t.Errorf("expected IsBootPartition=%v", tt.isBoot)
142 }
143 })
144 }
145}
146
147func TestPartition_IsEFI(t *testing.T) {
148 tests := []struct {
149 name string
150 fs FilesystemType
151 mount string
152 isEFI bool
153 shouldErr bool
154 }{
155 {"EFI partition", FilesystemFAT32, "/boot/efi", true, false},
156 {"EFI with ext4", FilesystemExt4, "/boot/efi", false, false},
157 {"FAT32 non-EFI", FilesystemFAT32, "/boot", false, true}, // Should error
158 {"ext4 root", FilesystemExt4, "/", false, false},
159 }
160
161 for _, tt := range tests {
162 t.Run(tt.name, func(t *testing.T) {
163 p, err := NewPartition("/dev/sda1", 1*1024, tt.fs, tt.mount, false)
164
165 if tt.shouldErr {
166 if err == nil {
167 t.Error("expected error")
168 }
169 return
170 }
171
172 if err != nil {
173 t.Errorf("unexpected error: %v", err)
174 return
175 }
176
177 if p.IsEFI() != tt.isEFI {
178 t.Errorf("expected IsEFI=%v", tt.isEFI)
179 }
180 })
181 }
182}
183
184// Disk Tests
185
186func TestNewDisk_Valid(t *testing.T) {
187 disk, err := NewDisk("/dev/sda", 500)
188
189 if err != nil {
190 t.Fatalf("expected no error, got %v", err)
191 }
192
193 if disk.Device() != "/dev/sda" {
194 t.Errorf("expected device /dev/sda")
195 }
196
197 if disk.SizeGB() != 500 {
198 t.Errorf("expected size 500GB")
199 }
200
201 if disk.PartitionCount() != 0 {
202 t.Error("expected no partitions initially")
203 }
204}
205
206func TestNewDisk_InvalidDevice(t *testing.T) {
207 _, err := NewDisk("", 500)
208
209 if err == nil {
210 t.Error("expected error for empty device")
211 }
212}
213
214func TestNewDisk_InvalidSize(t *testing.T) {
215 _, err := NewDisk("/dev/sda", 0)
216
217 if err == nil {
218 t.Error("expected error for zero size")
219 }
220}
221
222func TestDisk_AddPartition(t *testing.T) {
223 disk, _ := NewDisk("/dev/sda", 500)
224 partition, _ := NewPartition("/dev/sda1", 20*1024, FilesystemExt4, "/", false)
225
226 err := disk.AddPartition(partition)
227
228 if err != nil {
229 t.Fatalf("expected no error, got %v", err)
230 }
231
232 if disk.PartitionCount() != 1 {
233 t.Error("expected 1 partition")
234 }
235}
236
237func TestDisk_AddPartition_InvalidDevice(t *testing.T) {
238 disk, _ := NewDisk("/dev/sda", 500)
239 partition, _ := NewPartition("/dev/sdb1", 20*1024, FilesystemExt4, "/", false)
240
241 err := disk.AddPartition(partition)
242
243 if err == nil {
244 t.Error("expected error for partition on different disk")
245 }
246}
247
248func TestDisk_AddPartition_DuplicateMountPoint(t *testing.T) {
249 disk, _ := NewDisk("/dev/sda", 500)
250 partition1, _ := NewPartition("/dev/sda1", 20*1024, FilesystemExt4, "/", false)
251 partition2, _ := NewPartition("/dev/sda2", 20*1024, FilesystemExt4, "/", false)
252
253 if err := disk.AddPartition(partition1); err != nil {
254 t.Fatalf("expected no error, got %v", err)
255 }
256 err := disk.AddPartition(partition2)
257
258 if err == nil {
259 t.Error("expected error for duplicate mount point")
260 }
261}
262
263func TestDisk_AddPartition_ExceedsCapacity(t *testing.T) {
264 disk, _ := NewDisk("/dev/sda", 100)
265 partition1, _ := NewPartition("/dev/sda1", 80*1024, FilesystemExt4, "/", false)
266 partition2, _ := NewPartition("/dev/sda2", 50*1024, FilesystemExt4, "/home", false)
267
268 if err := disk.AddPartition(partition1); err != nil {
269 t.Fatalf("expected no error, got %v", err)
270 }
271 err := disk.AddPartition(partition2)
272
273 if err == nil {
274 t.Error("expected error when total partitions exceed disk size")
275 }
276}
277
278func TestDisk_FindPartitionByMountPoint(t *testing.T) {
279 disk, _ := NewDisk("/dev/sda", 500)
280 partition, _ := NewPartition("/dev/sda1", 20*1024, FilesystemExt4, "/", false)
281 if err := disk.AddPartition(partition); err != nil {
282 t.Fatalf("expected no error, got %v", err)
283 }
284
285 found := disk.FindPartitionByMountPoint("/")
286 if found == nil {
287 t.Error("expected to find partition")
288 }
289
290 if found.Device() != "/dev/sda1" {
291 t.Error("expected correct partition")
292 }
293
294 notFound := disk.FindPartitionByMountPoint("/home")
295 if notFound != nil {
296 t.Error("expected not to find partition")
297 }
298}
299
300func TestDisk_FindPartitionByDevice(t *testing.T) {
301 disk, _ := NewDisk("/dev/sda", 500)
302 partition, _ := NewPartition("/dev/sda1", 20*1024, FilesystemExt4, "/", false)
303 if err := disk.AddPartition(partition); err != nil {
304 t.Fatalf("expected no error, got %v", err)
305 }
306
307 found := disk.FindPartitionByDevice("/dev/sda1")
308 if found == nil {
309 t.Error("expected to find partition")
310 }
311
312 notFound := disk.FindPartitionByDevice("/dev/sda2")
313 if notFound != nil {
314 t.Error("expected not to find partition")
315 }
316}
317
318func TestDisk_HasRootPartition(t *testing.T) {
319 disk, _ := NewDisk("/dev/sda", 500)
320
321 if disk.HasRootPartition() {
322 t.Error("expected no root partition initially")
323 }
324
325 partition, _ := NewPartition("/dev/sda1", 20*1024, FilesystemExt4, "/", false)
326 if err := disk.AddPartition(partition); err != nil {
327 t.Fatalf("expected no error, got %v", err)
328 }
329
330 if !disk.HasRootPartition() {
331 t.Error("expected to have root partition")
332 }
333}
334
335func TestDisk_ValidateLayout_Success(t *testing.T) {
336 disk, _ := NewDisk("/dev/sda", 500)
337
338 // Add EFI partition
339 efi, _ := NewPartition("/dev/sda1", 512, FilesystemFAT32, "/boot/efi", false)
340 if err := disk.AddPartition(efi); err != nil {
341 t.Fatalf("expected no error, got %v", err)
342 }
343
344 // Add root partition
345 root, _ := NewPartition("/dev/sda2", 50*1024, FilesystemExt4, "/", false)
346 if err := disk.AddPartition(root); err != nil {
347 t.Fatalf("expected no error, got %v", err)
348 }
349
350 err := disk.ValidateLayout()
351 if err != nil {
352 t.Errorf("expected valid layout, got error: %v", err)
353 }
354}
355
356func TestDisk_ValidateLayout_MissingRoot(t *testing.T) {
357 disk, _ := NewDisk("/dev/sda", 500)
358
359 efi, _ := NewPartition("/dev/sda1", 512, FilesystemFAT32, "/boot/efi", false)
360 if err := disk.AddPartition(efi); err != nil {
361 t.Fatalf("expected no error, got %v", err)
362 }
363
364 err := disk.ValidateLayout()
365 if err == nil {
366 t.Error("expected error for missing root partition")
367 }
368}
369
370func TestDisk_ValidateLayout_MissingEFI(t *testing.T) {
371 disk, _ := NewDisk("/dev/sda", 500)
372
373 root, _ := NewPartition("/dev/sda1", 50*1024, FilesystemExt4, "/", false)
374 if err := disk.AddPartition(root); err != nil {
375 t.Fatalf("expected no error, got %v", err)
376 }
377
378 err := disk.ValidateLayout()
379 if err == nil {
380 t.Error("expected error for missing EFI partition")
381 }
382}
383
384func TestDisk_ValidateLayout_RootTooSmall(t *testing.T) {
385 disk, _ := NewDisk("/dev/sda", 500)
386
387 efi, _ := NewPartition("/dev/sda1", 512, FilesystemFAT32, "/boot/efi", false)
388 if err := disk.AddPartition(efi); err != nil {
389 t.Fatalf("expected no error, got %v", err)
390 }
391
392 root, _ := NewPartition("/dev/sda2", 10*1024, FilesystemExt4, "/", false)
393 if err := disk.AddPartition(root); err != nil {
394 t.Fatalf("expected no error, got %v", err)
395 }
396
397 err := disk.ValidateLayout()
398 if err == nil {
399 t.Error("expected error for root partition too small")
400 }
401}
402
403func TestDisk_ValidateLayout_EFIWrongFilesystem(t *testing.T) {
404 disk, _ := NewDisk("/dev/sda", 500)
405
406 efi, _ := NewPartition("/dev/sda1", 512, FilesystemExt4, "/boot/efi", false)
407 if err := disk.AddPartition(efi); err != nil {
408 t.Fatalf("expected no error, got %v", err)
409 }
410
411 root, _ := NewPartition("/dev/sda2", 50*1024, FilesystemExt4, "/", false)
412 if err := disk.AddPartition(root); err != nil {
413 t.Fatalf("expected no error, got %v", err)
414 }
415
416 err := disk.ValidateLayout()
417 if err == nil {
418 t.Error("expected error for EFI partition not FAT32")
419 }
420}
421
422func TestDisk_CalculateSpaces(t *testing.T) {
423 disk, _ := NewDisk("/dev/sda", 500)
424
425 efi, _ := NewPartition("/dev/sda1", 1*1024, FilesystemFAT32, "/boot/efi", false)
426 if err := disk.AddPartition(efi); err != nil {
427 t.Fatalf("expected no error, got %v", err)
428 }
429
430 root, _ := NewPartition("/dev/sda2", 100*1024, FilesystemExt4, "/", false)
431 if err := disk.AddPartition(root); err != nil {
432 t.Fatalf("expected no error, got %v", err)
433 }
434
435 used := disk.CalculateUsedSpace()
436 if used != 101 { // 1GB + 100GB
437 t.Errorf("expected 101GB used, got %dGB", used)
438 }
439
440 free := disk.CalculateFreeSpace()
441 if free != 399 { // 500GB - 101GB
442 t.Errorf("expected 399GB free, got %dGB", free)
443 }
444}
445
446func TestIsPartitionOfDisk(t *testing.T) {
447 tests := []struct {
448 disk string
449 partition string
450 expected bool
451 }{
452 {"/dev/sda", "/dev/sda1", true},
453 {"/dev/sda", "/dev/sda10", true},
454 {"/dev/sda", "/dev/sdb1", false},
455 {"/dev/sda", "/dev/sdaa1", false},
456 {"/dev/nvme0n1", "/dev/nvme0n1p1", true},
457 {"/dev/nvme0n1", "/dev/nvme0n1p10", true},
458 }
459
460 for _, tt := range tests {
461 result := isPartitionOfDisk(tt.disk, tt.partition)
462 if result != tt.expected {
463 t.Errorf("isPartitionOfDisk(%s, %s): expected %v, got %v",
464 tt.disk, tt.partition, tt.expected, result)
465 }
466 }
467}
468
469func TestFilesystemType_String(t *testing.T) {
470 tests := []struct {
471 fs FilesystemType
472 want string
473 }{
474 {FilesystemExt4, "ext4"},
475 {FilesystemFAT32, "FAT32"},
476 {FilesystemBtrfs, "Btrfs"},
477 }
478
479 for _, tt := range tests {
480 if got := tt.fs.String(); got != tt.want {
481 t.Errorf("expected %s, got %s", tt.want, got)
482 }
483 }
484}