github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/ed/filebuffer_test.go (about) 1 // Copyright 2015-2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "os" 12 "reflect" 13 "testing" 14 15 "github.com/google/go-cmp/cmp" 16 ) 17 18 // Test all functions with func() int signatur 19 var testTableInt = []struct { 20 name string 21 in *FileBuffer 22 exp interface{} 23 method func(f *FileBuffer) int 24 }{ 25 { 26 name: "Test Len: Len()=0", 27 in: &FileBuffer{file: []int{}}, 28 exp: 0, 29 method: (*FileBuffer).Len, 30 }, 31 { 32 name: "Test Len: Len()=4", 33 in: &FileBuffer{file: []int{0, 1, 2, 3}}, 34 exp: 4, 35 method: (*FileBuffer).Len, 36 }, 37 { 38 name: "Test GetAddr: GetAddr()=0", 39 in: &FileBuffer{addr: 0}, 40 exp: 0, 41 method: (*FileBuffer).GetAddr, 42 }, 43 { 44 name: "Test GetAddr: GetAddr()=4", 45 in: &FileBuffer{addr: 4}, 46 exp: 4, 47 method: (*FileBuffer).GetAddr, 48 }, 49 { 50 name: "Test Size: Size()=4", 51 in: &FileBuffer{file: []int{0, 1, 2, 3}, buffer: []string{"0", "1", "2", "3"}}, 52 exp: 4, 53 method: (*FileBuffer).Size, 54 }, 55 } 56 57 func TestBasicFuncsInt(t *testing.T) { 58 for _, tt := range testTableInt { 59 t.Run(tt.name, func(t *testing.T) { 60 got := tt.method(tt.in) 61 if got != tt.exp { 62 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 63 } 64 }) 65 } 66 } 67 68 // Test Dirty 69 var testTableDirty = []struct { 70 name string 71 in *FileBuffer 72 exp interface{} 73 method func(f *FileBuffer) bool 74 }{ 75 { 76 name: "Test Dirty: dirty = false", 77 in: &FileBuffer{dirty: false}, 78 exp: false, 79 method: (*FileBuffer).Dirty, 80 }, 81 { 82 name: "Test Dirty: dirty = true", 83 in: &FileBuffer{dirty: true}, 84 exp: true, 85 method: (*FileBuffer).Dirty, 86 }, 87 } 88 89 func TestDirty(t *testing.T) { 90 for _, tt := range testTableDirty { 91 t.Run(tt.name, func(t *testing.T) { 92 got := tt.method(tt.in) 93 if got != tt.exp { 94 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 95 } 96 }) 97 } 98 } 99 100 // Test all functions with func() signatur 101 var testTable = []struct { 102 name string 103 in *FileBuffer 104 exp interface{} 105 method func(f *FileBuffer) 106 }{ 107 { 108 name: "Test Touch", 109 in: &FileBuffer{dirty: false, mod: false}, 110 exp: &FileBuffer{dirty: true, mod: true}, 111 method: (*FileBuffer).Touch, 112 }, 113 { 114 name: "Test Start", 115 in: &FileBuffer{mod: true, tmpFile: []int{}, file: []int{0, 1, 2, 3}, tmpAddr: 0, addr: 10, tmpDirty: false, dirty: true}, 116 exp: &FileBuffer{mod: false, tmpFile: []int{0, 1, 2, 3}, file: []int{0, 1, 2, 3}, tmpAddr: 10, addr: 10, tmpDirty: true, dirty: true}, 117 method: (*FileBuffer).Start, 118 }, 119 { 120 name: "Test End", 121 in: &FileBuffer{mod: true, lastFile: []int{}, tmpFile: []int{0, 1, 2, 3}, lastAddr: 0, tmpAddr: 10, lastDirty: false, tmpDirty: true}, 122 exp: &FileBuffer{mod: true, lastFile: []int{0, 1, 2, 3}, tmpFile: []int{0, 1, 2, 3}, lastAddr: 10, tmpAddr: 10, lastDirty: true, tmpDirty: true}, 123 method: (*FileBuffer).End, 124 }, 125 { 126 name: "Test Rewind", 127 in: &FileBuffer{mod: false, file: []int{}, lastFile: []int{0, 1, 2, 3}, addr: 0, lastAddr: 10, dirty: true, lastDirty: false}, 128 exp: &FileBuffer{mod: true, file: []int{0, 1, 2, 3}, lastFile: []int{0, 1, 2, 3}, addr: 10, lastAddr: 10, dirty: false, lastDirty: false}, 129 method: (*FileBuffer).Rewind, 130 }, 131 { 132 name: "Test Clean", 133 in: &FileBuffer{dirty: true, lastDirty: true, lastFile: []int{0, 1, 2, 3}, lastAddr: 10}, 134 exp: &FileBuffer{dirty: false, lastDirty: false, lastFile: []int{}, lastAddr: 0}, 135 method: (*FileBuffer).Clean, 136 }, 137 } 138 139 func TestBasicFuncs(t *testing.T) { 140 for _, tt := range testTable { 141 t.Run(tt.name, func(t *testing.T) { 142 tt.method(tt.in) 143 if !reflect.DeepEqual(tt.in, tt.exp) { 144 t.Errorf("Expected value: %v, got: %v", tt.exp, tt.in) 145 } 146 }) 147 } 148 } 149 150 // Test NewFileBuffer 151 var testTableNewFileBuffer = []struct { 152 name string 153 in []string 154 exp *FileBuffer 155 }{ 156 { 157 name: "Test NewFileBuffer", 158 in: []string{"0", "1", "2", "3"}, 159 exp: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, dirty: false, mod: false, addr: 0, marks: make(map[byte]int)}, 160 }, 161 } 162 163 func TestNewFileBuffer(t *testing.T) { 164 for _, tt := range testTableNewFileBuffer { 165 t.Run(tt.name, func(t *testing.T) { 166 got := NewFileBuffer(tt.in) 167 if !reflect.DeepEqual(got, tt.exp) { 168 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 169 } 170 }) 171 } 172 } 173 174 // Test OOB 175 var testTableOOB = []struct { 176 name string 177 in *FileBuffer 178 exp interface{} 179 methodin int 180 }{ 181 { 182 name: "Test OOB: return true", 183 in: &FileBuffer{}, 184 exp: true, 185 methodin: 4, 186 }, 187 { 188 name: "Test OOB: return false", 189 in: &FileBuffer{file: []int{0, 1, 2, 3}}, 190 exp: false, 191 methodin: 2, 192 }, 193 } 194 195 func TestOOB(t *testing.T) { 196 for _, tt := range testTableOOB { 197 t.Run(tt.name, func(t *testing.T) { 198 got := tt.in.OOB(tt.methodin) 199 if !reflect.DeepEqual(got, tt.exp) { 200 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 201 } 202 }) 203 } 204 } 205 206 // Test GetMust 207 var testTableGetMust = []struct { 208 name string 209 in *FileBuffer 210 exp string 211 methodin1 int 212 methodin2 bool 213 }{ 214 { 215 name: "Test GetMust", 216 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 217 exp: "3", 218 methodin1: 3, 219 methodin2: true, 220 }, 221 } 222 223 func TestGetMust(t *testing.T) { 224 for _, tt := range testTableGetMust { 225 t.Run(tt.name, func(t *testing.T) { 226 got := tt.in.GetMust(tt.methodin1, tt.methodin2) 227 if !reflect.DeepEqual(got, tt.exp) { 228 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 229 } 230 }) 231 } 232 } 233 234 // Test Get 235 var testTableGet = []struct { 236 name string 237 in *FileBuffer 238 exp1 []string 239 exp2 error 240 methodin [2]int 241 }{ 242 { 243 name: "Test Get: with OOB error", 244 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 245 exp1: []string{}, 246 exp2: ErrOOB, 247 methodin: [2]int{0, 4}, 248 }, 249 { 250 name: "Test Get: without OOB error", 251 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 252 exp1: []string{"0", "1"}, 253 exp2: fmt.Errorf(""), 254 methodin: [2]int{0, 1}, 255 }, 256 } 257 258 func TestGet(t *testing.T) { 259 for _, tt := range testTableGet { 260 t.Run(tt.name, func(t *testing.T) { 261 got, err := tt.in.Get(tt.methodin) 262 if err != nil { 263 // Using cmp pkf with weird opt because reflect.DeepEqual does not work for empty string arrays 264 alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true }) 265 opt := cmp.FilterValues(func(x, y interface{}) bool { 266 vx, vy := reflect.ValueOf(x), reflect.ValueOf(y) 267 return (vx.IsValid() && vy.IsValid() && vx.Type() == vy.Type()) && 268 (vx.Kind() == reflect.Slice || vx.Kind() == reflect.Map) && 269 (vx.Len() == 0 && vy.Len() == 0) 270 }, alwaysEqual) 271 if !cmp.Equal(got, tt.exp1, opt) || !reflect.DeepEqual(err.Error(), tt.exp2.Error()) { 272 t.Errorf("Expected values: %v, %v, got: %v, %v", tt.exp1, tt.exp2, got, err) 273 } 274 } 275 }) 276 } 277 } 278 279 // Test Copy 280 var testTableCopy = []struct { 281 name string 282 in *FileBuffer 283 exp error 284 methodin [2]int 285 }{ 286 { 287 name: "Test Copy: with OOB error", 288 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 289 exp: ErrOOB, 290 methodin: [2]int{0, 4}, 291 }, 292 { 293 name: "Test Copy: without OOB error", 294 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 295 exp: nil, 296 methodin: [2]int{0, 1}, 297 }, 298 } 299 300 func TestCopy(t *testing.T) { 301 for _, tt := range testTableCopy { 302 t.Run(tt.name, func(t *testing.T) { 303 err := tt.in.Copy(tt.methodin) 304 if err != nil { 305 if !reflect.DeepEqual(err.Error(), tt.exp.Error()) { 306 t.Errorf("Expected value: %v, got: %v", tt.exp, err) 307 } 308 309 } 310 }) 311 } 312 } 313 314 // Test Paste & Insert 315 var testTablePasteInsert = []struct { 316 name string 317 in *FileBuffer 318 exp error 319 methodin int 320 }{ 321 { 322 name: "Test Paste & Insert: with OOB error", 323 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 324 exp: ErrOOB, 325 methodin: 5, 326 }, 327 { 328 name: "Test Paste & Insert: without OOB error and nlines == 0", 329 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 330 exp: nil, 331 methodin: 1, 332 }, 333 { 334 name: "Test Paste & Insert: without OOB error and nlines != 0", 335 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, cbuf: []string{"0", "1", "2", "3"}}, 336 exp: nil, 337 methodin: 1, 338 }, 339 } 340 341 func TestPasteInsert(t *testing.T) { 342 for _, tt := range testTablePasteInsert { 343 t.Run(tt.name, func(t *testing.T) { 344 err := tt.in.Paste(tt.methodin) 345 if err != nil { 346 if !reflect.DeepEqual(err.Error(), tt.exp.Error()) { 347 t.Errorf("Expected value: %v, got: %v", tt.exp, err) 348 } 349 } 350 }) 351 } 352 } 353 354 // Test Delete 355 var testTableDelete = []struct { 356 name string 357 in *FileBuffer 358 exp error 359 methodin [2]int 360 }{ 361 { 362 name: "Test Delete: with OOB error", 363 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 364 exp: ErrOOB, 365 methodin: [2]int{0, 4}, 366 }, 367 { 368 name: "Test Delete: without OOB error and addr OOB edge case", 369 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 370 exp: nil, 371 methodin: [2]int{0, 3}, 372 }, 373 } 374 375 func TestDelete(t *testing.T) { 376 for _, tt := range testTableDelete { 377 t.Run(tt.name, func(t *testing.T) { 378 err := tt.in.Delete(tt.methodin) 379 if err != nil { 380 if !reflect.DeepEqual(err.Error(), tt.exp.Error()) { 381 t.Errorf("Expected value: %v, got: %v", tt.exp, err) 382 } 383 } 384 }) 385 } 386 } 387 388 // Test SetAddr 389 var testTableSetAddr = []struct { 390 name string 391 in *FileBuffer 392 exp error 393 methodin int 394 }{ 395 { 396 name: "Test SetAddr: with OOB error", 397 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 398 exp: ErrOOB, 399 methodin: 4, 400 }, 401 { 402 name: "Test SetAddr: without OOB error and addr OOB edge case", 403 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}}, 404 exp: nil, 405 methodin: 0, 406 }, 407 } 408 409 func TestSetAddr(t *testing.T) { 410 for _, tt := range testTableSetAddr { 411 t.Run(tt.name, func(t *testing.T) { 412 err := tt.in.SetAddr(tt.methodin) 413 if err != nil { 414 if err.Error() != tt.exp.Error() { 415 t.Errorf("Expected value: %v, got: %v", tt.exp, err) 416 } 417 } else { 418 if tt.methodin != tt.in.addr { 419 t.Errorf("Expected value: %v, got: %v", tt.methodin, tt.in.addr) 420 } 421 } 422 }) 423 } 424 } 425 426 // Test SetMark 427 var testTableSetMark = []struct { 428 name string 429 in *FileBuffer 430 exp int 431 err error 432 methodin1 byte 433 methodin2 int 434 }{ 435 { 436 name: "Test SetMark: with OOB error", 437 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)}, 438 exp: 0, 439 err: ErrOOB, 440 methodin1: 0, 441 methodin2: 5, 442 }, 443 { 444 name: "Test SetMark: without OOB error", 445 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)}, 446 exp: 3, 447 err: ErrOOB, 448 methodin1: 0, 449 methodin2: 3, 450 }, 451 } 452 453 func TestSetMark(t *testing.T) { 454 for _, tt := range testTableSetMark { 455 t.Run(tt.name, func(t *testing.T) { 456 err := tt.in.SetMark(tt.methodin1, tt.methodin2) 457 if err != nil { 458 if err.Error() != tt.err.Error() { 459 t.Errorf("Expected value: %v, got: %v", tt.exp, err) 460 } 461 } else { 462 if tt.exp != tt.in.marks[0] { 463 t.Errorf("Expected value: %v, got: %v", tt.exp, tt.in.marks[0]) 464 } 465 } 466 }) 467 } 468 } 469 470 // Test GetMark 471 var testTableGetMark = []struct { 472 name string 473 in *FileBuffer 474 exp int 475 err int 476 methodin byte 477 }{ 478 { 479 name: "Test GetMark: with error", 480 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)}, 481 exp: 0, 482 err: -1, 483 methodin: 0x00, 484 }, 485 { 486 name: "Test GetMark: without error", 487 in: &FileBuffer{buffer: []string{"0", "1", "2", "3"}, file: []int{0, 1, 2, 3}, marks: make(map[byte]int)}, 488 exp: 1, 489 err: 0, 490 methodin: 0x01, 491 }, 492 { 493 name: "Test GetMark: without second error", 494 in: &FileBuffer{marks: make(map[byte]int)}, 495 exp: 1, 496 err: -1, 497 methodin: 0x01, 498 }, 499 } 500 501 func TestGetMark(t *testing.T) { 502 for _, tt := range testTableGetMark { 503 t.Run(tt.name, func(t *testing.T) { 504 tt.in.marks[1] = 1 505 got, err := tt.in.GetMark(tt.methodin) 506 if err != nil { 507 if got != tt.err { 508 t.Errorf("Expected value: %v, got: %v", tt.err, err) 509 } 510 } else { 511 if reflect.DeepEqual(got, tt.in.marks[0]) { 512 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 513 } 514 } 515 }) 516 } 517 } 518 519 // Test Read 520 var testTableRead = []struct { 521 name string 522 in *FileBuffer 523 err error 524 methodin1 int 525 methodin2 io.Reader 526 }{ 527 { 528 name: "Test Read", 529 in: &FileBuffer{}, 530 err: nil, 531 methodin1: 0, 532 methodin2: &bytes.Buffer{}, 533 }, 534 } 535 536 func TestRead(t *testing.T) { 537 for _, tt := range testTableRead { 538 t.Run(tt.name, func(t *testing.T) { 539 err := tt.in.Read(tt.methodin1, tt.methodin2) 540 if err != nil { 541 if err != tt.err { 542 t.Errorf("Expected value: %v, got: %v", tt.err, err) 543 } 544 } 545 }) 546 } 547 } 548 549 // Test ReadFile 550 func CreateFile(name string) string { 551 f, err := os.Create(name) 552 if err != nil { 553 return "" 554 } 555 defer f.Close() 556 f.Write([]byte{0x01}) 557 return f.Name() 558 } 559 560 var testTableReadFile = []struct { 561 name string 562 in *FileBuffer 563 err error 564 methodin1 int 565 methodin2 string 566 }{ 567 { 568 name: "Test ReadFile: file exists", 569 in: &FileBuffer{}, 570 err: nil, 571 methodin1: 0, 572 methodin2: CreateFile("readfile"), 573 }, 574 { 575 name: "Test ReadFile: file does not exist", 576 in: &FileBuffer{}, 577 err: fmt.Errorf("could not read file: open dir: no such file or directory"), 578 methodin1: 0, 579 methodin2: "dir", 580 }, 581 } 582 583 func TestReadFile(t *testing.T) { 584 for _, tt := range testTableReadFile { 585 t.Run(tt.name, func(t *testing.T) { 586 err := tt.in.ReadFile(tt.methodin1, tt.methodin2) 587 if err != nil { 588 if err.Error() != tt.err.Error() { 589 t.Errorf("Expected value: %v, got: %v", tt.err, err) 590 } 591 } 592 os.Remove(tt.methodin2) 593 594 }) 595 } 596 } 597 598 // Test FileToBuffer 599 var testTableFileToBuffer = []struct { 600 name string 601 in *FileBuffer 602 exp *FileBuffer 603 err error 604 methodin string 605 }{ 606 { 607 name: "Test FileToBuffer: file exists", 608 in: &FileBuffer{}, 609 exp: &FileBuffer{mod: true, file: []int{0}}, 610 err: fmt.Errorf(""), 611 methodin: CreateFile("filetobuffer"), 612 }, 613 { 614 name: "Test FileToBuffer: file does not exist", 615 in: &FileBuffer{}, 616 exp: NewFileBuffer(nil), 617 err: fmt.Errorf("could not read file: open %s: no such file or directory", "dir"), 618 methodin: "dir", 619 }, 620 } 621 622 func TestFileToBuffer(t *testing.T) { 623 for _, tt := range testTableFileToBuffer { 624 t.Run(tt.name, func(t *testing.T) { 625 got, err := FileToBuffer(tt.methodin) 626 if err != nil { 627 if err.Error() != tt.err.Error() { 628 t.Errorf("Expected value: %v, got: %v", tt.err, err) 629 } 630 } else if reflect.DeepEqual(tt.exp, got) { 631 t.Errorf("Expected value: %v, got: %v", tt.exp, got) 632 } 633 os.Remove(tt.methodin) 634 }) 635 } 636 }