@@ -593,20 +593,12 @@ struct AddedSecondBaseDerived : public AddedSecondBaseFirst, public AddedSecondB
593593)" ));
594594
595595 auto reader = RNTupleReader::Open (" ntpl" , fileGuard.GetPath ());
596- ASSERT_EQ (2 , reader->GetNEntries ());
597-
598- void *ptr = reader->GetModel ().GetDefaultEntry ().GetPtr <void >(" f" ).get ();
599- DeclarePointer (" AddedSecondBaseDerived" , " ptrAddedSecondBaseDerived" , ptr);
600-
601- reader->LoadEntry (0 );
602- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fFirstBase" , 1 );
603- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fSecondBase" , 2 );
604- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fDerived" , 3 );
605-
606- reader->LoadEntry (1 );
607- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fFirstBase" , 71 );
608- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fSecondBase" , 2 );
609- EXPECT_EVALUATE_EQ (" ptrAddedSecondBaseDerived->fDerived" , 93 );
596+ try {
597+ reader->GetModel ();
598+ FAIL () << " model reconstruction should fail" ;
599+ } catch (const ROOT::RException &err) {
600+ EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible number of base classes" ));
601+ }
610602}
611603
612604TEST (RNTupleEvolution, PrependSecondBaseClass)
@@ -662,7 +654,7 @@ struct PrependSecondBaseDerived : public PrependSecondBaseSecond, public Prepend
662654 reader->GetModel ();
663655 FAIL () << " model reconstruction should fail" ;
664656 } catch (const ROOT::RException &err) {
665- EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible type name for field " ));
657+ EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible number of base classes " ));
666658 }
667659}
668660
@@ -844,6 +836,61 @@ struct RemovedIntermediateDerived : public RemovedIntermediateBase {
844836 }
845837}
846838
839+ TEST (RNTupleEvolution, RemovedSecondBaseClass)
840+ {
841+ FileRaii fileGuard (" test_ntuple_evolution_removed_second_base_class.root" );
842+
843+ ExecInFork ([&] {
844+ // The child process writes the file and exits, but the file must be preserved to be read by the parent.
845+ fileGuard.PreserveFile ();
846+
847+ ASSERT_TRUE (gInterpreter ->Declare (R"(
848+ struct RemovedSecondBaseFirst {
849+ int fFirstBase = 1;
850+ };
851+ struct RemovedSecondBaseSecond {
852+ int fSecondBase = 2;
853+ };
854+ struct RemovedSecondBaseDerived : public RemovedSecondBaseFirst, public RemovedSecondBaseSecond {
855+ int fDerived = 3;
856+ };
857+ )" ));
858+
859+ auto model = RNTupleModel::Create ();
860+ model->AddField (RFieldBase::Create (" f" , " RemovedSecondBaseDerived" ).Unwrap ());
861+
862+ auto writer = RNTupleWriter::Recreate (std::move (model), " ntpl" , fileGuard.GetPath ());
863+ writer->Fill ();
864+
865+ // Reset / close the writer and flush the file.
866+ {
867+ // TStreamerInfo::Build will report a warning for interpreted classes (but only for base classes).
868+ // See also https://github.com/root-project/root/issues/9371
869+ ROOT::TestSupport::CheckDiagsRAII diagRAII;
870+ diagRAII.optionalDiag (kWarning , " TStreamerInfo::Build" , " has no streamer or dictionary" ,
871+ /* matchFullMessage=*/ false );
872+ writer.reset ();
873+ }
874+ });
875+
876+ ASSERT_TRUE (gInterpreter ->Declare (R"(
877+ struct RemovedSecondBaseFirst {
878+ int fFirstBase = 1;
879+ };
880+ struct RemovedSecondBaseDerived : public RemovedSecondBaseFirst {
881+ int fDerived = 3;
882+ };
883+ )" ));
884+
885+ auto reader = RNTupleReader::Open (" ntpl" , fileGuard.GetPath ());
886+ try {
887+ reader->GetModel ();
888+ FAIL () << " model reconstruction should fail" ;
889+ } catch (const ROOT::RException &err) {
890+ EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible number of base classes" ));
891+ }
892+ }
893+
847894TEST (RNTupleEvolution, RenamedBaseClass)
848895{
849896 // RNTuple currently does not support automatic schema evolution when a class is renamed.
0 commit comments