github.com/astrogo/cfitsio@v0.1.0/table_test.go (about) 1 package cfitsio 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "reflect" 8 "testing" 9 ) 10 11 func TestTable(t *testing.T) { 12 for _, table := range g_tables { 13 fname := table.fname 14 f, err := Open(fname, ReadOnly) 15 if err != nil { 16 t.Fatalf("error opening file [%v]: %v", fname, err) 17 } 18 19 for i := range f.HDUs() { 20 hdu, ok := f.HDU(i).(*Table) 21 if !ok { 22 continue 23 } 24 for irow := int64(0); irow < hdu.NumRows(); irow++ { 25 err := hdu.readRow(irow) 26 if err != nil { 27 t.Fatalf( 28 "error reading row [%v] (fname=%v, table=%v): %v", 29 irow, fname, hdu.Name(), err, 30 ) 31 } 32 } 33 } 34 } 35 } 36 37 func TestTableNext(t *testing.T) { 38 for _, table := range g_tables { 39 fname := table.fname 40 f, err := Open(fname, ReadOnly) 41 if err != nil { 42 t.Fatalf("error opening file [%v]: %v", fname, err) 43 } 44 45 for i := range f.HDUs() { 46 hdu, ok := f.HDU(i).(*Table) 47 if !ok { 48 continue 49 } 50 51 nrows := hdu.NumRows() 52 // iter over all rows 53 rows, err := hdu.Read(0, nrows) 54 if err != nil { 55 t.Fatalf("table.Read: %v", err) 56 } 57 count := int64(0) 58 for rows.Next() { 59 count++ 60 } 61 err = rows.Err() 62 if err != nil { 63 t.Fatalf("rows.Err: %v", err) 64 } 65 if count != nrows { 66 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 67 } 68 69 // iter over no row 70 rows, err = hdu.Read(0, 0) 71 if err != nil { 72 t.Fatalf("table.Read: %v", err) 73 } 74 count = int64(0) 75 for rows.Next() { 76 count++ 77 } 78 err = rows.Err() 79 if err != nil { 80 t.Fatalf("rows.Err: %v", err) 81 } 82 if count != 0 { 83 t.Fatalf("rows.Next: expected [%d] rows. got %d.", 0, count) 84 } 85 86 // iter over 1 row 87 rows, err = hdu.Read(0, 1) 88 if err != nil { 89 t.Fatalf("table.Read: %v", err) 90 } 91 count = int64(0) 92 for rows.Next() { 93 count++ 94 } 95 err = rows.Err() 96 if err != nil { 97 t.Fatalf("rows.Err: %v", err) 98 } 99 if count != 1 { 100 t.Fatalf("rows.Next: expected [%d] rows. got %d.", 1, count) 101 } 102 103 // iter over all rows 104 rows, err = hdu.Read(0, nrows) 105 if err != nil { 106 t.Fatalf("table.Read: %v", err) 107 } 108 count = int64(0) 109 for rows.Next() { 110 count++ 111 } 112 err = rows.Err() 113 if err != nil { 114 t.Fatalf("rows.Err: %v", err) 115 } 116 if count != nrows { 117 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 118 } 119 120 // iter over all rows +1 121 rows, err = hdu.Read(0, nrows+1) 122 if err != nil { 123 t.Fatalf("table.Read: %v", err) 124 } 125 count = int64(0) 126 for rows.Next() { 127 count++ 128 } 129 err = rows.Err() 130 if err != nil { 131 t.Fatalf("rows.Err: %v", err) 132 } 133 if count != nrows { 134 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 135 } 136 137 // iter over all rows -1 138 rows, err = hdu.Read(1, nrows) 139 if err != nil { 140 t.Fatalf("table.Read: %v", err) 141 } 142 count = int64(0) 143 for rows.Next() { 144 count++ 145 } 146 err = rows.Err() 147 if err != nil { 148 t.Fatalf("rows.Err: %v", err) 149 } 150 if count != nrows-1 { 151 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows-1, count) 152 } 153 154 // iter over [1,1+maxrows -1) 155 rows, err = hdu.Read(1, nrows-1) 156 if err != nil { 157 t.Fatalf("table.Read: %v", err) 158 } 159 count = int64(0) 160 for rows.Next() { 161 count++ 162 } 163 err = rows.Err() 164 if err != nil { 165 t.Fatalf("rows.Err: %v", err) 166 } 167 exp := nrows - 2 168 if exp <= 0 { 169 exp = 0 170 } 171 if count != exp { 172 t.Fatalf("rows.Next: expected [%d] rows. got %d.", exp, count) 173 } 174 175 // iter over last row 176 rows, err = hdu.Read(nrows-1, nrows) 177 if err != nil { 178 t.Fatalf("table.Read: %v", err) 179 } 180 count = int64(0) 181 for rows.Next() { 182 count++ 183 } 184 err = rows.Err() 185 if err != nil { 186 t.Fatalf("rows.Err: %v", err) 187 } 188 if count != 1 { 189 t.Fatalf("rows.Next: expected [%d] rows. got %d.", 1, count) 190 } 191 192 } 193 } 194 } 195 196 func TestTableErrScan(t *testing.T) { 197 for _, table := range g_tables { 198 fname := table.fname 199 f, err := Open(fname, ReadOnly) 200 if err != nil { 201 t.Fatalf("error opening file [%v]: %v", fname, err) 202 } 203 204 for i := range f.HDUs() { 205 hdu, ok := f.HDU(i).(*Table) 206 if !ok { 207 continue 208 } 209 nrows := hdu.NumRows() 210 rows, err := hdu.Read(0, nrows) 211 if err != nil { 212 t.Fatalf("table.Read: %v", err) 213 } 214 count := int64(0) 215 for rows.Next() { 216 count++ 217 err = rows.Scan() 218 if err != nil { 219 t.Fatalf("rows.Scan: error: %v", err) 220 } 221 222 dummy := 0 223 err = rows.Scan(&dummy) // none of the tables has only 1 field 224 if err == nil { 225 t.Fatalf("rows.Scan: expected a failure") 226 } 227 } 228 err = rows.Err() 229 if err != nil { 230 t.Fatalf("rows.Err: %v", err) 231 } 232 if count != nrows { 233 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 234 } 235 } 236 } 237 } 238 239 func TestTableScan(t *testing.T) { 240 for _, table := range g_tables { 241 fname := table.fname 242 f, err := Open(fname, ReadOnly) 243 if err != nil { 244 t.Fatalf("error opening file [%v]: %v", fname, err) 245 } 246 247 for i := range f.HDUs() { 248 hdu, ok := f.HDU(i).(*Table) 249 if !ok { 250 continue 251 } 252 nrows := hdu.NumRows() 253 rows, err := hdu.Read(0, nrows) 254 if err != nil { 255 t.Fatalf("table.Read: %v", err) 256 } 257 count := int64(0) 258 for rows.Next() { 259 ref := make([]interface{}, len(table.tuple[i][count])) 260 data := make([]interface{}, len(ref)) 261 for ii, vv := range table.tuple[i][count] { 262 rt := reflect.TypeOf(vv) 263 rv := reflect.New(rt) 264 xx := rv.Interface() 265 data[ii] = xx 266 ref[ii] = vv 267 } 268 err = rows.Scan(data...) 269 if err != nil { 270 t.Fatalf("rows.Scan: %v", err) 271 } 272 // check data just read in is ok 273 // check columns data is ok 274 for ii, vv := range data { 275 rv := reflect.ValueOf(vv).Elem().Interface() 276 if !reflect.DeepEqual(rv, hdu.Col(ii).Value) { 277 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", hdu.Col(ii).Value, rv) 278 } 279 if !reflect.DeepEqual(rv, ref[ii]) { 280 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref[ii], rv) 281 } 282 } 283 // modify value of first column 284 switch vv := hdu.Col(0).Value.(type) { 285 case float64: 286 hdu.Col(0).Value = 1 + vv 287 case int16: 288 hdu.Col(0).Value = 1 + vv 289 } 290 // check data just read in is ok 291 // check columns data is ok 292 for ii, vv := range data { 293 if ii == 0 { 294 continue 295 } 296 rv := reflect.ValueOf(vv).Elem().Interface() 297 if !reflect.DeepEqual(rv, hdu.Col(ii).Value) { 298 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", hdu.Col(ii).Value, rv) 299 } 300 if !reflect.DeepEqual(rv, ref[ii]) { 301 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref[ii], rv) 302 } 303 } 304 // but column data has changed 305 if reflect.DeepEqual(reflect.ValueOf(data[0]).Elem().Interface(), hdu.Col(0).Value) { 306 t.Fatalf("expected different values!") 307 } 308 count++ 309 } 310 err = rows.Err() 311 if err != nil { 312 t.Fatalf("rows.Err: %v", err) 313 } 314 if count != nrows { 315 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 316 } 317 } 318 } 319 } 320 321 func TestTableScanMap(t *testing.T) { 322 for _, table := range g_tables { 323 fname := table.fname 324 f, err := Open(fname, ReadOnly) 325 if err != nil { 326 t.Fatalf("error opening file [%v]: %v", fname, err) 327 } 328 329 for i := range f.HDUs() { 330 hdu, ok := f.HDU(i).(*Table) 331 if !ok { 332 continue 333 } 334 refmap := table.maps[i] 335 if len(refmap) <= 0 { 336 continue 337 } 338 nrows := hdu.NumRows() 339 rows, err := hdu.Read(0, nrows) 340 if err != nil { 341 t.Fatalf("table.Read: %v", err) 342 } 343 count := int64(0) 344 for rows.Next() { 345 ref := make(map[string]interface{}, len(refmap)) 346 data := make(map[string]interface{}, len(refmap)) 347 for kk, vv := range table.maps[i] { 348 rt := reflect.TypeOf(vv) 349 rv := reflect.New(rt) 350 xx := rv.Interface() 351 data[kk] = xx 352 ii := hdu.Index(kk) 353 if ii < 0 { 354 t.Fatalf("could not find index of [%v]", kk) 355 } 356 ref[kk] = table.tuple[i][count][ii] 357 } 358 err = rows.Scan(&data) 359 if err != nil { 360 t.Fatalf("rows.Scan: %v", err) 361 } 362 // check data just read in is ok 363 if !reflect.DeepEqual(data, ref) { 364 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref, data) 365 } 366 // check columns data is ok 367 for kk, vv := range data { 368 ii := hdu.Index(kk) 369 if !reflect.DeepEqual(vv, hdu.Col(ii).Value) { 370 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", hdu.Col(ii).Value, vv) 371 } 372 } 373 // modify value of first column 374 kk := hdu.Col(0).Name 375 switch vv := hdu.Col(0).Value.(type) { 376 case float64: 377 hdu.Col(0).Value = 1 + vv 378 case int16: 379 hdu.Col(0).Value = 1 + vv 380 } 381 // check data is still ok 382 if !reflect.DeepEqual(data, ref) { 383 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref, data) 384 } 385 // but column data has changed 386 if reflect.DeepEqual(data[kk], hdu.Col(0).Value) { 387 t.Fatalf("expected different values!") 388 } 389 count++ 390 } 391 err = rows.Err() 392 if err != nil { 393 t.Fatalf("rows.Err: %v", err) 394 } 395 if count != nrows { 396 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 397 } 398 } 399 } 400 } 401 402 func TestTableScanStruct(t *testing.T) { 403 for _, table := range g_tables { 404 fname := table.fname 405 f, err := Open(fname, ReadOnly) 406 if err != nil { 407 t.Fatalf("error opening file [%v]: %v", fname, err) 408 } 409 410 for i := range f.HDUs() { 411 hdu, ok := f.HDU(i).(*Table) 412 if !ok { 413 continue 414 } 415 reftypes := table.types[i] 416 if reftypes == nil { 417 continue 418 } 419 reftype := reflect.TypeOf(reftypes) 420 nrows := hdu.NumRows() 421 rows, err := hdu.Read(0, nrows) 422 if err != nil { 423 t.Fatalf("table.Read: %v", err) 424 } 425 count := int64(0) 426 for rows.Next() { 427 ref := reflect.New(reftype) 428 data := reflect.New(reftype) 429 for ii := 0; ii < reftype.NumField(); ii++ { 430 ft := reftype.Field(ii) 431 kk := ft.Tag.Get("fits") 432 if kk == "" { 433 kk = ft.Name 434 } 435 idx := hdu.Index(kk) 436 if idx < 0 { 437 t.Fatalf("could not find index of [%v.%v]", reftype.Name(), ft.Name) 438 } 439 vv := reflect.ValueOf(table.tuple[i][count][idx]) 440 reflect.Indirect(ref).Field(ii).Set(vv) 441 } 442 443 err = rows.Scan(data.Interface()) 444 if err != nil { 445 t.Fatalf("rows.Scan: %v", err) 446 } 447 // check data just read in is ok 448 if !reflect.DeepEqual(data.Interface(), ref.Interface()) { 449 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref, data) 450 } 451 // check columns data is ok 452 for ii := 0; ii < reftype.NumField(); ii++ { 453 ft := reftype.Field(ii) 454 kk := ft.Tag.Get("fits") 455 if kk == "" { 456 kk = ft.Name 457 } 458 idx := hdu.Index(kk) 459 if idx < 0 { 460 t.Fatalf("could not find index of [%v.%v]", reftype.Name(), ft.Name) 461 } 462 vv := data.Elem().Field(ii).Interface() 463 if !reflect.DeepEqual(vv, hdu.Col(idx).Value) { 464 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", hdu.Col(idx).Value, vv) 465 } 466 } 467 // modify value of first column 468 switch vv := hdu.Col(0).Value.(type) { 469 case float64: 470 hdu.Col(0).Value = 1 + vv 471 case int16: 472 hdu.Col(0).Value = 1 + vv 473 } 474 // check data is still ok 475 if !reflect.DeepEqual(data.Interface(), ref.Interface()) { 476 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v", ref, data) 477 } 478 // but column data has changed 479 if reflect.DeepEqual(data.Elem().Field(0).Interface(), hdu.Col(0).Value) { 480 t.Fatalf("expected different values!") 481 } 482 count++ 483 } 484 err = rows.Err() 485 if err != nil { 486 t.Fatalf("rows.Err: %v", err) 487 } 488 if count != nrows { 489 t.Fatalf("rows.Next: expected [%d] rows. got %d.", nrows, count) 490 } 491 } 492 } 493 } 494 495 func TestTableBuiltinsRW(t *testing.T) { 496 497 curdir, err := os.Getwd() 498 if err != nil { 499 t.Fatalf(err.Error()) 500 } 501 defer os.Chdir(curdir) 502 503 workdir, err := ioutil.TempDir("", "go-cfitsio-test-") 504 if err != nil { 505 t.Fatalf(err.Error()) 506 } 507 defer os.RemoveAll(workdir) 508 509 err = os.Chdir(workdir) 510 if err != nil { 511 t.Fatalf(err.Error()) 512 } 513 514 for ii, table := range []struct { 515 name string 516 cols []Column 517 htype HDUType 518 table interface{} 519 }{ 520 { 521 name: "new.fits", 522 cols: []Column{ 523 { 524 Name: "int8s", 525 Value: int8(42), 526 }, 527 }, 528 htype: ASCII_TBL, 529 table: []int8{ 530 10, 11, 12, 13, 531 14, 15, 16, 17, 532 18, 19, 10, 11, 533 }, 534 }, 535 { 536 name: "new.fits", 537 cols: []Column{ 538 { 539 Name: "int16s", 540 Value: int16(42), 541 }, 542 }, 543 htype: ASCII_TBL, 544 table: []int16{ 545 10, 11, 12, 13, 546 14, 15, 16, 17, 547 18, 19, 10, 11, 548 }, 549 }, 550 { 551 name: "new.fits", 552 cols: []Column{ 553 { 554 Name: "int32s", 555 Value: int32(42), 556 }, 557 }, 558 htype: ASCII_TBL, 559 table: []int32{ 560 10, 11, 12, 13, 561 14, 15, 16, 17, 562 18, 19, 10, 11, 563 }, 564 }, 565 { 566 name: "new.fits", 567 cols: []Column{ 568 { 569 Name: "int64s", 570 Value: int64(42), 571 }, 572 }, 573 htype: ASCII_TBL, 574 table: []int64{ 575 10, 11, 12, 13, 576 14, 15, 16, 17, 577 18, 19, 10, 11, 578 }, 579 }, 580 { 581 name: "new.fits", 582 cols: []Column{ 583 { 584 Name: "ints", 585 Value: int(42), 586 }, 587 }, 588 htype: ASCII_TBL, 589 table: []int{ 590 10, 11, 12, 13, 591 14, 15, 16, 17, 592 18, 19, 10, 11, 593 }, 594 }, 595 { 596 name: "new.fits", 597 cols: []Column{ 598 { 599 Name: "uint8s", 600 Value: uint8(42), 601 }, 602 }, 603 htype: ASCII_TBL, 604 table: []uint8{ 605 10, 11, 12, 13, 606 14, 15, 16, 17, 607 18, 19, 10, 11, 608 }, 609 }, 610 { 611 name: "new.fits", 612 cols: []Column{ 613 { 614 Name: "uint16s", 615 Value: uint16(42), 616 }, 617 }, 618 htype: ASCII_TBL, 619 table: []uint16{ 620 10, 11, 12, 13, 621 14, 15, 16, 17, 622 18, 19, 10, 11, 623 }, 624 }, 625 { 626 name: "new.fits", 627 cols: []Column{ 628 { 629 Name: "uint32s", 630 Value: uint32(42), 631 }, 632 }, 633 htype: ASCII_TBL, 634 table: []uint32{ 635 10, 11, 12, 13, 636 14, 15, 16, 17, 637 18, 19, 10, 11, 638 }, 639 }, 640 { 641 name: "new.fits", 642 cols: []Column{ 643 { 644 Name: "uint64s", 645 Value: uint64(42), 646 }, 647 }, 648 htype: ASCII_TBL, 649 table: []uint64{ 650 10, 11, 12, 13, 651 14, 15, 16, 17, 652 18, 19, 10, 11, 653 }, 654 }, 655 { 656 name: "new.fits", 657 cols: []Column{ 658 { 659 Name: "uints", 660 Value: uint(42), 661 }, 662 }, 663 htype: ASCII_TBL, 664 table: []uint{ 665 10, 11, 12, 13, 666 14, 15, 16, 17, 667 18, 19, 10, 11, 668 }, 669 }, 670 { 671 name: "new.fits", 672 cols: []Column{ 673 { 674 Name: "float32s", 675 Value: float32(42), 676 }, 677 }, 678 htype: ASCII_TBL, 679 table: []float32{ 680 10, 11, 12, 13, 681 14, 15, 16, 17, 682 18, 19, 10, 11, 683 }, 684 }, 685 { 686 name: "new.fits", 687 cols: []Column{ 688 { 689 Name: "float64s", 690 Value: float64(42), 691 }, 692 }, 693 htype: ASCII_TBL, 694 table: []float64{ 695 10, 11, 12, 13, 696 14, 15, 16, 17, 697 18, 19, 10, 11, 698 }, 699 }, 700 { 701 name: "new.fits", 702 cols: []Column{ 703 { 704 Name: "strings", 705 Value: "", 706 }, 707 }, 708 htype: ASCII_TBL, 709 table: []string{ 710 "10", "11", "12", "13", 711 "14", "15", "16", "17", 712 "18", "19", "10", "11", 713 }, 714 }, 715 // binary table 716 { 717 name: "new.fits", 718 cols: []Column{ 719 { 720 Name: "bools", 721 Value: false, 722 }, 723 }, 724 htype: BINARY_TBL, 725 table: []bool{ 726 true, true, true, true, 727 false, false, false, false, 728 true, false, true, false, 729 false, true, false, true, 730 }, 731 }, 732 { 733 name: "new.fits", 734 cols: []Column{ 735 { 736 Name: "int8s", 737 Value: int8(42), 738 }, 739 }, 740 htype: BINARY_TBL, 741 table: []int8{ 742 10, 11, 12, 13, 743 14, 15, 16, 17, 744 18, 19, 10, 11, 745 }, 746 }, 747 { 748 name: "new.fits", 749 cols: []Column{ 750 { 751 Name: "int16s", 752 Value: int16(42), 753 }, 754 }, 755 htype: BINARY_TBL, 756 table: []int16{ 757 10, 11, 12, 13, 758 14, 15, 16, 17, 759 18, 19, 10, 11, 760 }, 761 }, 762 { 763 name: "new.fits", 764 cols: []Column{ 765 { 766 Name: "int32s", 767 Value: int32(42), 768 }, 769 }, 770 htype: BINARY_TBL, 771 table: []int32{ 772 10, 11, 12, 13, 773 14, 15, 16, 17, 774 18, 19, 10, 11, 775 }, 776 }, 777 { 778 name: "new.fits", 779 cols: []Column{ 780 { 781 Name: "int64s", 782 Value: int64(42), 783 }, 784 }, 785 htype: BINARY_TBL, 786 table: []int64{ 787 10, 11, 12, 13, 788 14, 15, 16, 17, 789 18, 19, 10, 11, 790 }, 791 }, 792 { 793 name: "new.fits", 794 cols: []Column{ 795 { 796 Name: "ints", 797 Value: int(42), 798 }, 799 }, 800 htype: BINARY_TBL, 801 table: []int{ 802 10, 11, 12, 13, 803 14, 15, 16, 17, 804 18, 19, 10, 11, 805 }, 806 }, 807 { 808 name: "new.fits", 809 cols: []Column{ 810 { 811 Name: "uint8s", 812 Value: uint8(42), 813 }, 814 }, 815 htype: BINARY_TBL, 816 table: []uint8{ 817 10, 11, 12, 13, 818 14, 15, 16, 17, 819 18, 19, 10, 11, 820 }, 821 }, 822 { 823 name: "new.fits", 824 cols: []Column{ 825 { 826 Name: "uint16s", 827 Value: uint16(42), 828 }, 829 }, 830 htype: BINARY_TBL, 831 table: []uint16{ 832 10, 11, 12, 13, 833 14, 15, 16, 17, 834 18, 19, 10, 11, 835 }, 836 }, 837 { 838 name: "new.fits", 839 cols: []Column{ 840 { 841 Name: "uint32s", 842 Value: uint32(42), 843 }, 844 }, 845 htype: BINARY_TBL, 846 table: []uint32{ 847 10, 11, 12, 13, 848 14, 15, 16, 17, 849 18, 19, 10, 11, 850 }, 851 }, 852 { 853 name: "new.fits", 854 cols: []Column{ 855 { 856 Name: "uint64s", 857 Value: uint64(42), 858 }, 859 }, 860 htype: BINARY_TBL, 861 table: []uint64{ 862 10, 11, 12, 13, 863 14, 15, 16, 17, 864 18, 19, 10, 11, 865 }, 866 }, 867 { 868 name: "new.fits", 869 cols: []Column{ 870 { 871 Name: "uints", 872 Value: uint(42), 873 }, 874 }, 875 htype: BINARY_TBL, 876 table: []uint{ 877 10, 11, 12, 13, 878 14, 15, 16, 17, 879 18, 19, 10, 11, 880 }, 881 }, 882 { 883 name: "new.fits", 884 cols: []Column{ 885 { 886 Name: "float32s", 887 Value: float32(42), 888 }, 889 }, 890 htype: BINARY_TBL, 891 table: []float32{ 892 10, 11, 12, 13, 893 14, 15, 16, 17, 894 18, 19, 10, 11, 895 }, 896 }, 897 { 898 name: "new.fits", 899 cols: []Column{ 900 { 901 Name: "float64s", 902 Value: float64(42), 903 }, 904 }, 905 htype: BINARY_TBL, 906 table: []float64{ 907 10, 11, 12, 13, 908 14, 15, 16, 17, 909 18, 19, 10, 11, 910 }, 911 }, 912 { 913 name: "new.fits", 914 cols: []Column{ 915 { 916 Name: "cplx64s", 917 Value: complex(float32(42), float32(42)), 918 }, 919 }, 920 htype: BINARY_TBL, 921 table: []complex64{ 922 complex(float32(10), float32(10)), complex(float32(11), float32(11)), 923 complex(float32(12), float32(12)), complex(float32(13), float32(13)), 924 complex(float32(14), float32(14)), complex(float32(15), float32(15)), 925 complex(float32(16), float32(16)), complex(float32(17), float32(17)), 926 complex(float32(18), float32(18)), complex(float32(19), float32(19)), 927 complex(float32(10), float32(10)), complex(float32(11), float32(11)), 928 }, 929 }, 930 { 931 name: "new.fits", 932 cols: []Column{ 933 { 934 Name: "cplx128s", 935 Value: complex(float64(42), float64(42)), 936 }, 937 }, 938 htype: BINARY_TBL, 939 table: []complex128{ 940 complex(10, 10), complex(11, 11), complex(12, 12), complex(13, 13), 941 complex(14, 14), complex(15, 15), complex(16, 16), complex(17, 17), 942 complex(18, 18), complex(19, 19), complex(10, 10), complex(11, 11), 943 }, 944 }, 945 { 946 name: "new.fits", 947 cols: []Column{ 948 { 949 Name: "strings", 950 Value: "", 951 }, 952 }, 953 htype: BINARY_TBL, 954 table: []string{ 955 "10", "11", "12", "13", 956 "14", "15", "16", "17", 957 "18", "19", "10", "11", 958 }, 959 }, 960 { 961 name: "new.fits", 962 cols: []Column{ 963 { 964 Name: "float64s", 965 Value: [2]float64{}, 966 }, 967 }, 968 htype: BINARY_TBL, 969 table: [][2]float64{ 970 {10, 11}, 971 {12, 13}, 972 {14, 15}, 973 {16, 17}, 974 {18, 19}, 975 {10, 11}, 976 }, 977 }, 978 } { 979 fname := fmt.Sprintf("%03d_%s", ii, table.name) 980 for _, fct := range []func(){ 981 // create 982 func() { 983 f, err := Create(fname) 984 if err != nil { 985 t.Fatalf("error creating new file [%v]: %v", fname, err) 986 } 987 defer f.Close() 988 989 phdu, err := NewPrimaryHDU(&f, NewDefaultHeader()) 990 if err != nil { 991 t.Fatalf("error creating PHDU: %v", err) 992 } 993 defer phdu.Close() 994 995 tbl, err := NewTable(&f, "test", table.cols, table.htype) 996 if err != nil { 997 t.Fatalf("error creating new table: %v (%v)", err, table.cols[0].Name) 998 } 999 defer tbl.Close() 1000 1001 rslice := reflect.ValueOf(table.table) 1002 for i := 0; i < rslice.Len(); i++ { 1003 data := rslice.Index(i).Addr() 1004 err = tbl.Write(data.Interface()) 1005 if err != nil { 1006 t.Fatalf("error writing row [%v]: %v (data=%v %T)", i, err, data.Interface(), data.Interface()) 1007 } 1008 } 1009 1010 nrows := tbl.NumRows() 1011 if nrows != int64(rslice.Len()) { 1012 t.Fatalf("expected num rows [%v]. got [%v] (%v)", rslice.Len(), nrows, table.cols[0].Name) 1013 } 1014 }, 1015 // read 1016 func() { 1017 f, err := Open(fname, ReadOnly) 1018 if err != nil { 1019 t.Fatalf("error opening file [%v]: %v", fname, err) 1020 } 1021 defer f.Close() 1022 1023 hdu := f.HDU(1) 1024 tbl := hdu.(*Table) 1025 if tbl.Name() != "test" { 1026 t.Fatalf("expected table name==%q. got %q", "test", tbl.Name()) 1027 } 1028 1029 rslice := reflect.ValueOf(table.table) 1030 nrows := tbl.NumRows() 1031 if nrows != int64(rslice.Len()) { 1032 t.Fatalf("expected num rows [%v]. got [%v]", rslice.Len(), nrows) 1033 } 1034 1035 rows, err := tbl.Read(0, nrows) 1036 if err != nil { 1037 t.Fatalf("table.Read: %v", err) 1038 } 1039 count := int64(0) 1040 for rows.Next() { 1041 ref := rslice.Index(int(count)).Interface() 1042 rt := reflect.TypeOf(ref) 1043 data := reflect.New(rt).Elem().Interface() 1044 err = rows.Scan(&data) 1045 if err != nil { 1046 t.Fatalf("rows.Scan: %v", err) 1047 } 1048 // check data just read in is ok 1049 if !reflect.DeepEqual(data, ref) { 1050 t.Fatalf("rows.Scan: %[3]s\nexp=%[1]v (%[1]T)\ngot=%[2]v (%[2]T)", ref, data, table.cols[0].Name) 1051 } 1052 count++ 1053 } 1054 if count != nrows { 1055 t.Fatalf("expected [%v] rows. got [%v]", nrows, count) 1056 } 1057 }, 1058 } { 1059 fct() 1060 } 1061 } 1062 } 1063 1064 func TestTableSliceRW(t *testing.T) { 1065 1066 curdir, err := os.Getwd() 1067 if err != nil { 1068 t.Fatalf(err.Error()) 1069 } 1070 defer os.Chdir(curdir) 1071 1072 workdir, err := ioutil.TempDir("", "go-cfitsio-test-") 1073 if err != nil { 1074 t.Fatalf(err.Error()) 1075 } 1076 defer os.RemoveAll(workdir) 1077 1078 err = os.Chdir(workdir) 1079 if err != nil { 1080 t.Fatalf(err.Error()) 1081 } 1082 1083 for ii, table := range []struct { 1084 name string 1085 cols []Column 1086 htype HDUType 1087 table interface{} 1088 }{ 1089 // binary table 1090 { 1091 name: "new.fits", 1092 cols: []Column{ 1093 { 1094 Name: "bools", 1095 Value: []bool{}, 1096 }, 1097 }, 1098 htype: BINARY_TBL, 1099 table: [][]bool{ 1100 {true, true, true, true}, 1101 {false, false, false, false}, 1102 {true, false, true, false}, 1103 {false, true, false, true}, 1104 }, 1105 }, 1106 { 1107 name: "new.fits", 1108 cols: []Column{ 1109 { 1110 Name: "int8s", 1111 Value: []int8{}, 1112 }, 1113 }, 1114 htype: BINARY_TBL, 1115 table: [][]int8{ 1116 {10, 11, 12, 13}, 1117 {14, 15, 16, 17}, 1118 {18, 19, 10, 11}, 1119 }, 1120 }, 1121 { 1122 name: "new.fits", 1123 cols: []Column{ 1124 { 1125 Name: "int16s", 1126 Value: []int16{}, 1127 }, 1128 }, 1129 htype: BINARY_TBL, 1130 table: [][]int16{ 1131 {10, 11, 12, 13}, 1132 {14, 15, 16, 17}, 1133 {18, 19, 10, 11}, 1134 }, 1135 }, 1136 { 1137 name: "new.fits", 1138 cols: []Column{ 1139 { 1140 Name: "int32s", 1141 Value: []int32{}, 1142 }, 1143 }, 1144 htype: BINARY_TBL, 1145 table: [][]int32{ 1146 {10, 11, 12, 13}, 1147 {14, 15, 16, 17}, 1148 {18, 19, 10, 11}, 1149 }, 1150 }, 1151 { 1152 name: "new.fits", 1153 cols: []Column{ 1154 { 1155 Name: "int64s", 1156 Value: []int64{}, 1157 }, 1158 }, 1159 htype: BINARY_TBL, 1160 table: [][]int64{ 1161 {10, 11, 12, 13}, 1162 {14, 15, 16, 17}, 1163 {18, 19, 10, 11}, 1164 }, 1165 }, 1166 { 1167 name: "new.fits", 1168 cols: []Column{ 1169 { 1170 Name: "ints", 1171 Value: []int{}, 1172 }, 1173 }, 1174 htype: BINARY_TBL, 1175 table: [][]int{ 1176 {10, 11, 12, 13}, 1177 {14, 15, 16, 17}, 1178 {18, 19, 10, 11}, 1179 }, 1180 }, 1181 { 1182 name: "new.fits", 1183 cols: []Column{ 1184 { 1185 Name: "uint8s", 1186 Value: []uint8{}, 1187 }, 1188 }, 1189 htype: BINARY_TBL, 1190 table: [][]uint8{ 1191 {10, 11, 12, 13}, 1192 {14, 15, 16, 17}, 1193 {18, 19, 10, 11}, 1194 }, 1195 }, 1196 { 1197 name: "new.fits", 1198 cols: []Column{ 1199 { 1200 Name: "uint16s", 1201 Value: []uint16{}, 1202 }, 1203 }, 1204 htype: BINARY_TBL, 1205 table: [][]uint16{ 1206 {10, 11, 12, 13}, 1207 {14, 15, 16, 17}, 1208 {18, 19, 10, 11}, 1209 }, 1210 }, 1211 { 1212 name: "new.fits", 1213 cols: []Column{ 1214 { 1215 Name: "uint32s", 1216 Value: []uint32{}, 1217 }, 1218 }, 1219 htype: BINARY_TBL, 1220 table: [][]uint32{ 1221 {10, 11, 12, 13}, 1222 {14, 15, 16, 17}, 1223 {18, 19, 10, 11}, 1224 }, 1225 }, 1226 { 1227 name: "new.fits", 1228 cols: []Column{ 1229 { 1230 Name: "uint64s", 1231 Value: []uint64{}, 1232 }, 1233 }, 1234 htype: BINARY_TBL, 1235 table: [][]uint64{ 1236 {10, 11, 12, 13}, 1237 {14, 15, 16, 17}, 1238 {18, 19, 10, 11}, 1239 }, 1240 }, 1241 { 1242 name: "new.fits", 1243 cols: []Column{ 1244 { 1245 Name: "uints", 1246 Value: []uint{}, 1247 }, 1248 }, 1249 htype: BINARY_TBL, 1250 table: [][]uint{ 1251 {10, 11, 12, 13}, 1252 {14, 15, 16, 17}, 1253 {18, 19, 10, 11}, 1254 }, 1255 }, 1256 { 1257 name: "new.fits", 1258 cols: []Column{ 1259 { 1260 Name: "float32s", 1261 Value: []float32{}, 1262 }, 1263 }, 1264 htype: BINARY_TBL, 1265 table: [][]float32{ 1266 {10, 11, 12, 13}, 1267 {14, 15, 16, 17}, 1268 {18, 19, 10, 11}, 1269 }, 1270 }, 1271 { 1272 name: "new.fits", 1273 cols: []Column{ 1274 { 1275 Name: "float64s", 1276 Value: []float64{}, 1277 }, 1278 }, 1279 htype: BINARY_TBL, 1280 table: [][]float64{ 1281 {10, 11, 12, 13}, 1282 {14, 15, 16, 17}, 1283 {18, 19, 10, 11}, 1284 }, 1285 }, 1286 { 1287 name: "new.fits", 1288 cols: []Column{ 1289 { 1290 Name: "cplx64s", 1291 Value: []complex64{}, 1292 }, 1293 }, 1294 htype: BINARY_TBL, 1295 table: [][]complex64{ 1296 {complex(float32(10), float32(10)), complex(float32(11), float32(11)), 1297 complex(float32(12), float32(12)), complex(float32(13), float32(13))}, 1298 {complex(float32(14), float32(14)), complex(float32(15), float32(15)), 1299 complex(float32(16), float32(16)), complex(float32(17), float32(17))}, 1300 {complex(float32(18), float32(18)), complex(float32(19), float32(19)), 1301 complex(float32(10), float32(10)), complex(float32(11), float32(11))}, 1302 }, 1303 }, 1304 { 1305 name: "new.fits", 1306 cols: []Column{ 1307 { 1308 Name: "cplx128s", 1309 Value: []complex128{}, 1310 }, 1311 }, 1312 htype: BINARY_TBL, 1313 table: [][]complex128{ 1314 {complex(10, 10), complex(11, 11), complex(12, 12), complex(13, 13)}, 1315 {complex(14, 14), complex(15, 15), complex(16, 16), complex(17, 17)}, 1316 {complex(18, 18), complex(19, 19), complex(10, 10), complex(11, 11)}, 1317 }, 1318 }, 1319 } { 1320 fname := fmt.Sprintf("%03d_%s", ii, table.name) 1321 for _, fct := range []func(){ 1322 // create 1323 func() { 1324 f, err := Create(fname) 1325 if err != nil { 1326 t.Fatalf("error creating new file [%v]: %v", fname, err) 1327 } 1328 defer f.Close() 1329 1330 phdu, err := NewPrimaryHDU(&f, NewDefaultHeader()) 1331 if err != nil { 1332 t.Fatalf("error creating PHDU: %v", err) 1333 } 1334 defer phdu.Close() 1335 1336 tbl, err := NewTable(&f, "test", table.cols, table.htype) 1337 if err != nil { 1338 t.Fatalf("error creating new table: %v (%v)", err, table.cols[0].Name) 1339 } 1340 defer tbl.Close() 1341 1342 rslice := reflect.ValueOf(table.table) 1343 for i := 0; i < rslice.Len(); i++ { 1344 data := rslice.Index(i).Addr() 1345 err = tbl.Write(data.Interface()) 1346 if err != nil { 1347 t.Fatalf("error writing row [%v]: %v", i, err) 1348 } 1349 } 1350 1351 nrows := tbl.NumRows() 1352 if nrows != int64(rslice.Len()) { 1353 t.Fatalf("expected num rows [%v]. got [%v] (%v)", rslice.Len(), nrows, table.cols[0].Name) 1354 } 1355 }, 1356 // read 1357 func() { 1358 f, err := Open(fname, ReadOnly) 1359 if err != nil { 1360 t.Fatalf("error opening file [%v]: %v", fname, err) 1361 } 1362 defer f.Close() 1363 1364 hdu := f.HDU(1) 1365 tbl := hdu.(*Table) 1366 if tbl.Name() != "test" { 1367 t.Fatalf("expected table name==%q. got %q", "test", tbl.Name()) 1368 } 1369 1370 rslice := reflect.ValueOf(table.table) 1371 nrows := tbl.NumRows() 1372 if nrows != int64(rslice.Len()) { 1373 t.Fatalf("expected num rows [%v]. got [%v]", rslice.Len(), nrows) 1374 } 1375 1376 rows, err := tbl.Read(0, nrows) 1377 if err != nil { 1378 t.Fatalf("table.Read: %v", err) 1379 } 1380 count := int64(0) 1381 for rows.Next() { 1382 ref := rslice.Index(int(count)).Interface() 1383 rt := reflect.TypeOf(ref) 1384 data := reflect.New(rt).Elem().Interface() 1385 err = rows.Scan(&data) 1386 if err != nil { 1387 t.Fatalf("rows.Scan: %v", err) 1388 } 1389 // check data just read in is ok 1390 if !reflect.DeepEqual(data, ref) { 1391 t.Fatalf("rows.Scan: [%[3]s|%[4]v]\nexp=%[1]v (%[1]T)\ngot=%[2]v (%[2]T)", ref, data, table.cols[0].Name, table.htype) 1392 } 1393 count++ 1394 } 1395 if count != nrows { 1396 t.Fatalf("expected [%v] rows. got [%v]", nrows, count) 1397 } 1398 }, 1399 } { 1400 fct() 1401 } 1402 } 1403 } 1404 1405 func TestTableArrayRW(t *testing.T) { 1406 1407 curdir, err := os.Getwd() 1408 if err != nil { 1409 t.Fatalf(err.Error()) 1410 } 1411 defer os.Chdir(curdir) 1412 1413 workdir, err := ioutil.TempDir("", "go-cfitsio-test-") 1414 if err != nil { 1415 t.Fatalf(err.Error()) 1416 } 1417 defer os.RemoveAll(workdir) 1418 1419 err = os.Chdir(workdir) 1420 if err != nil { 1421 t.Fatalf(err.Error()) 1422 } 1423 1424 for ii, table := range []struct { 1425 name string 1426 cols []Column 1427 htype HDUType 1428 table interface{} 1429 }{ 1430 // binary table 1431 { 1432 name: "new.fits", 1433 cols: []Column{ 1434 { 1435 Name: "bools", 1436 Value: [4]bool{}, 1437 }, 1438 }, 1439 htype: BINARY_TBL, 1440 table: [][4]bool{ 1441 {true, true, true, true}, 1442 {false, false, false, false}, 1443 {true, false, true, false}, 1444 {false, true, false, true}, 1445 }, 1446 }, 1447 { 1448 name: "new.fits", 1449 cols: []Column{ 1450 { 1451 Name: "int8s", 1452 Value: [4]int8{}, 1453 }, 1454 }, 1455 htype: BINARY_TBL, 1456 table: [][4]int8{ 1457 {10, 11, 12, 13}, 1458 {14, 15, 16, 17}, 1459 {18, 19, 10, 11}, 1460 }, 1461 }, 1462 { 1463 name: "new.fits", 1464 cols: []Column{ 1465 { 1466 Name: "int16s", 1467 Value: [4]int16{}, 1468 }, 1469 }, 1470 htype: BINARY_TBL, 1471 table: [][4]int16{ 1472 {10, 11, 12, 13}, 1473 {14, 15, 16, 17}, 1474 {18, 19, 10, 11}, 1475 }, 1476 }, 1477 { 1478 name: "new.fits", 1479 cols: []Column{ 1480 { 1481 Name: "int32s", 1482 Value: [4]int32{}, 1483 }, 1484 }, 1485 htype: BINARY_TBL, 1486 table: [][4]int32{ 1487 {10, 11, 12, 13}, 1488 {14, 15, 16, 17}, 1489 {18, 19, 10, 11}, 1490 }, 1491 }, 1492 { 1493 name: "new.fits", 1494 cols: []Column{ 1495 { 1496 Name: "int64s", 1497 Value: [4]int64{}, 1498 }, 1499 }, 1500 htype: BINARY_TBL, 1501 table: [][4]int64{ 1502 {10, 11, 12, 13}, 1503 {14, 15, 16, 17}, 1504 {18, 19, 10, 11}, 1505 }, 1506 }, 1507 { 1508 name: "new.fits", 1509 cols: []Column{ 1510 { 1511 Name: "ints", 1512 Value: [4]int{}, 1513 }, 1514 }, 1515 htype: BINARY_TBL, 1516 table: [][4]int{ 1517 {10, 11, 12, 13}, 1518 {14, 15, 16, 17}, 1519 {18, 19, 10, 11}, 1520 }, 1521 }, 1522 { 1523 name: "new.fits", 1524 cols: []Column{ 1525 { 1526 Name: "uint8s", 1527 Value: [4]uint8{}, 1528 }, 1529 }, 1530 htype: BINARY_TBL, 1531 table: [][4]uint8{ 1532 {10, 11, 12, 13}, 1533 {14, 15, 16, 17}, 1534 {18, 19, 10, 11}, 1535 }, 1536 }, 1537 { 1538 name: "new.fits", 1539 cols: []Column{ 1540 { 1541 Name: "uint16s", 1542 Value: [4]uint16{}, 1543 }, 1544 }, 1545 htype: BINARY_TBL, 1546 table: [][4]uint16{ 1547 {10, 11, 12, 13}, 1548 {14, 15, 16, 17}, 1549 {18, 19, 10, 11}, 1550 }, 1551 }, 1552 { 1553 name: "new.fits", 1554 cols: []Column{ 1555 { 1556 Name: "uint32s", 1557 Value: [4]uint32{}, 1558 }, 1559 }, 1560 htype: BINARY_TBL, 1561 table: [][4]uint32{ 1562 {10, 11, 12, 13}, 1563 {14, 15, 16, 17}, 1564 {18, 19, 10, 11}, 1565 }, 1566 }, 1567 { 1568 name: "new.fits", 1569 cols: []Column{ 1570 { 1571 Name: "uint64s", 1572 Value: [4]uint64{}, 1573 }, 1574 }, 1575 htype: BINARY_TBL, 1576 table: [][4]uint64{ 1577 {10, 11, 12, 13}, 1578 {14, 15, 16, 17}, 1579 {18, 19, 10, 11}, 1580 }, 1581 }, 1582 { 1583 name: "new.fits", 1584 cols: []Column{ 1585 { 1586 Name: "uints", 1587 Value: [4]uint{}, 1588 }, 1589 }, 1590 htype: BINARY_TBL, 1591 table: [][4]uint{ 1592 {10, 11, 12, 13}, 1593 {14, 15, 16, 17}, 1594 {18, 19, 10, 11}, 1595 }, 1596 }, 1597 { 1598 name: "new.fits", 1599 cols: []Column{ 1600 { 1601 Name: "float32s", 1602 Value: [4]float32{}, 1603 }, 1604 }, 1605 htype: BINARY_TBL, 1606 table: [][4]float32{ 1607 {10, 11, 12, 13}, 1608 {14, 15, 16, 17}, 1609 {18, 19, 10, 11}, 1610 }, 1611 }, 1612 { 1613 name: "new.fits", 1614 cols: []Column{ 1615 { 1616 Name: "float64s", 1617 Value: [4]float64{}, 1618 }, 1619 }, 1620 htype: BINARY_TBL, 1621 table: [][4]float64{ 1622 {10, 11, 12, 13}, 1623 {14, 15, 16, 17}, 1624 {18, 19, 10, 11}, 1625 }, 1626 }, 1627 { 1628 name: "new.fits", 1629 cols: []Column{ 1630 { 1631 Name: "cplx64s", 1632 Value: [4]complex64{}, 1633 }, 1634 }, 1635 htype: BINARY_TBL, 1636 table: [][4]complex64{ 1637 {complex(float32(10), float32(10)), complex(float32(11), float32(11)), 1638 complex(float32(12), float32(12)), complex(float32(13), float32(13))}, 1639 {complex(float32(14), float32(14)), complex(float32(15), float32(15)), 1640 complex(float32(16), float32(16)), complex(float32(17), float32(17))}, 1641 {complex(float32(18), float32(18)), complex(float32(19), float32(19)), 1642 complex(float32(10), float32(10)), complex(float32(11), float32(11))}, 1643 }, 1644 }, 1645 { 1646 name: "new.fits", 1647 cols: []Column{ 1648 { 1649 Name: "cplx128s", 1650 Value: [4]complex128{}, 1651 }, 1652 }, 1653 htype: BINARY_TBL, 1654 table: [][4]complex128{ 1655 {complex(10, 10), complex(11, 11), complex(12, 12), complex(13, 13)}, 1656 {complex(14, 14), complex(15, 15), complex(16, 16), complex(17, 17)}, 1657 {complex(18, 18), complex(19, 19), complex(10, 10), complex(11, 11)}, 1658 }, 1659 }, 1660 } { 1661 fname := fmt.Sprintf("%03d_%s", ii, table.name) 1662 for _, fct := range []func(){ 1663 // create 1664 func() { 1665 f, err := Create(fname) 1666 if err != nil { 1667 t.Fatalf("error creating new file [%v]: %v", fname, err) 1668 } 1669 defer f.Close() 1670 1671 phdu, err := NewPrimaryHDU(&f, NewDefaultHeader()) 1672 if err != nil { 1673 t.Fatalf("error creating PHDU: %v", err) 1674 } 1675 defer phdu.Close() 1676 1677 tbl, err := NewTable(&f, "test", table.cols, table.htype) 1678 if err != nil { 1679 t.Fatalf("error creating new table: %v (%v)", err, table.cols[0].Name) 1680 } 1681 defer tbl.Close() 1682 1683 rslice := reflect.ValueOf(table.table) 1684 for i := 0; i < rslice.Len(); i++ { 1685 data := rslice.Index(i).Addr() 1686 err = tbl.Write(data.Interface()) 1687 if err != nil { 1688 t.Fatalf("error writing row [%v]: %v", i, err) 1689 } 1690 } 1691 1692 nrows := tbl.NumRows() 1693 if nrows != int64(rslice.Len()) { 1694 t.Fatalf("expected num rows [%v]. got [%v] (%v)", rslice.Len(), nrows, table.cols[0].Name) 1695 } 1696 }, 1697 // read 1698 func() { 1699 f, err := Open(fname, ReadOnly) 1700 if err != nil { 1701 t.Fatalf("error opening file [%v]: %v", fname, err) 1702 } 1703 defer f.Close() 1704 1705 hdu := f.HDU(1) 1706 tbl := hdu.(*Table) 1707 if tbl.Name() != "test" { 1708 t.Fatalf("expected table name==%q. got %q", "test", tbl.Name()) 1709 } 1710 1711 rslice := reflect.ValueOf(table.table) 1712 nrows := tbl.NumRows() 1713 if nrows != int64(rslice.Len()) { 1714 t.Fatalf("expected num rows [%v]. got [%v]", rslice.Len(), nrows) 1715 } 1716 1717 rows, err := tbl.Read(0, nrows) 1718 if err != nil { 1719 t.Fatalf("table.Read: %v", err) 1720 } 1721 count := int64(0) 1722 for rows.Next() { 1723 ref := rslice.Index(int(count)).Interface() 1724 rt := reflect.TypeOf(ref) 1725 data := reflect.New(rt).Elem().Interface() 1726 err = rows.Scan(&data) 1727 if err != nil { 1728 t.Fatalf("rows.Scan: %v", err) 1729 } 1730 // check data just read in is ok 1731 if !reflect.DeepEqual(data, ref) { 1732 t.Fatalf("rows.Scan: [%[3]s|%[4]v]\nexp=%[1]v (%[1]T)\ngot=%[2]v (%[2]T)", ref, data, table.cols[0].Name, table.htype) 1733 } 1734 count++ 1735 } 1736 if count != nrows { 1737 t.Fatalf("expected [%v] rows. got [%v]", nrows, count) 1738 } 1739 }, 1740 } { 1741 fct() 1742 } 1743 } 1744 } 1745 1746 func TestTableStructsRW(t *testing.T) { 1747 1748 curdir, err := os.Getwd() 1749 if err != nil { 1750 t.Fatalf(err.Error()) 1751 } 1752 defer os.Chdir(curdir) 1753 1754 workdir, err := ioutil.TempDir("", "go-cfitsio-test-") 1755 if err != nil { 1756 t.Fatalf(err.Error()) 1757 } 1758 defer os.RemoveAll(workdir) 1759 1760 err = os.Chdir(workdir) 1761 if err != nil { 1762 t.Fatalf(err.Error()) 1763 } 1764 1765 type DataStruct struct { 1766 A int64 `fits:"int64"` 1767 XX0 int // hole 1768 B float64 `fits:"float64"` 1769 XX1 int // hole 1770 C []int64 `fits:"int64s"` 1771 XX2 int // hole 1772 D []float64 `fits:"float64s"` 1773 XX3 int // hole 1774 E [2]float64 `fits:"arrfloat64s"` 1775 } 1776 1777 for ii, table := range []struct { 1778 name string 1779 cols []Column 1780 htype HDUType 1781 table interface{} 1782 }{ 1783 { 1784 name: "new.fits", 1785 cols: []Column{ 1786 { 1787 Name: "int64", 1788 Value: int64(0), 1789 }, 1790 { 1791 Name: "float64", 1792 Value: float64(0), 1793 }, 1794 { 1795 Name: "int64s", 1796 Value: []int64{}, 1797 }, 1798 { 1799 Name: "float64s", 1800 Value: []float64{}, 1801 }, 1802 { 1803 Name: "arrfloat64s", 1804 Value: [2]float64{}, 1805 }, 1806 }, 1807 htype: BINARY_TBL, 1808 table: []DataStruct{ 1809 {A: 10, B: 10, C: []int64{10, 10}, D: []float64{10, 10}, E: [2]float64{10, 10}}, 1810 {A: 11, B: 11, C: []int64{11, 11}, D: []float64{11, 11}, E: [2]float64{11, 11}}, 1811 {A: 12, B: 12, C: []int64{12, 12}, D: []float64{12, 12}, E: [2]float64{12, 12}}, 1812 {A: 13, B: 13, C: []int64{13, 13}, D: []float64{13, 13}, E: [2]float64{13, 13}}, 1813 }, 1814 }, 1815 } { 1816 fname := fmt.Sprintf("%03d_%s", ii, table.name) 1817 for _, fct := range []func(){ 1818 // create 1819 func() { 1820 f, err := Create(fname) 1821 if err != nil { 1822 t.Fatalf("error creating new file [%v]: %v", fname, err) 1823 } 1824 defer f.Close() 1825 1826 phdu, err := NewPrimaryHDU(&f, NewDefaultHeader()) 1827 if err != nil { 1828 t.Fatalf("error creating PHDU: %v", err) 1829 } 1830 defer phdu.Close() 1831 1832 tbl, err := NewTable(&f, "test", table.cols, table.htype) 1833 if err != nil { 1834 t.Fatalf("error creating new table: %v (%v)", err, table.cols[0].Name) 1835 } 1836 defer tbl.Close() 1837 1838 rslice := reflect.ValueOf(table.table) 1839 for i := 0; i < rslice.Len(); i++ { 1840 data := rslice.Index(i).Addr() 1841 err = tbl.Write(data.Interface()) 1842 if err != nil { 1843 t.Fatalf("error writing row [%v]: %v", i, err) 1844 } 1845 } 1846 1847 nrows := tbl.NumRows() 1848 if nrows != int64(rslice.Len()) { 1849 t.Fatalf("expected num rows [%v]. got [%v] (%v)", rslice.Len(), nrows, table.cols[0].Name) 1850 } 1851 }, 1852 // read 1853 func() { 1854 f, err := Open(fname, ReadOnly) 1855 if err != nil { 1856 t.Fatalf("error opening file [%v]: %v", fname, err) 1857 } 1858 defer f.Close() 1859 1860 hdu := f.HDU(1) 1861 tbl := hdu.(*Table) 1862 if tbl.Name() != "test" { 1863 t.Fatalf("expected table name==%q. got %q", "test", tbl.Name()) 1864 } 1865 1866 rslice := reflect.ValueOf(table.table) 1867 nrows := tbl.NumRows() 1868 if nrows != int64(rslice.Len()) { 1869 t.Fatalf("expected num rows [%v]. got [%v]", rslice.Len(), nrows) 1870 } 1871 1872 rows, err := tbl.Read(0, nrows) 1873 if err != nil { 1874 t.Fatalf("table.Read: %v", err) 1875 } 1876 count := int64(0) 1877 for rows.Next() { 1878 ref := rslice.Index(int(count)).Interface() 1879 rt := reflect.TypeOf(ref) 1880 rv := reflect.New(rt).Elem() 1881 data := rv.Interface().(DataStruct) 1882 err = rows.Scan(&data) 1883 if err != nil { 1884 t.Fatalf("rows.Scan: %v", err) 1885 } 1886 // check data just read in is ok 1887 if !reflect.DeepEqual(data, ref) { 1888 t.Fatalf("rows.Scan:\nexpected=%v\ngot=%v (%T)", ref, data, data) 1889 } 1890 count++ 1891 } 1892 if count != nrows { 1893 t.Fatalf("expected [%v] rows. got [%v]", nrows, count) 1894 } 1895 }, 1896 } { 1897 fct() 1898 } 1899 } 1900 } 1901 1902 func TestTableMapsRW(t *testing.T) { 1903 1904 curdir, err := os.Getwd() 1905 if err != nil { 1906 t.Fatalf(err.Error()) 1907 } 1908 defer os.Chdir(curdir) 1909 1910 workdir, err := ioutil.TempDir("", "go-cfitsio-test-") 1911 if err != nil { 1912 t.Fatalf(err.Error()) 1913 } 1914 defer os.RemoveAll(workdir) 1915 1916 err = os.Chdir(workdir) 1917 if err != nil { 1918 t.Fatalf(err.Error()) 1919 } 1920 1921 for ii, table := range []struct { 1922 name string 1923 cols []Column 1924 htype HDUType 1925 table interface{} 1926 }{ 1927 { 1928 name: "new.fits", 1929 cols: []Column{ 1930 { 1931 Name: "A", 1932 Value: int64(0), 1933 }, 1934 { 1935 Name: "B", 1936 Value: float64(0), 1937 }, 1938 { 1939 Name: "C", 1940 Value: []int64{}, 1941 }, 1942 { 1943 Name: "D", 1944 Value: []float64{}, 1945 }, 1946 // FIXME: re-add when reflect.ArrayOf is available 1947 // { 1948 // Name: "E", 1949 // Value: [2]float64{}, 1950 // }, 1951 }, 1952 htype: BINARY_TBL, 1953 table: []map[string]interface{}{ 1954 { 1955 "A": int64(10), 1956 "B": float64(10), 1957 "C": []int64{10, 10}, 1958 "D": []float64{10, 10}, 1959 // FIXME: re-add when reflect.ArrayOf is available 1960 // "E": [2]float64{10, 10}, 1961 }, 1962 { 1963 "A": int64(11), 1964 "B": float64(11), 1965 "C": []int64{11, 11}, 1966 "D": []float64{11, 11}, 1967 // FIXME: re-add when reflect.ArrayOf is available 1968 // "E": [2]float64{11, 11}, 1969 }, 1970 { 1971 "A": int64(12), 1972 "B": float64(12), 1973 "C": []int64{12, 12}, 1974 "D": []float64{12, 12}, 1975 // FIXME: re-add when reflect.ArrayOf is available 1976 // "E": [2]float64{12, 12}, 1977 }, 1978 { 1979 "A": int64(13), 1980 "B": float64(13), 1981 "C": []int64{13, 13}, 1982 "D": []float64{13, 13}, 1983 // FIXME: re-add when reflect.ArrayOf is available 1984 // "E": [2]float64{13, 13}, 1985 }, 1986 }, 1987 }, 1988 } { 1989 fname := fmt.Sprintf("%03d_%s", ii, table.name) 1990 for _, fct := range []func(){ 1991 // create 1992 func() { 1993 f, err := Create(fname) 1994 if err != nil { 1995 t.Fatalf("error creating new file [%v]: %v", fname, err) 1996 } 1997 defer f.Close() 1998 1999 phdu, err := NewPrimaryHDU(&f, NewDefaultHeader()) 2000 if err != nil { 2001 t.Fatalf("error creating PHDU: %v", err) 2002 } 2003 defer phdu.Close() 2004 2005 tbl, err := NewTable(&f, "test", table.cols, table.htype) 2006 if err != nil { 2007 t.Fatalf("error creating new table: %v (%v)", err, table.cols[0].Name) 2008 } 2009 defer tbl.Close() 2010 2011 rslice := reflect.ValueOf(table.table) 2012 for i := 0; i < rslice.Len(); i++ { 2013 data := rslice.Index(i).Addr() 2014 err = tbl.Write(data.Interface()) 2015 if err != nil { 2016 t.Fatalf("error writing row [%v]: %v", i, err) 2017 } 2018 } 2019 2020 nrows := tbl.NumRows() 2021 if nrows != int64(rslice.Len()) { 2022 t.Fatalf("expected num rows [%v]. got [%v] (%v)", rslice.Len(), nrows, table.cols[0].Name) 2023 } 2024 }, 2025 // read 2026 func() { 2027 f, err := Open(fname, ReadOnly) 2028 if err != nil { 2029 t.Fatalf("error opening file [%v]: %v", fname, err) 2030 } 2031 defer f.Close() 2032 2033 hdu := f.HDU(1) 2034 tbl := hdu.(*Table) 2035 if tbl.Name() != "test" { 2036 t.Fatalf("expected table name==%q. got %q", "test", tbl.Name()) 2037 } 2038 2039 rslice := reflect.ValueOf(table.table) 2040 nrows := tbl.NumRows() 2041 if nrows != int64(rslice.Len()) { 2042 t.Fatalf("expected num rows [%v]. got [%v]", rslice.Len(), nrows) 2043 } 2044 2045 rows, err := tbl.Read(0, nrows) 2046 if err != nil { 2047 t.Fatalf("table.Read: %v", err) 2048 } 2049 count := int64(0) 2050 for rows.Next() { 2051 ref := rslice.Index(int(count)).Interface().(map[string]interface{}) 2052 data := map[string]interface{}{} 2053 err = rows.Scan(&data) 2054 if err != nil { 2055 t.Fatalf("rows.Scan: %v", err) 2056 } 2057 // check data just read in is ok 2058 if !reflect.DeepEqual(data, ref) { 2059 t.Fatalf("rows.Scan:\nexp=%[1]v (%[1]T)\ngot=%[2]v (%[2]T)", ref, data) 2060 } 2061 count++ 2062 } 2063 if count != nrows { 2064 t.Fatalf("expected [%v] rows. got [%v]", nrows, count) 2065 } 2066 }, 2067 } { 2068 fct() 2069 } 2070 } 2071 } 2072 2073 // EOF