@@ -8,6 +8,8 @@ class ServerTest < ActiveSupport::TestCase
88 setup do
99 @stdout = StringIO . new
1010 @stderr = StringIO . new
11+ RubyLsp ::Rails ::ServerAddon . instance_variable_set ( :@server_addon_classes , [ ] )
12+ RubyLsp ::Rails ::ServerAddon . instance_variable_set ( :@server_addons , { } )
1113 @server = RubyLsp ::Rails ::Server . new ( stdout : @stdout , stderr : @stderr , override_default_output_device : false )
1214 end
1315
@@ -268,6 +270,91 @@ def print_it!
268270 $> = original_stdout
269271 end
270272
273+ test "forked processes are named based on caller" do
274+ skip ( "Fork is not supported on Windows" ) if Gem . win_platform?
275+
276+ addon_path = File . expand_path ( "my_addon.rb" )
277+ File . write ( addon_path , <<~RUBY )
278+ module Patch
279+ def setproctitle(title)
280+ $TEST_TITLE = title
281+ end
282+
283+ Process.singleton_class.prepend(Patch)
284+ end
285+
286+ class MyServerAddon < RubyLsp::Rails::ServerAddon
287+ def name
288+ "MyAddon"
289+ end
290+
291+ def execute(request, params)
292+ file = "process_name.txt"
293+
294+ # We can't directly send a message in these tests because we're using a StringIO as stdout instead of the
295+ # actual pipe, which means that the child process doesn't have access to the same object
296+ pid = fork { File.write(file, $TEST_TITLE) }
297+ Process.wait(pid)
298+
299+ send_message({ process_name: File.read(file) })
300+ File.delete(file)
301+ end
302+ end
303+ RUBY
304+
305+ begin
306+ @server . execute ( "server_addon/register" , server_addon_path : addon_path )
307+ @server . execute ( "server_addon/delegate" , server_addon_name : "MyAddon" , request_name : "dsl" )
308+ assert_equal ( response , { process_name : "ruby-lsp-rails: #{ addon_path } " } )
309+ ensure
310+ FileUtils . rm ( addon_path )
311+ end
312+ end
313+
314+ test "forked processes with no block are named based on caller" do
315+ skip ( "Fork is not supported on Windows" ) if Gem . win_platform?
316+
317+ addon_path = File . expand_path ( "my_other_addon.rb" )
318+ File . write ( addon_path , <<~RUBY )
319+ module Patch
320+ def setproctitle(title)
321+ $TEST_TITLE = title
322+ end
323+
324+ Process.singleton_class.prepend(Patch)
325+ end
326+
327+ class MyOtherServerAddon < RubyLsp::Rails::ServerAddon
328+ def name
329+ "MyOtherAddon"
330+ end
331+
332+ def execute(request, params)
333+ file = "other_process_name.txt"
334+ pid = fork
335+
336+ if pid
337+ Process.wait(pid)
338+ send_message({ process_name: File.read(file) })
339+ File.delete(file)
340+ else
341+ File.write(file, $TEST_TITLE)
342+ # Exit from the child process or else we're stuck in the infinite loop of the server
343+ exit!
344+ end
345+ end
346+ end
347+ RUBY
348+
349+ begin
350+ @server . execute ( "server_addon/register" , server_addon_path : addon_path )
351+ @server . execute ( "server_addon/delegate" , server_addon_name : "MyOtherAddon" , request_name : "dsl" )
352+ assert_equal ( response , { process_name : "ruby-lsp-rails: #{ addon_path } " } )
353+ ensure
354+ FileUtils . rm ( addon_path )
355+ end
356+ end
357+
271358 private
272359
273360 def response
0 commit comments