@@ -394,3 +394,162 @@ TEST(TFileMerger, MergeSelectiveTutorial)
394394 EXPECT_NE (file.Get <TNtuple>(" ntuple" ), nullptr );
395395 }
396396}
397+
398+ // https://github.com/root-project/root/issues/14558
399+ TEST (TFileMerger, ImportBranches)
400+ {
401+ {
402+ // Case 1 - Static: ZeroBranches + 1 entry (1 branch) + 1 entry (2 branch)
403+ TTree atree (" atree" , " atitle" );
404+ int value;
405+ atree.Branch (" a" , &value);
406+ value = 11 ;
407+ atree.Fill ();
408+ TTree abtree (" abtree" , " abtitle" );
409+ abtree.Branch (" a" , &value);
410+ abtree.Branch (" b" , &value);
411+ value = 42 ;
412+ abtree.Fill ();
413+
414+ TTree dummy (" ztree" , " zeroBranches" );
415+ TList treelist;
416+ treelist.Add (&dummy);
417+ treelist.Add (&atree);
418+ treelist.Add (&abtree);
419+ std::unique_ptr<TFile> file1 (TFile::Open (" b4716.root" , " RECREATE" ));
420+ auto rtree = TTree::MergeTrees (&treelist, " ImportBranches" );
421+ file1->Write ();
422+ ASSERT_TRUE (rtree->FindBranch (" a" ));
423+ EXPECT_EQ (rtree->FindBranch (" a" )->GetEntries (), 2 );
424+ ASSERT_TRUE (rtree->FindBranch (" b" ));
425+ EXPECT_EQ (rtree->FindBranch (" b" )->GetEntries (), 2 );
426+ ASSERT_TRUE (atree.FindBranch (" a" ));
427+ ASSERT_FALSE (atree.FindBranch (" b" ));
428+ ASSERT_TRUE (abtree.FindBranch (" a" ));
429+ ASSERT_TRUE (abtree.FindBranch (" b" ));
430+ EXPECT_EQ (atree.FindBranch (" a" )->GetEntries (), 1 );
431+ EXPECT_EQ (abtree.FindBranch (" a" )->GetEntries (), 1 );
432+ EXPECT_EQ (abtree.FindBranch (" b" )->GetEntries (), 1 );
433+ EXPECT_EQ (dummy.FindBranch (" a" ), nullptr );
434+ EXPECT_EQ (dummy.FindBranch (" b" ), nullptr );
435+ }
436+ {
437+ // Case 2 - this (ZeroBranches) + 1 entry (1 branch) + 1 entry (2 branch)
438+ TTree atree (" atree" , " atitle" );
439+ int value;
440+ atree.Branch (" a" , &value);
441+ value = 11 ;
442+ atree.Fill ();
443+ TTree abtree (" abtree" , " abtitle" );
444+ abtree.Branch (" a" , &value);
445+ abtree.Branch (" b" , &value);
446+ value = 42 ;
447+ abtree.Fill ();
448+
449+ TTree dummy (" ztree" , " zeroBranches" );
450+ TList treelist;
451+ treelist.Add (&atree);
452+ treelist.Add (&abtree);
453+ std::unique_ptr<TFile> file2 (TFile::Open (" c4716.root" , " RECREATE" ));
454+ TFileMergeInfo info2 (file2.get ());
455+ info2.fOptions += " ImportBranches" ;
456+ dummy.Merge (&treelist, &info2);
457+ file2->Write ();
458+ ASSERT_TRUE (dummy.FindBranch (" a" ));
459+ EXPECT_EQ (dummy.FindBranch (" a" )->GetEntries (), 2 );
460+ ASSERT_TRUE (dummy.FindBranch (" b" ));
461+ EXPECT_EQ (dummy.FindBranch (" b" )->GetEntries (), 2 );
462+ EXPECT_EQ (TString (atree.GetName ()),
463+ " ztree" ); // As a side effect of trees with zero branches being ignored but it's name kept since it's first
464+ // in list, the first tree with branches (name) gets ztree's name.
465+ ASSERT_TRUE (atree.FindBranch (" a" ));
466+ EXPECT_EQ (atree.FindBranch (" a" )->GetEntries (), 2 ); // As a side effect, the first with branches (atree) has been
467+ // modified and has now 2 entries instead of 1, and ztree's name
468+ ASSERT_TRUE (atree.FindBranch (" b" ));
469+ EXPECT_EQ (atree.FindBranch (" b" )->GetEntries (), 2 ); // As a side effect, the first with branches (atree) has been
470+ // modified and has now 2 entries instead of 1, and ztree's name
471+ ASSERT_TRUE (abtree.FindBranch (" a" ));
472+ ASSERT_TRUE (abtree.FindBranch (" b" ));
473+ EXPECT_EQ (abtree.FindBranch (" a" )->GetEntries (), 1 );
474+ EXPECT_EQ (abtree.FindBranch (" b" )->GetEntries (), 1 );
475+ }
476+ {
477+ // Case 3 - this (0 entry / 1 branch) + 1 entry (1 branch) + 1 entry (2 branch)
478+ TTree atree (" atree" , " atitle" );
479+ int value;
480+ atree.Branch (" a" , &value);
481+ value = 11 ;
482+ atree.Fill ();
483+ TTree abtree (" abtree" , " abtitle" );
484+ abtree.Branch (" a" , &value);
485+ abtree.Branch (" b" , &value);
486+ value = 42 ;
487+ abtree.Fill ();
488+
489+ TList treelist;
490+ treelist.Add (&atree);
491+ treelist.Add (&abtree);
492+ TTree a0tree (" a0tree" , " a0title" );
493+ a0tree.Branch (" a" , &value);
494+ std::unique_ptr<TFile> file3 (TFile::Open (" d4716.root" , " RECREATE" ));
495+ TFileMergeInfo info3 (file3.get ());
496+ info3.fOptions += " ImportBranches" ;
497+ a0tree.Merge (&treelist, &info3);
498+ file3->Write ();
499+ ASSERT_TRUE (a0tree.FindBranch (" a" ));
500+ EXPECT_EQ (a0tree.FindBranch (" a" )->GetEntries (), 2 );
501+ ASSERT_TRUE (a0tree.FindBranch (" b" ));
502+ EXPECT_EQ (a0tree.FindBranch (" b" )->GetEntries (), 2 );
503+ ASSERT_TRUE (atree.FindBranch (" a" ));
504+ ASSERT_FALSE (atree.FindBranch (" b" ));
505+ ASSERT_TRUE (abtree.FindBranch (" a" ));
506+ ASSERT_TRUE (abtree.FindBranch (" b" ));
507+ EXPECT_EQ (atree.FindBranch (" a" )->GetEntries (), 1 );
508+ EXPECT_EQ (abtree.FindBranch (" a" )->GetEntries (), 1 );
509+ EXPECT_EQ (abtree.FindBranch (" b" )->GetEntries (), 1 );
510+ }
511+ {
512+ // Case 4 - this 1 entry (3 branch) + 1 entry (1 branch) + (0 entry / 1 branch)
513+ TTree abctree (" abctree" , " abctitle" );
514+ int value;
515+ abctree.Branch (" a" , &value);
516+ abctree.Branch (" b" , &value);
517+ abctree.Branch (" c" , &value);
518+ value = 11 ;
519+ abctree.Fill ();
520+ TTree ctree (" ctree" , " ctitle" );
521+ ctree.Branch (" c" , &value);
522+ value = 42 ;
523+ ctree.Fill ();
524+ TTree c0tree (" c0tree" , " c0title" );
525+ c0tree.Branch (" c" , &value);
526+
527+ std::unique_ptr<TFile> file4 (TFile::Open (" e4716.root" , " RECREATE" ));
528+ TFileMergeInfo info4 (file4.get ());
529+ info4.fOptions += " ImportBranches" ;
530+ TList treelist;
531+ treelist.Add (&ctree);
532+ treelist.Add (&c0tree);
533+ ROOT::TestSupport::CheckDiagsRAII diagRAII; // ctree and c0tree don't have a/b branch so warn since they will be auto-filled
534+ diagRAII.requiredDiag (kWarning , " TTree::CopyAddresses" , " Could not find branch named 'a' in tree named 'ctree'" );
535+ diagRAII.requiredDiag (kWarning , " TTree::CopyAddresses" , " Could not find branch named 'b' in tree named 'ctree'" );
536+ diagRAII.requiredDiag (kWarning , " TTree::CopyAddresses" , " Could not find branch named 'a' in tree named 'c0tree'" );
537+ diagRAII.requiredDiag (kWarning , " TTree::CopyAddresses" , " Could not find branch named 'b' in tree named 'c0tree'" );
538+ abctree.Merge (&treelist, &info4);
539+ file4->Write ();
540+ ASSERT_TRUE (abctree.FindBranch (" a" ));
541+ ASSERT_TRUE (abctree.FindBranch (" b" ));
542+ ASSERT_TRUE (abctree.FindBranch (" c" ));
543+ EXPECT_EQ (abctree.FindBranch (" a" )->GetEntries (), 2 );
544+ EXPECT_EQ (abctree.FindBranch (" b" )->GetEntries (), 2 );
545+ EXPECT_EQ (abctree.FindBranch (" c" )->GetEntries (), 2 );
546+ ASSERT_FALSE (ctree.FindBranch (" a" ));
547+ ASSERT_FALSE (ctree.FindBranch (" b" ));
548+ ASSERT_TRUE (ctree.FindBranch (" c" ));
549+ EXPECT_EQ (ctree.FindBranch (" c" )->GetEntries (), 1 );
550+ ASSERT_FALSE (c0tree.FindBranch (" a" ));
551+ ASSERT_FALSE (c0tree.FindBranch (" b" ));
552+ ASSERT_TRUE (c0tree.FindBranch (" c" ));
553+ EXPECT_EQ (c0tree.FindBranch (" c" )->GetEntries (), 0 );
554+ }
555+ }
0 commit comments