go-hep.org/x/hep@v0.38.1/hbook/h1d_test.go (about) 1 // Copyright ©2015 The go-hep 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 hbook 6 7 import ( 8 "bytes" 9 "encoding/gob" 10 "fmt" 11 "math" 12 "os" 13 "reflect" 14 "runtime" 15 "testing" 16 17 "github.com/google/go-cmp/cmp" 18 "gonum.org/v1/gonum/floats/scalar" 19 "gonum.org/v1/plot/plotter" 20 ) 21 22 func panics(fn func()) (panicked bool, message string) { 23 defer func() { 24 r := recover() 25 panicked = r != nil 26 message = fmt.Sprint(r) 27 }() 28 fn() 29 return 30 } 31 32 func TestH1D(t *testing.T) { 33 h1 := NewH1D(100, 0., 100.) 34 if h1 == nil { 35 t.Errorf("nil pointer to H1D") 36 } 37 38 h1.Annotation()["name"] = "h1" 39 40 n := h1.Name() 41 if n != "h1" { 42 t.Errorf("expected H1D.Name() == %q (got %q)\n", 43 n, "h1") 44 } 45 xmin := h1.XMin() 46 if xmin != 0. { 47 t.Errorf("expected H1D.Min() == %v (got %v)\n", 48 0., xmin, 49 ) 50 } 51 xmax := h1.XMax() 52 if xmax != 100. { 53 t.Errorf("expected H1D.Max() == %v (got %v)\n", 54 100., xmax, 55 ) 56 } 57 /* 58 for idx := 0; idx < nbins; idx++ { 59 size := h1.Binning().BinWidth(idx) 60 if size != 1. { 61 t.Errorf("expected H1D.Binning.BinWidth(%v) == %v (got %v)\n", 62 idx, 1., size, 63 ) 64 } 65 } 66 */ 67 var _ plotter.XYer = h1 68 var _ plotter.Valuer = h1 69 } 70 71 func TestH1DEdges(t *testing.T) { 72 h := NewH1DFromEdges([]float64{ 73 -4.0, -3.6, -3.2, -2.8, -2.4, -2.0, -1.6, -1.2, -0.8, -0.4, 74 +0.0, +0.4, +0.8, +1.2, +1.6, +2.0, +2.4, +2.8, +3.2, +3.6, 75 +4.0, 76 }) 77 if got, want := h.XMin(), -4.0; got != want { 78 t.Errorf("got xmin=%v. want=%v", got, want) 79 } 80 if got, want := h.XMax(), +4.0; got != want { 81 t.Errorf("got xmax=%v. want=%v", got, want) 82 } 83 84 bins := Bin1Ds(h.Binning.Bins) 85 for _, test := range []struct { 86 v float64 87 want int 88 }{ 89 {v: -4.1, want: UnderflowBin1D}, 90 {v: -4.0, want: 0}, 91 {v: -3.6, want: 1}, 92 {v: -3.2, want: 2}, 93 {v: -2.8, want: 3}, 94 {v: -2.4, want: 4}, 95 {v: -2.0, want: 5}, 96 {v: -1.6, want: 6}, 97 {v: -1.2, want: 7}, 98 {v: -0.8, want: 8}, 99 {v: -0.4, want: 9}, 100 {v: +0.0, want: 10}, 101 {v: +0.4, want: 11}, 102 {v: +0.8, want: 12}, 103 {v: +1.2, want: 13}, 104 {v: +1.6, want: 14}, 105 {v: +2.0, want: 15}, 106 {v: +2.4, want: 16}, 107 {v: +2.8, want: 17}, 108 {v: +3.2, want: 18}, 109 {v: +3.6, want: 19}, 110 {v: +4.0, want: OverflowBin1D}, 111 } { 112 idx := bins.IndexOf(test.v) 113 if idx != test.want { 114 t.Errorf("invalid index for %v. got=%d. want=%d\n", test.v, idx, test.want) 115 } 116 } 117 } 118 119 func TestH1DBins(t *testing.T) { 120 h := NewH1DFromBins([]Range{ 121 {Min: -4.0, Max: -3.6}, {Min: -3.6, Max: -3.2}, {Min: -3.2, Max: -2.8}, {Min: -2.8, Max: -2.4}, {Min: -2.4, Max: -2.0}, 122 {Min: -2.0, Max: -1.6}, {Min: -1.6, Max: -1.2}, {Min: -1.2, Max: -0.8}, {Min: -0.8, Max: -0.4}, {Min: -0.4, Max: +0.0}, 123 {Min: +0.0, Max: +0.4}, {Min: +0.4, Max: +0.8}, {Min: +0.8, Max: +1.2}, {Min: +1.2, Max: +1.6}, {Min: +1.6, Max: +2.0}, 124 {Min: +2.0, Max: +2.4}, {Min: +2.4, Max: +2.8}, {Min: +2.8, Max: +3.2}, {Min: +3.2, Max: +3.6}, {Min: +3.6, Max: +4.0}, 125 }...) 126 if got, want := h.XMin(), -4.0; got != want { 127 t.Errorf("got xmin=%v. want=%v", got, want) 128 } 129 if got, want := h.XMax(), +4.0; got != want { 130 t.Errorf("got xmax=%v. want=%v", got, want) 131 } 132 bins := Bin1Ds(h.Binning.Bins) 133 for _, test := range []struct { 134 v float64 135 want int 136 }{ 137 {v: -4.1, want: UnderflowBin1D}, 138 {v: -4.0, want: 0}, 139 {v: -3.6, want: 1}, 140 {v: -3.2, want: 2}, 141 {v: -2.8, want: 3}, 142 {v: -2.4, want: 4}, 143 {v: -2.0, want: 5}, 144 {v: -1.6, want: 6}, 145 {v: -1.2, want: 7}, 146 {v: -0.8, want: 8}, 147 {v: -0.4, want: 9}, 148 {v: +0.0, want: 10}, 149 {v: +0.4, want: 11}, 150 {v: +0.8, want: 12}, 151 {v: +1.2, want: 13}, 152 {v: +1.6, want: 14}, 153 {v: +2.0, want: 15}, 154 {v: +2.4, want: 16}, 155 {v: +2.8, want: 17}, 156 {v: +3.2, want: 18}, 157 {v: +3.6, want: 19}, 158 {v: +4.0, want: OverflowBin1D}, 159 } { 160 idx := bins.IndexOf(test.v) 161 if idx != test.want { 162 t.Errorf("invalid index for %v. got=%d. want=%d\n", test.v, idx, test.want) 163 } 164 } 165 166 } 167 168 func TestH1DBinsWithGapsv1(t *testing.T) { 169 h1 := NewH1DFromBins([]Range{ 170 {Min: -10, Max: -5}, {Min: -5, Max: 0}, {Min: 0, Max: 4} /*GAP*/, {Min: 5, Max: 10}, 171 }...) 172 if got, want := h1.XMin(), -10.0; got != want { 173 t.Errorf("got xmin=%v. want=%v", got, want) 174 } 175 if got, want := h1.XMax(), 10.0; got != want { 176 t.Errorf("got xmax=%v. want=%v", got, want) 177 } 178 179 bins := Bin1Ds(h1.Binning.Bins) 180 for _, test := range []struct { 181 v float64 182 want int 183 }{ 184 {v: -20, want: UnderflowBin1D}, 185 {v: -10, want: 0}, 186 {v: -9, want: 0}, 187 {v: -5, want: 1}, 188 {v: 0, want: 2}, 189 {v: 4.5, want: len(bins)}, 190 {v: 5, want: 3}, 191 {v: 6, want: 3}, 192 {v: 10, want: OverflowBin1D}, 193 } { 194 idx := bins.IndexOf(test.v) 195 if idx != test.want { 196 t.Errorf("invalid index for %v. got=%d. want=%d\n", test.v, idx, test.want) 197 } 198 } 199 200 h := NewH1DFromBins([]Range{ 201 {Min: 0, Max: 1}, {Min: 1, Max: 2}, {Min: 3, Max: 4}, 202 }...) 203 h.Fill(0, 1) 204 h.Fill(1, 1) 205 h.Fill(2, 1) // gap 206 h.Fill(3, 1) 207 h.Annotation()["title"] = "my-title" 208 209 raw, err := h.marshalYODAv1() 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 want, err := os.ReadFile("testdata/h1d_gaps_v1_golden.yoda") 215 if err != nil { 216 t.Fatal(err) 217 } 218 219 if !reflect.DeepEqual(raw, want) { 220 t.Fatalf("h1d file differ:\n%s\n", 221 cmp.Diff( 222 string(want), 223 string(raw), 224 ), 225 ) 226 } 227 228 var href H1D 229 err = href.UnmarshalYODA(want) 230 if err != nil { 231 t.Fatalf("error: %+v", err) 232 } 233 234 raw, err = href.marshalYODAv1() 235 if err != nil { 236 t.Fatal(err) 237 } 238 239 if !reflect.DeepEqual(raw, want) { 240 t.Fatalf("h1d file differ:\n%s\n", 241 cmp.Diff( 242 string(want), 243 string(raw), 244 ), 245 ) 246 } 247 } 248 249 func TestH1DBinsWithGapsv2(t *testing.T) { 250 h1 := NewH1DFromBins([]Range{ 251 {Min: -10, Max: -5}, {Min: -5, Max: 0}, {Min: 0, Max: 4} /*GAP*/, {Min: 5, Max: 10}, 252 }...) 253 if got, want := h1.XMin(), -10.0; got != want { 254 t.Errorf("got xmin=%v. want=%v", got, want) 255 } 256 if got, want := h1.XMax(), 10.0; got != want { 257 t.Errorf("got xmax=%v. want=%v", got, want) 258 } 259 260 bins := Bin1Ds(h1.Binning.Bins) 261 for _, test := range []struct { 262 v float64 263 want int 264 }{ 265 {v: -20, want: UnderflowBin1D}, 266 {v: -10, want: 0}, 267 {v: -9, want: 0}, 268 {v: -5, want: 1}, 269 {v: 0, want: 2}, 270 {v: 4.5, want: len(bins)}, 271 {v: 5, want: 3}, 272 {v: 6, want: 3}, 273 {v: 10, want: OverflowBin1D}, 274 } { 275 idx := bins.IndexOf(test.v) 276 if idx != test.want { 277 t.Errorf("invalid index for %v. got=%d. want=%d\n", test.v, idx, test.want) 278 } 279 } 280 281 h := NewH1DFromBins([]Range{ 282 {Min: 0, Max: 1}, {Min: 1, Max: 2}, {Min: 3, Max: 4}, 283 }...) 284 h.Fill(0, 1) 285 h.Fill(1, 1) 286 h.Fill(2, 1) // gap 287 h.Fill(3, 1) 288 h.Annotation()["title"] = "my-title" 289 290 raw, err := h.MarshalYODA() 291 if err != nil { 292 t.Fatal(err) 293 } 294 295 want, err := os.ReadFile("testdata/h1d_gaps_v2_golden.yoda") 296 if err != nil { 297 t.Fatal(err) 298 } 299 300 if !reflect.DeepEqual(raw, want) { 301 t.Fatalf("h1d file differ:\n%s\n", 302 cmp.Diff( 303 string(want), 304 string(raw), 305 ), 306 ) 307 } 308 309 var href H1D 310 err = href.UnmarshalYODA(want) 311 if err != nil { 312 t.Fatalf("error: %+v", err) 313 } 314 315 raw, err = href.MarshalYODA() 316 if err != nil { 317 t.Fatal(err) 318 } 319 320 if !reflect.DeepEqual(raw, want) { 321 t.Fatalf("h1d file differ:\n%s\n", 322 cmp.Diff( 323 string(want), 324 string(raw), 325 ), 326 ) 327 } 328 } 329 330 func TestH1DEdgesWithPanics(t *testing.T) { 331 for _, test := range [][]float64{ 332 {0}, 333 {0, 1, 0.5, 2}, 334 {0, 1, 1}, 335 {0, 1, 0, 1}, 336 {0, 1, 2, 2}, 337 {0, 1, 2, 2, 2}, 338 } { 339 panicked, _ := panics(func() { 340 _ = NewH1DFromEdges(test) 341 }) 342 if !panicked { 343 t.Fatalf("edges %v should have panicked", test) 344 } 345 } 346 } 347 348 func TestH1DBinsWithPanics(t *testing.T) { 349 for _, test := range [][]Range{ 350 {{Min: 0, Max: 1}, {Min: 0.5, Max: 1.5}}, 351 {{Min: 0, Max: 1}, {Min: -1, Max: 2}}, 352 {{Min: 0, Max: 1.5}, {Min: -1, Max: 1}}, 353 {{Min: 0, Max: 1}, {Min: 0.5, Max: 0.6}}, 354 } { 355 panicked, _ := panics(func() { 356 _ = NewH1DFromBins(test...) 357 }) 358 if !panicked { 359 t.Fatalf("bins %v should have panicked", test) 360 } 361 } 362 } 363 364 func TestH1DIntegral(t *testing.T) { 365 h1 := NewH1D(6, 0, 6) 366 h1.Fill(-0.5, 1.3) 367 h1.Fill(0, 1) 368 h1.Fill(0.5, 1.6) 369 h1.Fill(1.2, 0.7) 370 h1.Fill(2.1, 0.3) 371 h1.Fill(4.2, 1.2) 372 h1.Fill(5.9, 0.5) 373 h1.Fill(6, 2.1) 374 375 integral := h1.Integral() 376 if integral != 8.7 { 377 t.Errorf("expected H1D.Integral() == 8.7 (got %v)\n", integral) 378 } 379 if got, want := h1.Integral(h1.XMin(), h1.XMax()), 5.3; got != want { 380 t.Errorf("H1D.Integral(xmin,xmax) = %v. want=%v\n", got, want) 381 } 382 383 integralall := h1.Integral(math.Inf(-1), math.Inf(+1)) 384 if integralall != 8.7 { 385 t.Errorf("expected H1D.Integral(math.Inf(-1), math.Inf(+1)) == 8.7 (got %v)\n", integralall) 386 } 387 integralu := h1.Integral(math.Inf(-1), h1.XMax()) 388 if integralu != 6.6 { 389 t.Errorf("expected H1D.Integral(math.Inf(-1), h1.Binning().UpperEdge()) == 6.6 (got %v)\n", integralu) 390 } 391 integralo := h1.Integral(h1.XMin(), math.Inf(+1)) 392 if integralo != 7.4 { 393 t.Errorf("expected H1D.Integral(h1.Binning().LowerEdge(), math.Inf(+1)) == 7.4 (got %v)\n", integralo) 394 } 395 integralrange := h1.Integral(0.5, 5.5) 396 if integralrange != 2.7 { 397 t.Errorf("expected H1D.Integral(0.5, 5.5) == 2.7 (got %v)\n", integralrange) 398 } 399 400 mean1, rms1 := h1.XMean(), h1.XRMS() 401 402 h1.Scale(1 / integral) 403 integral = h1.Integral() 404 if integral != 1 { 405 t.Errorf("expected H1D.Integral() == 1 (got %v)\n", integral) 406 } 407 408 mean2, rms2 := h1.XMean(), h1.XRMS() 409 410 if math.Abs(mean1-mean2)/mean1 > 1e-12 { 411 t.Errorf("mean has changed while rescaling (mean1, mean2) = (%v, %v)", mean1, mean2) 412 } 413 if math.Abs(rms1-rms2)/rms1 > 1e-12 { 414 t.Errorf("rms has changed while rescaling (rms1, rms2) = (%v, %v)", rms1, rms2) 415 } 416 417 h2 := NewH1D(2, 0, 1) 418 h2.Fill(0.0, 1) 419 h2.Fill(0.5, 1) 420 for _, ibin := range []int{0, 1} { 421 if got, want := h2.Value(ibin), 1.0; got != want { 422 t.Errorf("got H1D.Value(%d) = %v. want %v\n", ibin, got, want) 423 } 424 if got, want := h2.Error(ibin), 1.0; got != want { 425 t.Errorf("got H1D.Error(%d) = %v. want %v\n", ibin, got, want) 426 } 427 } 428 429 if got, want := h2.Integral(), 2.0; got != want { 430 t.Errorf("got H1D.Integral() == %v. want %v\n", got, want) 431 } 432 } 433 434 func TestH1DNegativeWeights(t *testing.T) { 435 h1 := NewH1D(5, 0, 100) 436 h1.Fill(10, -200) 437 h1.Fill(20, 1) 438 h1.Fill(30, 0.2) 439 h1.Fill(10, +200) 440 441 h2 := NewH1D(5, 0, 100) 442 h2.Fill(20, 1) 443 h2.Fill(30, 0.2) 444 445 const tol = 1e-12 446 if x1, x2 := h1.XMean(), h2.XMean(); !scalar.EqualWithinAbs(x1, x2, tol) { 447 t.Errorf("mean differ:\nh1=%v\nh2=%v\n", x1, x2) 448 } 449 if x1, x2 := h1.XRMS(), h2.XRMS(); !scalar.EqualWithinAbs(x1, x2, tol) { 450 t.Errorf("rms differ:\nh1=%v\nh2=%v\n", x1, x2) 451 } 452 /* FIXME 453 if x1, x2 := h1.StdDevX(), h2.StdDevX(); !scalar.EqualWithinAbs(x1, x2, tol) { 454 t.Errorf("std-dev differ:\nh1=%v\nh2=%v\n", x1, x2) 455 } 456 */ 457 } 458 459 func TestH1DSerialization(t *testing.T) { 460 const nentries = 50 461 href := NewH1D(100, 0., 100.) 462 for range nentries { 463 href.Fill(rnd()*100., 1.) 464 } 465 href.Annotation()["title"] = "histo title" 466 href.Annotation()["name"] = "histo name" 467 468 // test gob.GobDecode/gob.GobEncode interface 469 func() { 470 buf := new(bytes.Buffer) 471 enc := gob.NewEncoder(buf) 472 err := enc.Encode(href) 473 if err != nil { 474 t.Fatalf("could not serialize histogram: %v", err) 475 } 476 477 var hnew H1D 478 dec := gob.NewDecoder(buf) 479 err = dec.Decode(&hnew) 480 if err != nil { 481 t.Fatalf("could not deserialize histogram: %v", err) 482 } 483 484 if !reflect.DeepEqual(href, &hnew) { 485 t.Fatalf("ref=%v\nnew=%v\n", href, &hnew) 486 } 487 }() 488 489 // test rio.Marshaler/Unmarshaler 490 func() { 491 buf := new(bytes.Buffer) 492 err := href.RioMarshal(buf) 493 if err != nil { 494 t.Fatalf("could not serialize histogram: %v", err) 495 } 496 497 var hnew H1D 498 err = hnew.RioUnmarshal(buf) 499 if err != nil { 500 t.Fatalf("could not deserialize histogram: %v", err) 501 } 502 503 if !reflect.DeepEqual(href, &hnew) { 504 t.Fatalf("ref=%v\nnew=%v\n", href, &hnew) 505 } 506 }() 507 508 } 509 510 func TestH1DWriteYODA(t *testing.T) { 511 h := NewH1D(10, -4, 4) 512 h.Fill(1, 1) 513 h.Fill(2, 1) 514 h.Fill(-3, 1) 515 h.Fill(-4, 1) 516 h.Fill(0, 1) 517 h.Fill(0, 1) 518 h.Fill(10, 1) 519 h.Fill(-10, 1) 520 521 chk, err := h.MarshalYODA() 522 if err != nil { 523 t.Fatal(err) 524 } 525 526 ref, err := os.ReadFile("testdata/h1d_v2_golden.yoda") 527 if err != nil { 528 t.Fatal(err) 529 } 530 531 if !reflect.DeepEqual(chk, ref) { 532 fatalf := t.Fatalf 533 if runtime.GOOS == "darwin" { 534 // ignore errors for darwin and mac-silicon 535 fatalf = t.Logf 536 } 537 fatalf("h1d file differ:\n%s\n", 538 cmp.Diff( 539 string(ref), 540 string(chk), 541 ), 542 ) 543 } 544 } 545 546 func TestH1DReadYODAv1(t *testing.T) { 547 ref, err := os.ReadFile("testdata/h1d_v1_golden.yoda") 548 if err != nil { 549 t.Fatal(err) 550 } 551 552 var h H1D 553 err = h.UnmarshalYODA(ref) 554 if err != nil { 555 t.Fatal(err) 556 } 557 558 chk, err := h.marshalYODAv1() 559 if err != nil { 560 t.Fatal(err) 561 } 562 563 if !reflect.DeepEqual(chk, ref) { 564 t.Fatalf("h1d file differ:\n%s\n", 565 cmp.Diff( 566 string(ref), 567 string(chk), 568 ), 569 ) 570 } 571 } 572 573 func TestH1DReadYODAv2(t *testing.T) { 574 ref, err := os.ReadFile("testdata/h1d_v2_golden.yoda") 575 if err != nil { 576 t.Fatal(err) 577 } 578 579 var h H1D 580 err = h.UnmarshalYODA(ref) 581 if err != nil { 582 t.Fatal(err) 583 } 584 585 chk, err := h.MarshalYODA() 586 if err != nil { 587 t.Fatal(err) 588 } 589 590 if !reflect.DeepEqual(chk, ref) { 591 t.Fatalf("h1d file differ:\n%s\n", 592 cmp.Diff( 593 string(ref), 594 string(chk), 595 ), 596 ) 597 } 598 } 599 600 func TestH1DBin(t *testing.T) { 601 h := NewH1DFromEdges([]float64{ 602 -4.0, -3.6, -3.2, -2.8, -2.4, -2.0, -1.6, -1.2, -0.8, -0.4, 603 +0.0, +0.4, +0.8, +1.2, +1.6, +2.0, +2.4, +2.8, +3.2, +3.6, 604 +4.0, 605 }) 606 if got, want := h.XMin(), -4.0; got != want { 607 t.Errorf("got xmin=%v. want=%v", got, want) 608 } 609 if got, want := h.XMax(), +4.0; got != want { 610 t.Errorf("got xmax=%v. want=%v", got, want) 611 } 612 613 h.Fill(-4.0, 1) 614 h.Fill(-3.6, 1) 615 h.Fill(-3.6, 1) 616 h.Fill(-3.1, 1) 617 h.Fill(-3.1, 1) 618 h.Fill(-3.1, 1) 619 620 for _, tc := range []struct { 621 x float64 622 bin int 623 }{ 624 {-4.0, 1}, 625 {-3.9, 1}, 626 {-3.6, 2}, 627 {-3.1, 3}, 628 {-10, -1}, 629 {+4, -1}, 630 } { 631 t.Run(fmt.Sprintf("x=%v", tc.x), func(t *testing.T) { 632 bin := h.Bin(tc.x) 633 if tc.bin < 0 && bin == nil { 634 // ok 635 return 636 } 637 if bin == nil { 638 t.Fatalf("unexpected nil bin") 639 } 640 641 if bin.EffEntries() != float64(tc.bin) { 642 t.Fatalf("x=%v got=%v %v, want=%d", tc.x, bin.EffEntries(), bin.Entries(), tc.bin) 643 } 644 }) 645 } 646 } 647 648 func TestH1DFillN(t *testing.T) { 649 h1 := NewH1D(10, 0, 10) 650 h2 := NewH1D(10, 0, 10) 651 652 xs := []float64{1, 2, 3, 4} 653 ws := []float64{1, 2, 1, 1} 654 655 for i := range xs { 656 h1.Fill(xs[i], ws[i]) 657 } 658 h2.FillN(xs, ws) 659 660 if s1, s2 := h1.SumW(), h2.SumW(); s1 != s2 { 661 t.Fatalf("invalid sumw: h1=%v, h2=%v", s1, s2) 662 } 663 664 for i := range xs { 665 h1.Fill(xs[i], 1) 666 } 667 h2.FillN(xs, nil) 668 669 if s1, s2 := h1.SumW(), h2.SumW(); s1 != s2 { 670 t.Fatalf("invalid sumw: h1=%v, h2=%v", s1, s2) 671 } 672 673 func() { 674 defer func() { 675 err := recover() 676 if err == nil { 677 t.Fatalf("expected a panic!") 678 } 679 const want = "hbook: lengths mismatch" 680 if got, want := err.(error).Error(), want; got != want { 681 t.Fatalf("invalid panic message:\ngot= %q\nwant=%q", got, want) 682 } 683 }() 684 685 h2.FillN(xs, []float64{1}) 686 }() 687 } 688 689 func TestH1DClone(t *testing.T) { 690 h1 := NewH1D(10, 0, 10) 691 h1.FillN( 692 []float64{-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11}, 693 []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1}, 694 ) 695 h1.Ann["hello"] = "world" 696 697 msg1, err := h1.MarshalYODA() 698 if err != nil { 699 t.Fatalf("could not marshal h1: %+v", err) 700 } 701 702 h2 := h1.Clone() 703 msg2, err := h2.MarshalYODA() 704 if err != nil { 705 t.Fatalf("could not marshal h2: %+v", err) 706 } 707 708 if !bytes.Equal(msg1, msg2) { 709 t.Fatalf("h1d file differ:\n%s\n", 710 cmp.Diff( 711 string(msg1), 712 string(msg2), 713 ), 714 ) 715 } 716 717 h1.Ann["world"] = "bye" 718 h1.FillN( 719 []float64{-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11}, 720 []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1}, 721 ) 722 723 msg3, err := h1.MarshalYODA() 724 if err != nil { 725 t.Fatalf("could not marshal h1: %+v", err) 726 } 727 728 msg4, err := h2.MarshalYODA() 729 if err != nil { 730 t.Fatalf("could not marshal h2: %+v", err) 731 } 732 733 if bytes.Equal(msg1, msg3) { 734 t.Fatalf("msg1/msg3 should differ") 735 } 736 737 if !bytes.Equal(msg4, msg2) { 738 t.Fatalf("h1d file differ:\n%s\n", 739 cmp.Diff( 740 string(msg4), 741 string(msg2), 742 ), 743 ) 744 } 745 }