|
886 | 886 | %i[caller_locations path probe serialized_locals target_self] |
887 | 887 | end |
888 | 888 |
|
| 889 | + shared_examples 'multiple invocations' do |
| 890 | + # Since the instrumentation mutates the state of the probe, |
| 891 | + # verify that the state mutation is not breaking the instrumentation. |
| 892 | + context 'when the code is executed multiple times' do |
| 893 | + before do |
| 894 | + load File.join(File.dirname(__FILE__), 'hook_line_load.rb') |
| 895 | + end |
| 896 | + |
| 897 | + let(:probe) do |
| 898 | + Datadog::DI::Probe.new(file: 'hook_line_load.rb', line_no: 5, |
| 899 | + id: 1, type: :log, rate_limit: rate_limit) |
| 900 | + end |
| 901 | + |
| 902 | + it 'invokes the instrumentation every time' do |
| 903 | + expect_any_instance_of(TracePoint).to receive(:enable).and_call_original |
| 904 | + |
| 905 | + instrumenter.hook_line(probe) do |payload| |
| 906 | + observed_calls << payload |
| 907 | + end |
| 908 | + |
| 909 | + HookLineLoadTestClass.new.test_method |
| 910 | + HookLineLoadTestClass.new.test_method |
| 911 | + |
| 912 | + expect(observed_calls.length).to eq 2 |
| 913 | + |
| 914 | + expect(observed_calls[0].keys.sort).to eq(call_keys) |
| 915 | + expect(observed_calls[1].keys.sort).to eq(call_keys) |
| 916 | + end |
| 917 | + end |
| 918 | + end |
| 919 | + |
889 | 920 | context 'when called without a block' do |
890 | 921 | let(:probe) do |
891 | 922 | instance_double(Datadog::DI::Probe) |
|
999 | 1030 | end |
1000 | 1031 | end |
1001 | 1032 |
|
1002 | | - context 'line inside of method' do |
| 1033 | + context 'line inside of method without code tracking' do |
1003 | 1034 | before do |
1004 | 1035 | # We need untargeted trace points for this test since the line |
1005 | 1036 | # being instrumented has already been loaded. |
|
1035 | 1066 | expect(File.basename(frame.path)).to eq 'hook_line.rb' |
1036 | 1067 | end |
1037 | 1068 | end |
| 1069 | + |
| 1070 | + include_examples 'multiple invocations' |
1038 | 1071 | end |
1039 | 1072 |
|
1040 | 1073 | context 'when hooking same line twice with identical but different probes' do |
|
1116 | 1149 | expect(observed_calls.first).to be_a(Hash) |
1117 | 1150 | end |
1118 | 1151 |
|
| 1152 | + context 'end line of a method' do |
| 1153 | + before do |
| 1154 | + load File.join(File.dirname(__FILE__), 'hook_line_load.rb') |
| 1155 | + end |
| 1156 | + |
| 1157 | + let(:probe) do |
| 1158 | + Datadog::DI::Probe.new(file: 'hook_line_load.rb', line_no: 6, |
| 1159 | + id: 1, type: :log, rate_limit: rate_limit) |
| 1160 | + end |
| 1161 | + |
| 1162 | + it 'invokes the instrumentation' do |
| 1163 | + expect_any_instance_of(TracePoint).to receive(:enable).and_call_original |
| 1164 | + |
| 1165 | + instrumenter.hook_line(probe) do |payload| |
| 1166 | + observed_calls << payload |
| 1167 | + end |
| 1168 | + |
| 1169 | + HookLineLoadTestClass.new.test_method |
| 1170 | + |
| 1171 | + expect(observed_calls.length).to eq 1 |
| 1172 | + |
| 1173 | + expect(observed_calls[0].keys.sort).to eq(call_keys) |
| 1174 | + end |
| 1175 | + |
| 1176 | + # Since the instrumentation mutates the state of the probe, |
| 1177 | + # verify that the state mutation is not breaking the instrumentation. |
| 1178 | + context 'when the code is executed multiple times' do |
| 1179 | + it 'invokes the instrumentation every time' do |
| 1180 | + expect_any_instance_of(TracePoint).to receive(:enable).and_call_original |
| 1181 | + |
| 1182 | + instrumenter.hook_line(probe) do |payload| |
| 1183 | + observed_calls << payload |
| 1184 | + end |
| 1185 | + |
| 1186 | + HookLineLoadTestClass.new.test_method |
| 1187 | + HookLineLoadTestClass.new.test_method |
| 1188 | + |
| 1189 | + expect(observed_calls.length).to eq 2 |
| 1190 | + |
| 1191 | + expect(observed_calls[0].keys.sort).to eq(call_keys) |
| 1192 | + expect(observed_calls[1].keys.sort).to eq(call_keys) |
| 1193 | + end |
| 1194 | + end |
| 1195 | + end |
| 1196 | + |
1119 | 1197 | context 'when instrumenting a line in loaded but not tracked file' do |
1120 | 1198 | let(:probe) do |
1121 | 1199 | Datadog::DI::Probe.new(file: 'hook_line.rb', line_no: 3, |
|
1129 | 1207 | end.to raise_error(Datadog::DI::Error::DITargetNotInRegistry, /File matching probe path.*was loaded and is not in code tracker registry/) |
1130 | 1208 | end |
1131 | 1209 | end |
| 1210 | + |
| 1211 | + include_examples 'multiple invocations' |
1132 | 1212 | end |
1133 | 1213 |
|
1134 | 1214 | context 'when method is recursive' do |
|
1208 | 1288 | end |
1209 | 1289 | end |
1210 | 1290 |
|
| 1291 | + context 'when the instrumented line raises an exception' do |
| 1292 | + include_context 'with code tracking' |
| 1293 | + |
| 1294 | + before do |
| 1295 | + load File.join(File.dirname(__FILE__), 'hook_line_load.rb') |
| 1296 | + end |
| 1297 | + |
| 1298 | + let(:probe) do |
| 1299 | + Datadog::DI::Probe.new(file: 'hook_line_load.rb', line_no: 32, |
| 1300 | + id: 1, type: :log, rate_limit: rate_limit) |
| 1301 | + end |
| 1302 | + |
| 1303 | + let(:payload) do |
| 1304 | + expect_any_instance_of(TracePoint).to receive(:enable).and_call_original |
| 1305 | + |
| 1306 | + instrumenter.hook_line(probe) do |payload| |
| 1307 | + observed_calls << payload |
| 1308 | + end |
| 1309 | + |
| 1310 | + expect do |
| 1311 | + HookLineIvarLoadTestClass.new.test_exception |
| 1312 | + end.to raise_error(HookLineIvarLoadTestClass::TestException) |
| 1313 | + |
| 1314 | + expect(observed_calls.length).to eq 1 |
| 1315 | + observed_calls.first |
| 1316 | + end |
| 1317 | + |
| 1318 | + it 'invokes callback with expected keys' do |
| 1319 | + expect(payload).to be_a(Hash) |
| 1320 | + expect(payload.keys.sort).to eq(call_keys) |
| 1321 | + end |
| 1322 | + end |
| 1323 | + |
1211 | 1324 | context 'when there is a condition' do |
1212 | 1325 | include_context 'with code tracking' |
1213 | 1326 |
|
|
0 commit comments