From 95a7238fca14af7f0cd1909e94f75cb0972dfd99 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 9 Sep 2025 11:32:00 +0200 Subject: [PATCH 1/5] [roottest] Prepare execFileMerger for ROOT 7. --- roottest/root/io/filemerger/execFileMerger.C | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roottest/root/io/filemerger/execFileMerger.C b/roottest/root/io/filemerger/execFileMerger.C index 70eaed8a4c55f..9e44e1bbe1d5d 100644 --- a/roottest/root/io/filemerger/execFileMerger.C +++ b/roottest/root/io/filemerger/execFileMerger.C @@ -6,13 +6,14 @@ #include "THStack.h" #include "TTree.h" -void createInputs(int n = 2) +void createInputs(int n = 2) { for(UInt_t i = 0; i < (UInt_t)n; ++i ) { TFile *file = TFile::Open(TString::Format("input%d.root",i),"RECREATE"); TH1F * h = new TH1F("h1","",10,0,100); + h->SetDirectory(file); h->Fill(10.5); h->Fill(20.5); - + Int_t nbins[5]; Double_t xmin[5]; Double_t xmax[5]; From 54b9de4e66786f4943dcf861a85c47eca523e280 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Thu, 15 Jan 2026 10:48:24 +0100 Subject: [PATCH 2/5] [roottest] Prepare a hist test for ROOT 7 ownership model. --- roottest/root/hist/misc/runownership.C | 2 ++ 1 file changed, 2 insertions(+) diff --git a/roottest/root/hist/misc/runownership.C b/roottest/root/hist/misc/runownership.C index a3e457147f162..3f7bdcd693629 100644 --- a/roottest/root/hist/misc/runownership.C +++ b/roottest/root/hist/misc/runownership.C @@ -28,7 +28,9 @@ void write(const char *filename = "histo.root") { TFile * f = TFile::Open(filename,"RECREATE"); TH1F *histo = new TH1F_inst("h1","h1",10,0,10); histo->Fill(3); + histo->SetDirectory(f); histo = new TH1F_inst("h2","h2",10,0,10); histo->Fill(3); + histo->SetDirectory(f); TCanvas *c1 = new TCanvas("c1"); histo->SetBit(kCanDelete); histo->Draw(); From 9557913a6660e4736ff9085946c9f815340ff7e5 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Thu, 15 Jan 2026 10:52:33 +0100 Subject: [PATCH 3/5] [roottest] Prepare a directory test for ROOT 7 ownership model. --- .../root/io/directory/testFindObjectAny.C | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/roottest/root/io/directory/testFindObjectAny.C b/roottest/root/io/directory/testFindObjectAny.C index 915471400d970..81b0b05d64aa6 100644 --- a/roottest/root/io/directory/testFindObjectAny.C +++ b/roottest/root/io/directory/testFindObjectAny.C @@ -1,13 +1,13 @@ void doit() { TFile* base = new TFile("f.db","recreate"); - TDirectory* a = base->mkdir("a","First Level Dir"); - a->cd(); + TDirectory *a = base->mkdir("a", "First Level Dir"); TH1D* ha = new TH1D("ha","ha",10,0,1); - TDirectory* aa = a->mkdir("aa","Second Level Dira"); - aa->cd(); + ha->SetDirectory(a); + TDirectory *aa = a->mkdir("aa", "Second Level Dira"); TH1D* haa = new TH1D("haa","haa",10,0,1); - + haa->SetDirectory(aa); + a->ls(); printf(" a: created@ %p found@ %p\n", a,base->FindObjectAny("a")); @@ -92,13 +92,13 @@ void testing(TObject *orig, TObject *found) } } -int testFindObjectAny() -{ - TDirectory* db = gROOT->mkdir("db","db"); - TDirectory* a = db->mkdir("a","a"); - TDirectory* aa = a->mkdir("aa","aa"); - aa->cd(); - TH1D* haa_new = new TH1D("haa","haa",10,0,1); +int testFindObjectAny() +{ + TDirectory *db = gROOT->mkdir("db", "db"); + TDirectory *a = db->mkdir("a", "a"); + TDirectory *aa = a->mkdir("aa", "aa"); + TH1D *haa_new = new TH1D("haa", "haa", 10, 0, 1); + haa_new->SetDirectory(aa); TH1D* haa_find = (TH1D*)db->FindObjectAny("haa"); #ifdef ClingWorkAroundMissingDynamicScope TH1D* haa = haa_find; @@ -108,15 +108,15 @@ int testFindObjectAny() } else if (haa_new != haa_find) { cout << "haa not found correctly!\n"; } - + TFile* base = new TFile("fdb.root","recreate"); #ifdef ClingReinstateRedeclarationAllowed TDirectory* a = base->mkdir("a","First Level Dir"); #else a = base->mkdir("a","First Level Dir"); #endif - a->cd(); TH1D* ha = new TH1D("ha","ha",10,0,1); + ha->SetDirectory(a); #ifdef ClingReinstateRedeclarationAllowed TDirectory* aa = a->mkdir("aa","Second Level Dira"); #else @@ -128,7 +128,8 @@ int testFindObjectAny() #else TH1D* haa = new TH1D("haa","haa",10,0,1); #endif - + haa->SetDirectory(aa); + testing( a, base->FindObjectAny("a")); testing( ha, base->FindObjectAny("ha")); testing( ha, a->FindObjectAny("ha")); From 8c3a5566cce57105a777b7300e1b8cd184c6aef2 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Thu, 23 Oct 2025 15:01:25 +0200 Subject: [PATCH 4/5] [roottest] Make notebook test independent of ownership model. The test was relying on implicit ownership to transfer a histogram from python to C++, so now the histogram is appended explicitly. --- roottest/python/JupyROOT/ROOT_kernel.ipynb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/roottest/python/JupyROOT/ROOT_kernel.ipynb b/roottest/python/JupyROOT/ROOT_kernel.ipynb index ade90d23a76d5..daeba789cb70d 100644 --- a/roottest/python/JupyROOT/ROOT_kernel.ipynb +++ b/roottest/python/JupyROOT/ROOT_kernel.ipynb @@ -63,7 +63,7 @@ ], "source": [ "%%cpp -a\n", - "#include \n", + "#include \n", "\n", "template\n", "class B{};\n", @@ -172,7 +172,8 @@ "outputs": [], "source": [ "%%python\n", - "h = ROOT.TH1F(\"s\",\"s\",10,0,1)" + "h = ROOT.TH1F(\"s\",\"s\",10,0,1)\n", + "h.SetDirectory(ROOT.gDirectory)" ] }, { From 38b6fdd63fcb288c62ad3a5d35774544d3c8b61e Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Fri, 13 Feb 2026 15:45:12 +0100 Subject: [PATCH 5/5] [hist] Add a test for implicit registration of histograms to TDirectory. --- hist/hist/test/test_TH1.cxx | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/hist/hist/test/test_TH1.cxx b/hist/hist/test/test_TH1.cxx index 8449c1588a20f..b1fba0682f706 100644 --- a/hist/hist/test/test_TH1.cxx +++ b/hist/hist/test/test_TH1.cxx @@ -5,6 +5,9 @@ #include "TH3.h" #include "TH1F.h" #include "THLimitsFinder.h" +#include "TDirectory.h" +#include "TList.h" +#include "TROOT.h" #include #include @@ -167,6 +170,51 @@ TEST(TH1, Normalize) EXPECT_FLOAT_EQ(v2.GetMaximum(), 7.9999990); } +TEST(TH1, RegistrationToTDirectory_ImplicitOwnershipOn) +{ + TH1D histo1("histo1", "Test Histogram", 10, 0, 10); + auto histo2 = std::make_unique("histo2", "Test Histogram", 10, 0, 10); + TH1D *histo3 = new TH1D("histo3", "Test Histogram", 10, 0, 10); + + { + TDirectory dir("dir", "Test Directory"); + histo3->SetDirectory(&dir); + + dir.cd(); + + TH1D histo4("histo4", "Test Histogram", 10, 0, 10); + auto histo5 = std::make_unique("histo5", "Test Histogram", 10, 0, 10); + + EXPECT_EQ(dir.GetList()->GetSize(), 3); + EXPECT_EQ(dir.Get("histo1"), nullptr); + EXPECT_EQ(dir.Get("histo2"), nullptr); + EXPECT_EQ(dir.Get("histo3"), histo3); + EXPECT_EQ(dir.Get("histo4"), &histo4); + EXPECT_EQ(dir.Get("histo5"), histo5.get()); + + EXPECT_EQ(histo1.GetDirectory(), gROOT); + EXPECT_EQ(histo2->GetDirectory(), gROOT); + EXPECT_EQ(histo3->GetDirectory(), &dir); + EXPECT_EQ(histo4.GetDirectory(), &dir); + EXPECT_EQ(histo5->GetDirectory(), &dir); + + histo5.reset(); + + EXPECT_EQ(dir.GetList()->GetSize(), 2); + EXPECT_EQ(dir.Get("histo1"), nullptr); + EXPECT_EQ(dir.Get("histo2"), nullptr); + EXPECT_EQ(dir.Get("histo3"), histo3); + EXPECT_EQ(dir.Get("histo4"), &histo4); + EXPECT_EQ(dir.Get("histo5"), nullptr); + } + + EXPECT_STREQ(histo1.GetName(), "histo1"); + EXPECT_STREQ(histo2->GetName(), "histo2"); + + EXPECT_EQ(histo1.GetDirectory(), gROOT); + EXPECT_EQ(histo2->GetDirectory(), gROOT); +} + TEST(TAxis, BinComputation_FPAccuracy) { // Example from 1703c54