@@ -234,6 +234,47 @@ TEST(RNTupleEvolution, Enum)
234234 EXPECT_EQ (kRenamedCustomEnumVal , ve3 (0 ));
235235}
236236
237+ TEST (RNTupleEvolution, CheckAtomic)
238+ {
239+ // TODO(jblomer): enable test with CustomAtomicNotLockFree once linking of libatomic is sorted out.
240+
241+ FileRaii fileGuard (" test_ntuple_evolution_check_atomic.root" );
242+ {
243+ auto model = ROOT::RNTupleModel::Create ();
244+ auto atomicInt = model->MakeField <std::atomic<std::int32_t >>(" atomicInt" );
245+ auto regularInt = model->MakeField <std::int32_t >(" regularInt" );
246+ auto writer = ROOT::RNTupleWriter::Recreate (std::move (model), " ntpl" , fileGuard.GetPath ());
247+
248+ *atomicInt = 7 ;
249+ *regularInt = 13 ;
250+ writer->Fill ();
251+ }
252+
253+ auto reader = RNTupleReader::Open (" ntpl" , fileGuard.GetPath ());
254+
255+ auto v1 = reader->GetView <std::atomic<std::int64_t >>(" atomicInt" );
256+ auto v2 = reader->GetView <std::atomic<std::int64_t >>(" regularInt" );
257+ auto v3 = reader->GetView <std::int64_t >(" atomicInt" );
258+
259+ try {
260+ reader->GetView <std::atomic<std::byte>>(" atomicInt" );
261+ FAIL () << " automatic evolution into an invalid atomic inner type should fail" ;
262+ } catch (const ROOT::RException &err) {
263+ EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible with on-disk field" ));
264+ }
265+
266+ try {
267+ reader->GetView <CustomAtomicNotLockFree>(" atomicInt" );
268+ FAIL () << " automatic evolution into an invalid non-atomic inner type should fail" ;
269+ } catch (const ROOT::RException &err) {
270+ EXPECT_THAT (err.what (), testing::HasSubstr (" incompatible type name for field" ));
271+ }
272+
273+ EXPECT_EQ (7 , v1 (0 ));
274+ EXPECT_EQ (13 , v2 (0 ));
275+ EXPECT_EQ (7 , v3 (0 ));
276+ }
277+
237278TEST (RNTupleEvolution, ArrayAsRVec)
238279{
239280 FileRaii fileGuard (" test_ntuple_evolution_array_as_rvec.root" );
0 commit comments