@@ -284,3 +284,97 @@ TEST_F(RNTupleJoinProcessorTest, WithModel)
284
284
285
285
EXPECT_EQ (5 , proc->GetNEntriesProcessed ());
286
286
}
287
+
288
+ TEST_F (RNTupleJoinProcessorTest, PartialModels)
289
+ {
290
+ {
291
+ std::vector<std::unique_ptr<RNTupleModel>> auxModels;
292
+
293
+ auxModels.emplace_back (RNTupleModel::Create ());
294
+ auto y = auxModels.back ()->MakeField <std::vector<float >>(" y" );
295
+
296
+ auxModels.emplace_back (RNTupleModel::Create ());
297
+ auto z = auxModels.back ()->MakeField <float >(" z" );
298
+
299
+ // no primary model provided, aux models have been provided
300
+ auto procNoPrimaryModel = RNTupleProcessor::CreateJoin (
301
+ {fNTupleNames [0 ], fFileNames [0 ]}, {{fNTupleNames [1 ], fFileNames [1 ]}, {fNTupleNames [2 ], fFileNames [2 ]}}, {" i" },
302
+ nullptr , std::move (auxModels));
303
+
304
+ auto i = procNoPrimaryModel->GetEntry ().GetPtr <int >(" i" );
305
+ std::vector<float > yExpected;
306
+ for (auto &entry : *procNoPrimaryModel) {
307
+ EXPECT_EQ (procNoPrimaryModel->GetCurrentEntryNumber () * 2 , *i);
308
+ EXPECT_FLOAT_EQ (*i * 0 .5f , *entry.GetPtr <float >(" x" ));
309
+ yExpected = {static_cast <float >(*i * 0.2 ), 3.14 , static_cast <float >(*i * 1.3 )};
310
+ EXPECT_EQ (yExpected, *y);
311
+ EXPECT_FLOAT_EQ (static_cast <float >(*i * 2 .f ), *z);
312
+
313
+ try {
314
+ entry.GetPtr <float >(" ntuple2.z" );
315
+ FAIL () << " should not be able to access values from fields not present in the provided models" ;
316
+ } catch (const ROOT::RException &err) {
317
+ EXPECT_THAT (err.what (), testing::HasSubstr (" invalid field name: ntuple2.z" ));
318
+ }
319
+ }
320
+ }
321
+ {
322
+ // primary model provided, no aux models have been provided
323
+ auto primaryModel = RNTupleModel::Create ();
324
+ auto i = primaryModel->MakeField <int >(" i" );
325
+ auto x = primaryModel->MakeField <float >(" x" );
326
+
327
+ auto procNoAuxModels = RNTupleProcessor::CreateJoin (
328
+ {fNTupleNames [0 ], fFileNames [0 ]}, {{fNTupleNames [1 ], fFileNames [1 ]}, {fNTupleNames [2 ], fFileNames [2 ]}}, {" i" },
329
+ std::move (primaryModel));
330
+
331
+ std::vector<float > yExpected;
332
+ for (auto &entry : *procNoAuxModels) {
333
+ EXPECT_EQ (procNoAuxModels->GetCurrentEntryNumber () * 2 , *i);
334
+ EXPECT_FLOAT_EQ (*i * 0 .5f , *x);
335
+ yExpected = {static_cast <float >(*i * 0.2 ), 3.14 , static_cast <float >(*i * 1.3 )};
336
+ EXPECT_EQ (yExpected, *entry.GetPtr <std::vector<float >>(" ntuple2.y" ));
337
+ EXPECT_FLOAT_EQ (static_cast <float >(*i * 2 .f ), *entry.GetPtr <float >(" ntuple3.z" ));
338
+
339
+ try {
340
+ entry.GetPtr <float >(" ntuple2.z" );
341
+ FAIL () << " should not be able to access values from fields not present in the provided models" ;
342
+ } catch (const ROOT::RException &err) {
343
+ EXPECT_THAT (err.what (), testing::HasSubstr (" invalid field name: ntuple2.z" ));
344
+ }
345
+ }
346
+ }
347
+ {
348
+ // primary model and model for first aux ntuple has been provided, but not for the second
349
+ auto primaryModel = RNTupleModel::Create ();
350
+ auto i = primaryModel->MakeField <int >(" i" );
351
+ auto x = primaryModel->MakeField <float >(" x" );
352
+
353
+ std::vector<std::unique_ptr<RNTupleModel>> partialAuxModels;
354
+
355
+ partialAuxModels.emplace_back (RNTupleModel::Create ());
356
+ auto y = partialAuxModels.back ()->MakeField <std::vector<float >>(" y" );
357
+
358
+ partialAuxModels.emplace_back (nullptr );
359
+
360
+ auto procPartialAuxModels = RNTupleProcessor::CreateJoin (
361
+ {fNTupleNames [0 ], fFileNames [0 ]}, {{fNTupleNames [1 ], fFileNames [1 ]}, {fNTupleNames [2 ], fFileNames [2 ]}}, {" i" },
362
+ std::move (primaryModel), std::move (partialAuxModels));
363
+
364
+ std::vector<float > yExpected;
365
+ for (auto &entry : *procPartialAuxModels) {
366
+ EXPECT_EQ (procPartialAuxModels->GetCurrentEntryNumber () * 2 , *i);
367
+ EXPECT_FLOAT_EQ (*i * 0 .5f , *x);
368
+ yExpected = {static_cast <float >(*i * 0.2 ), 3.14 , static_cast <float >(*i * 1.3 )};
369
+ EXPECT_EQ (yExpected, *y);
370
+ EXPECT_FLOAT_EQ (static_cast <float >(*i * 2 .f ), *entry.GetPtr <float >(" ntuple3.z" ));
371
+
372
+ try {
373
+ entry.GetPtr <float >(" ntuple2.z" );
374
+ FAIL () << " should not be able to access values from fields not present in the provided models" ;
375
+ } catch (const ROOT::RException &err) {
376
+ EXPECT_THAT (err.what (), testing::HasSubstr (" invalid field name: ntuple2.z" ));
377
+ }
378
+ }
379
+ }
380
+ }
0 commit comments