|
1 | 1 | #include "ROOT/RDataFrame.hxx" |
| 2 | +#include <TInterpreter.h> |
2 | 3 | #include <TTree.h> |
3 | 4 |
|
4 | 5 | #include "gtest/gtest.h" |
@@ -89,3 +90,56 @@ TEST(Aliases, FilterOnAliasJit) |
89 | 90 | auto c = tdf.Define("c0", [&i]() { return i++; }).Alias("c1", "c0").Filter("c1>1").Count(); |
90 | 91 | EXPECT_EQ(1U, *c); |
91 | 92 | } |
| 93 | + |
| 94 | +// Regression test for https://github.com/root-project/root/issues/22295 |
| 95 | +// A column named "phi" must not be confused with a .phi() method call in a JIT expression. |
| 96 | +TEST(ColNames, MethodCallNotConfusedWithColumn) |
| 97 | +{ |
| 98 | + // Declare minimal helper types for use in JIT strings. |
| 99 | + // Using gInterpreter::Declare avoids any dependency on GenVector or other libraries. |
| 100 | + gInterpreter->Declare("struct RDF22295Vec { double phi() const { return 42.0; } };"); |
| 101 | + gInterpreter->Declare("struct RDF22295Mem { double phi = 1.5; };"); |
| 102 | + |
| 103 | + // Case 1: column "phi" exists, expression calls .phi() method — must not throw, |
| 104 | + // and the result must be the value returned by the method (42.0), not a substitution |
| 105 | + // artifact. Before the fix this crashed with "no member named 'var0'" because the |
| 106 | + // parser replaced .phi() with .var0(). |
| 107 | + { |
| 108 | + ROOT::RDataFrame df(1); |
| 109 | + auto df2 = df.Define("phi", "1.0"); |
| 110 | + std::vector<double> v; |
| 111 | + EXPECT_NO_THROW({ |
| 112 | + auto df3 = df2.Define("result", "RDF22295Vec{}.phi()"); |
| 113 | + v = *df3.Take<double>("result"); |
| 114 | + }); |
| 115 | + EXPECT_NEAR(42.0, v[0], 1e-9); |
| 116 | + } |
| 117 | + |
| 118 | + // Case 2: column "phi" exists, expression uses BOTH .phi() method call AND standalone |
| 119 | + // phi column reference — only the standalone reference must be substituted. |
| 120 | + { |
| 121 | + ROOT::RDataFrame df(1); |
| 122 | + auto df2 = df.Define("phi", "0.5"); |
| 123 | + std::vector<double> v; |
| 124 | + EXPECT_NO_THROW({ |
| 125 | + auto df3 = df2.Define("result", "RDF22295Vec{}.phi() + phi"); |
| 126 | + v = *df3.Take<double>("result"); |
| 127 | + }); |
| 128 | + // .phi() returns 42.0; standalone phi column = 0.5 |
| 129 | + EXPECT_NEAR(42.5, v[0], 1e-9); |
| 130 | + } |
| 131 | + |
| 132 | + // Case 3: data-member access obj.phi (not a function call) must still work after the |
| 133 | + // fix — the preceding-dot guard must not break legitimate dot-chain expressions. |
| 134 | + { |
| 135 | + ROOT::RDataFrame df(1); |
| 136 | + auto df2 = df.Define("phi", "0.5"); |
| 137 | + std::vector<double> v; |
| 138 | + EXPECT_NO_THROW({ |
| 139 | + auto df3 = df2.Define("result", "RDF22295Mem{}.phi + phi"); |
| 140 | + v = *df3.Take<double>("result"); |
| 141 | + }); |
| 142 | + // data member .phi = 1.5; standalone phi column = 0.5 |
| 143 | + EXPECT_NEAR(2.0, v[0], 1e-9); |
| 144 | + } |
| 145 | +} |
0 commit comments