go-hep.org/x/hep@v0.38.1/groot/rjson/rjson_test.go (about)

     1  // Copyright ©2023 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 rjson_test
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"go-hep.org/x/hep/groot/internal/rtests"
    14  	"go-hep.org/x/hep/groot/rhist"
    15  	"go-hep.org/x/hep/groot/rjson"
    16  	"go-hep.org/x/hep/groot/root"
    17  	"go-hep.org/x/hep/hbook"
    18  	"go-hep.org/x/hep/internal/diff"
    19  )
    20  
    21  func TestMarshal(t *testing.T) {
    22  	for _, tc := range []struct {
    23  		name string
    24  		gen  func() root.Object
    25  	}{
    26  		{
    27  			name: "h1d",
    28  			gen: func() root.Object {
    29  				h := hbook.NewH1D(100, 0, 100)
    30  				h.Fill(1, 1)
    31  				h.Fill(-1, 1)
    32  				h.Fill(200, 1)
    33  				h.Ann["name"] = "h1"
    34  				h.Ann["title"] = "my title"
    35  
    36  				return rhist.NewH1DFrom(h)
    37  			},
    38  		},
    39  		{
    40  			name: "h2d",
    41  			gen: func() root.Object {
    42  				h := hbook.NewH2D(5, 0, 5, 2, 0, 2)
    43  				h.Fill(1, 1, 1)
    44  				h.Fill(-1, -1, 1)
    45  				h.Fill(200, 300, 1)
    46  				h.Ann["name"] = "h2"
    47  				h.Ann["title"] = "my title"
    48  
    49  				return rhist.NewH2DFrom(h)
    50  			},
    51  		},
    52  		{
    53  			name: "graph",
    54  			gen: func() root.Object {
    55  				s := hbook.NewS2DFrom([]float64{1, 2, 3}, []float64{2, 4, 6})
    56  				s.Annotation()["name"] = "s2"
    57  				s.Annotation()["title"] = "my title"
    58  				return rhist.NewGraphFrom(s)
    59  			},
    60  		},
    61  		{
    62  			name: "tge",
    63  			gen: func() root.Object {
    64  				s := hbook.NewS2D([]hbook.Point2D{
    65  					{X: 1, Y: 2, ErrX: hbook.Range{Min: 10, Max: 20}, ErrY: hbook.Range{Min: 11, Max: 22}},
    66  					{X: 2, Y: 4, ErrX: hbook.Range{Min: 20, Max: 30}, ErrY: hbook.Range{Min: 12, Max: 23}},
    67  					{X: 3, Y: 6, ErrX: hbook.Range{Min: 30, Max: 40}, ErrY: hbook.Range{Min: 13, Max: 24}},
    68  				}...)
    69  				s.Annotation()["name"] = "s2"
    70  				s.Annotation()["title"] = "my title"
    71  				return rhist.NewGraphErrorsFrom(s)
    72  			},
    73  		},
    74  		{
    75  			name: "tgae",
    76  			gen: func() root.Object {
    77  				s := hbook.NewS2D([]hbook.Point2D{
    78  					{X: 1, Y: 2, ErrX: hbook.Range{Min: 10, Max: 20}, ErrY: hbook.Range{Min: 11, Max: 22}},
    79  					{X: 2, Y: 4, ErrX: hbook.Range{Min: 20, Max: 30}, ErrY: hbook.Range{Min: 12, Max: 23}},
    80  					{X: 3, Y: 6, ErrX: hbook.Range{Min: 30, Max: 40}, ErrY: hbook.Range{Min: 13, Max: 24}},
    81  				}...)
    82  				s.Annotation()["name"] = "s2"
    83  				s.Annotation()["title"] = "my title"
    84  				return rhist.NewGraphAsymmErrorsFrom(s)
    85  			},
    86  		},
    87  		{
    88  			name: "tgme",
    89  			gen: func() root.Object {
    90  				s := hbook.NewS2D([]hbook.Point2D{
    91  					{X: 1, Y: 2, ErrX: hbook.Range{Min: 10, Max: 20}, ErrY: hbook.Range{Min: 11, Max: 22}},
    92  					{X: 2, Y: 4, ErrX: hbook.Range{Min: 20, Max: 30}, ErrY: hbook.Range{Min: 12, Max: 23}},
    93  					{X: 3, Y: 6, ErrX: hbook.Range{Min: 30, Max: 40}, ErrY: hbook.Range{Min: 13, Max: 24}},
    94  				}...)
    95  				s.Annotation()["name"] = "s2"
    96  				s.Annotation()["title"] = "my title"
    97  				return rhist.NewGraphMultiErrorsFrom(s)
    98  			},
    99  		},
   100  	} {
   101  		t.Run(tc.name, func(t *testing.T) {
   102  			var (
   103  				fname = filepath.Join("testdata", tc.name+".json")
   104  				want  = filepath.Join("testdata", tc.name+"_golden.json")
   105  			)
   106  
   107  			obj := tc.gen()
   108  			got, err := rjson.Marshal(obj)
   109  			if err != nil {
   110  				t.Fatalf("could not generate JSON: %+v", err)
   111  			}
   112  
   113  			err = os.WriteFile(fname, got, 0644)
   114  			if err != nil {
   115  				t.Fatalf("could not write JSON: %+v", err)
   116  			}
   117  
   118  			err = diff.Files(fname, want)
   119  			if err != nil {
   120  				t.Fatalf("invalid JSON:\n%v", err)
   121  			}
   122  
   123  			if !rtests.HasROOT {
   124  				return
   125  			}
   126  
   127  			// make sure ROOT can read back that file as well.
   128  			code := fmt.Sprintf(`#include <iostream>
   129  #include <fstream>
   130  #include <sstream>
   131  #include <string>
   132  
   133  #include "TBufferJSON.h"
   134  #include "%[1]s.h"
   135  
   136  void unmarshal(const char *fname) {
   137  	std:ifstream input(fname);
   138  	std::stringstream s;
   139  	while (input >> s.rdbuf()) {}
   140  
   141  	auto str = s.str();
   142  
   143  	%[1]s *o = nullptr;
   144  	TBufferJSON::FromJSON(o, str.c_str());
   145  
   146  	if (o->ClassName() != std::string("%[1]s")) {
   147  		std::cerr << "invalid class name: got=\"" << o->ClassName() << "\", want=\"%[1]s\"\n";
   148  		exit(1);
   149  	}
   150  	o->Print();
   151  }
   152  `, obj.Class(),
   153  			)
   154  			out, err := rtests.RunCxxROOT("unmarshal", []byte(code), fname)
   155  			if err != nil {
   156  				t.Fatalf("could not run C++ ROOT: %+v\noutput:\n%s\ncode:\n%s", err, out, code)
   157  			}
   158  
   159  			defer os.Remove(fname)
   160  		})
   161  	}
   162  }