Skip to content

Commit 6f2e871

Browse files
authored
Merge pull request #212 from applandinc/fix/stack-overflow-on-prepend
fix: Stack overflow error on prepend
2 parents fead721 + 318d294 commit 6f2e871

File tree

7 files changed

+162
-226
lines changed

7 files changed

+162
-226
lines changed

lib/appmap/builtin_hooks/json.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
- method: JSON::Ext::Parser#parse
2-
label: format.json.parse
2+
labels:
3+
- format.json.parse
4+
- deserialize
35
- method: JSON::Ext::Generator::State#generate
4-
label: format.json.generate
6+
label:
7+
- format.json.generate
8+
- serialize
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
- methods:
2+
- Marshal#load
3+
- Marshal#restore
4+
require_name: ruby
5+
label:
6+
- deserialize
7+
- deserialize.unsafe
8+
- methods:
9+
- Marshal#dump
10+
require_name: ruby
11+
label:
12+
- deserialize

lib/appmap/builtin_hooks/yaml.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
- methods:
22
- Psych#load
3+
- Psych#unsafe_load
4+
- Psych#load_file
5+
- Psych#unsafe_load_file
36
- Psych#load_stream
47
- Psych#parse
58
- Psych#parse_stream
6-
label: format.yaml.parse
9+
label:
10+
- format.yaml.parse
11+
- deserialize
12+
- deserialize.unsafe
13+
- methods:
14+
- Psych#safe_load
15+
label:
16+
- format.yaml.parse
17+
- deserialize
718
- methods:
819
- Psych#dump
920
- Psych#dump_stream
10-
label: format.yaml.generate
21+
label:
22+
- format.yaml.generate
23+
- serialize

lib/appmap/hook/method.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ def activate
9494
end
9595
hook_method_def = hook_method_def.ruby2_keywords if hook_method_def.respond_to?(:ruby2_keywords)
9696

97-
hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
97+
m = Module.new
98+
m.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
99+
hook_class.prepend m
98100
end
99101

100102
protected

spec/config_spec.rb

Lines changed: 86 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -20,235 +20,100 @@
2020
}.deep_stringify_keys!
2121
config = AppMap::Config.load(config_data)
2222

23-
expect(JSON.parse(JSON.generate(config.as_json))).to eq(JSON.parse(<<~FIXTURE))
24-
{
25-
"name": "test",
26-
"appmap_dir": "tmp/appmap",
27-
"packages": [
23+
expect(config.as_json.keys.sort).to eq(["appmap_dir", "builtin_hooks", "depends_config", "exclude", "functions", "gem_hooks", "hook_paths", "name", "packages", "swagger_config"])
24+
expect(config.as_json['appmap_dir']).to eq('tmp/appmap')
25+
expect(config.as_json['name']).to eq('test')
26+
expect(config.as_json['packages']).to eq([])
27+
expect(config.as_json['depends_config']).to eq({
28+
"base_dir" => nil,
29+
"base_branches" => [
30+
"remotes/origin/main",
31+
"remotes/origin/master"
2832
],
29-
"swagger_config": {
30-
"project_name": null,
31-
"project_version": "1.0",
32-
"output_dir": "swagger",
33-
"description": "Generate Swagger from AppMaps"
34-
},
35-
"depends_config": {
36-
"base_dir": null,
37-
"base_branches": [
38-
"remotes/origin/main",
39-
"remotes/origin/master"
40-
],
41-
"test_file_patterns": [
42-
"spec/**/*_spec.rb",
43-
"test/**/*_test.rb"
44-
],
45-
"dependent_tasks": [
46-
"swagger"
47-
],
48-
"description": "Bring AppMaps up to date with local file modifications, and updated derived data such as Swagger files",
49-
"rspec_environment_method": "AppMap::Depends.test_env",
50-
"minitest_environment_method": "AppMap::Depends.test_env",
51-
"rspec_select_tests_method": "AppMap::Depends.select_rspec_tests",
52-
"minitest_select_tests_method": "AppMap::Depends.select_minitest_tests",
53-
"rspec_test_command_method": "AppMap::Depends.rspec_test_command",
54-
"minitest_test_command_method": "AppMap::Depends.minitest_test_command"
55-
},
56-
"hook_paths": [
57-
"pkg",
58-
"#{Gem.loaded_specs['activesupport'].gem_dir}"
33+
"test_file_patterns" => [
34+
"spec/**/*_spec.rb",
35+
"test/**/*_test.rb"
5936
],
60-
"exclude": [
37+
"dependent_tasks" => [
38+
"swagger"
6139
],
62-
"functions": [
63-
{
64-
"cls": "cls",
65-
"target_methods": {
66-
"package": "pkg",
67-
"method_names": [
68-
"fn"
69-
]
70-
}
71-
},
72-
{
73-
"cls": "cls",
74-
"target_methods": {
75-
"package": "pkg",
76-
"method_names": [
77-
"new_fn"
78-
]
79-
}
40+
"description" => "Bring AppMaps up to date with local file modifications, and updated derived data such as Swagger files",
41+
"rspec_environment_method" => "AppMap::Depends.test_env",
42+
"minitest_environment_method" => "AppMap::Depends.test_env",
43+
"rspec_select_tests_method" => "AppMap::Depends.select_rspec_tests",
44+
"minitest_select_tests_method" => "AppMap::Depends.select_minitest_tests",
45+
"rspec_test_command_method" => "AppMap::Depends.rspec_test_command",
46+
"minitest_test_command_method" => "AppMap::Depends.minitest_test_command"
47+
})
48+
expect(config.as_json['swagger_config']).to eq({
49+
"project_name" => nil,
50+
"project_version" => "1.0",
51+
"output_dir" => "swagger",
52+
"description" => "Generate Swagger from AppMaps"
53+
})
54+
expect(config.as_json['hook_paths']).to eq([
55+
"pkg",
56+
"#{Gem.loaded_specs['activesupport'].gem_dir}"
57+
])
58+
expect(config.as_json['exclude']).to eq([])
59+
expect(config.as_json['functions'].map(&:deep_stringify_keys)).to eq([
60+
{
61+
"cls" => "cls",
62+
"target_methods" => {
63+
"package" => "pkg",
64+
"method_names" => [
65+
:fn
66+
]
8067
}
81-
],
82-
"builtin_hooks": {
83-
"JSON::Ext::Parser": [
84-
{
85-
"package": "json",
86-
"method_names": [
87-
"parse"
88-
]
89-
}
90-
],
91-
"JSON::Ext::Generator::State": [
92-
{
93-
"package": "json",
94-
"method_names": [
95-
"generate"
96-
]
97-
}
98-
],
99-
"Logger::LogDevice": [
100-
{
101-
"package": "logger",
102-
"method_names": [
103-
"write"
104-
]
105-
}
106-
],
107-
"Net::HTTP": [
108-
{
109-
"package": "net/http",
110-
"method_names": [
111-
"request"
112-
]
113-
}
114-
],
115-
"OpenSSL::PKey::PKey": [
116-
{
117-
"package": "openssl",
118-
"method_names": [
119-
"sign"
120-
]
121-
}
122-
],
123-
"OpenSSL::X509::Request": [
124-
{
125-
"package": "openssl",
126-
"method_names": [
127-
"sign"
128-
]
129-
},
130-
{
131-
"package": "openssl",
132-
"method_names": [
133-
"verify"
134-
]
135-
}
136-
],
137-
"OpenSSL::X509::Certificate": [
138-
{
139-
"package": "openssl",
140-
"method_names": [
141-
"sign"
142-
]
143-
}
144-
],
145-
"OpenSSL::PKCS5": [
146-
{
147-
"package": "openssl",
148-
"method_names": [
149-
"pbkdf2_hmac"
150-
]
151-
},
152-
{
153-
"package": "openssl",
154-
"method_names": [
155-
"pbkdf2_hmac_sha1"
156-
]
157-
}
158-
],
159-
"OpenSSL::Cipher": [
160-
{
161-
"package": "openssl",
162-
"method_names": [
163-
"encrypt"
164-
]
165-
},
166-
{
167-
"package": "openssl",
168-
"method_names": [
169-
"decrypt"
170-
]
171-
}
172-
],
173-
"Psych": [
174-
{
175-
"package": "yaml",
176-
"method_names": [
177-
"load"
178-
]
179-
},
180-
{
181-
"package": "yaml",
182-
"method_names": [
183-
"load_stream"
184-
]
185-
},
186-
{
187-
"package": "yaml",
188-
"method_names": [
189-
"parse"
190-
]
191-
},
192-
{
193-
"package": "yaml",
194-
"method_names": [
195-
"parse_stream"
196-
]
197-
},
198-
{
199-
"package": "yaml",
200-
"method_names": [
201-
"dump"
202-
]
203-
},
204-
{
205-
"package": "yaml",
206-
"method_names": [
207-
"dump_stream"
208-
]
209-
}
68+
},
69+
{
70+
"cls" => "cls",
71+
"target_methods" => {
72+
"package" => "pkg",
73+
"method_names" => [
74+
:new_fn
75+
]
76+
}
77+
}
78+
])
79+
expect(config.as_json['builtin_hooks']).to have_key('JSON::Ext::Parser')
80+
expect(config.as_json['builtin_hooks']['JSON::Ext::Parser'].map(&:deep_stringify_keys)).to eq([{
81+
"package" => "json",
82+
"method_names" => [
83+
:parse
84+
]
85+
}
86+
])
87+
expect(config.as_json['gem_hooks']).to have_key('cls')
88+
expect(config.as_json['gem_hooks']['cls'].map(&:deep_stringify_keys)).to eq([
89+
{
90+
"package" => "pkg",
91+
"method_names" => [
92+
:fn
93+
]
94+
},
95+
{
96+
"package" => "pkg",
97+
"method_names" => [
98+
:new_fn
99+
]
100+
}
101+
])
102+
expect(config.as_json['gem_hooks']).to have_key('ActiveSupport::Callbacks::CallbackSequence')
103+
expect(config.as_json['gem_hooks']['ActiveSupport::Callbacks::CallbackSequence'].map(&:deep_stringify_keys)).to eq([
104+
{
105+
"package" => "activesupport",
106+
"method_names" => [
107+
:invoke_before
210108
]
211109
},
212-
"gem_hooks": {
213-
"cls": [
214-
{
215-
"package": "pkg",
216-
"method_names": [
217-
"fn"
218-
]
219-
},
220-
{
221-
"package": "pkg",
222-
"method_names": [
223-
"new_fn"
224-
]
225-
}
226-
],
227-
"ActiveSupport::Callbacks::CallbackSequence": [
228-
{
229-
"package": "activesupport",
230-
"method_names": [
231-
"invoke_before"
232-
]
233-
},
234-
{
235-
"package": "activesupport",
236-
"method_names": [
237-
"invoke_after"
238-
]
239-
}
240-
],
241-
"ActiveSupport::SecurityUtils": [
242-
{
243-
"package": "activesupport",
244-
"method_names": [
245-
"secure_compare"
246-
]
247-
}
110+
{
111+
"package" => "activesupport",
112+
"method_names" => [
113+
:invoke_after
248114
]
249115
}
250-
}
251-
FIXTURE
116+
])
252117
end
253118

254119
describe AppMap::Config::Package do
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
module PrependedModule
3+
def say_hello
4+
'please allow me to ' + super
5+
end
6+
end
7+
8+
class PrependedClass
9+
prepend PrependedModule
10+
11+
def say_hello
12+
'introduce myself'
13+
end
14+
end

0 commit comments

Comments
 (0)