appmap 0.77.4 → 0.80.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.travis.yml +4 -16
  4. data/CHANGELOG.md +30 -0
  5. data/{spec/fixtures/rails5_users_app/Dockerfile.pg → Dockerfile.pg} +0 -0
  6. data/README.md +14 -44
  7. data/README_CI.md +0 -7
  8. data/Rakefile +12 -150
  9. data/appmap.gemspec +3 -2
  10. data/docker-compose.yml +10 -0
  11. data/ext/appmap/appmap.c +21 -2
  12. data/lib/appmap/agent.rb +8 -0
  13. data/lib/appmap/builtin_hooks/ruby.yml +6 -3
  14. data/lib/appmap/event.rb +19 -12
  15. data/lib/appmap/gem_hooks/actionpack.yml +6 -0
  16. data/lib/appmap/handler/eval.rb +41 -0
  17. data/lib/appmap/handler/rails/render_handler.rb +29 -0
  18. data/lib/appmap/handler/rails/request_handler.rb +13 -11
  19. data/lib/appmap/handler/rails/sql_handler.rb +43 -1
  20. data/lib/appmap/handler.rb +3 -0
  21. data/lib/appmap/hook/method.rb +0 -1
  22. data/lib/appmap/version.rb +1 -1
  23. data/spec/config_spec.rb +1 -1
  24. data/spec/depends/api_spec.rb +13 -5
  25. data/spec/depends/spec_helper.rb +0 -9
  26. data/spec/fixtures/database.yml +11 -0
  27. data/spec/fixtures/rails5_users_app/config/database.yml +1 -0
  28. data/spec/fixtures/rails6_users_app/Gemfile +1 -25
  29. data/spec/fixtures/rails6_users_app/config/database.yml +1 -0
  30. data/spec/fixtures/rails7_users_app/Gemfile +1 -25
  31. data/spec/fixtures/rails7_users_app/config/database.yml +1 -0
  32. data/spec/handler/eval_spec.rb +66 -0
  33. data/spec/hook_spec.rb +6 -1
  34. data/spec/rails_recording_spec.rb +7 -21
  35. data/spec/rails_spec_helper.rb +76 -63
  36. data/spec/rails_test_spec.rb +7 -17
  37. data/spec/railtie_spec.rb +4 -18
  38. data/spec/record_sql_rails_pg_spec.rb +44 -75
  39. data/spec/remote_recording_spec.rb +18 -30
  40. data/spec/spec_helper.rb +1 -0
  41. data/spec/swagger/swagger_spec.rb +1 -16
  42. data/spec/util_spec.rb +1 -1
  43. data/test/expectations/openssl_test_key_sign2-3.1.json +2 -1
  44. metadata +24 -21
  45. data/Dockerfile.appmap +0 -5
  46. data/spec/fixtures/rack_users_app/Dockerfile +0 -32
  47. data/spec/fixtures/rack_users_app/docker-compose.yml +0 -9
  48. data/spec/fixtures/rails5_users_app/Dockerfile +0 -29
  49. data/spec/fixtures/rails5_users_app/config/database.yml +0 -18
  50. data/spec/fixtures/rails5_users_app/create_app +0 -33
  51. data/spec/fixtures/rails5_users_app/docker-compose.yml +0 -31
  52. data/spec/fixtures/rails6_users_app/.ruby-version +0 -1
  53. data/spec/fixtures/rails6_users_app/Dockerfile +0 -44
  54. data/spec/fixtures/rails6_users_app/Dockerfile.pg +0 -3
  55. data/spec/fixtures/rails6_users_app/config/database.yml +0 -18
  56. data/spec/fixtures/rails6_users_app/create_app +0 -33
  57. data/spec/fixtures/rails6_users_app/docker-compose.yml +0 -31
  58. data/spec/fixtures/rails7_users_app/.ruby-version +0 -1
  59. data/spec/fixtures/rails7_users_app/Dockerfile +0 -30
  60. data/spec/fixtures/rails7_users_app/Dockerfile.pg +0 -3
  61. data/spec/fixtures/rails7_users_app/config/database.yml +0 -86
  62. data/spec/fixtures/rails7_users_app/create_app +0 -31
  63. data/spec/fixtures/rails7_users_app/docker-compose.yml +0 -31
@@ -1,93 +1,106 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'open3'
4
+
3
5
  require 'spec_helper'
4
6
  require 'active_support'
5
7
  require 'active_support/core_ext'
6
- require 'open3'
7
8
 
8
- # The RUBY_VERSION global variable indicates the version of the
9
- # runtime. The RUBY_VERSION environment variable is the version we're
10
- # testing, so it needs to be used to pick a fixture directory.
11
9
  def testing_ruby_2?
12
- ENV['RUBY_VERSION'].split('.')[0].to_i == 2
10
+ RUBY_VERSION.split('.')[0].to_i == 2
13
11
  end
14
12
 
15
- # docker compose v2 replaced the --filter flag with --status
16
- PS_CMD=`docker-compose --version` =~ /version v2/ ?
17
- "docker-compose ps -q --status running" :
18
- "docker-compose ps -q --filter health=healthy"
13
+ class TestRailsApp
14
+ def initialize(fixture_dir)
15
+ @fixture_dir = fixture_dir
16
+ end
19
17
 
20
- def wait_for_container(app_name)
21
- start_time = Time.now
22
- until `#{PS_CMD} #{app_name}`.strip != ''
23
- elapsed = Time.now - start_time
24
- raise "Timeout waiting for container #{app_name} to be ready" if elapsed > 10
18
+ attr_reader :fixture_dir
25
19
 
26
- $stderr.write '.' if elapsed > 3
27
- sleep 0.25
20
+ def run_cmd(cmd, env = {})
21
+ run_process method(:system), cmd, env, exception: true
28
22
  end
29
- end
30
23
 
31
- def run_cmd(*cmd, &failed)
32
- out, status = Open3.capture2e(*cmd)
33
- return [ out, status ] if status.success?
34
-
35
- warn <<~WARNING
36
- Command failed:
37
- #{cmd}
38
- <<< Output:
39
- #{out}
40
- >>> End of output
41
- WARNING
42
- failed&.call
43
- raise 'Command failed'
44
- end
24
+ def spawn_cmd(cmd, env = {})
25
+ puts "Spawning `#{cmd}` in #{fixture_dir}..."
26
+ run_process Process.method(:spawn), cmd, env
27
+ end
45
28
 
46
- shared_context 'Rails app pg database' do |fixture_dir|
47
- define_method(:fixture_dir) { fixture_dir }
29
+ def capture_cmd(cmd, env = {})
30
+ puts "Capturing `#{cmd}` in #{fixture_dir}..."
31
+ run_process(Open3.method(:capture2), cmd, env).first
32
+ end
48
33
 
49
- before(:all) do
50
- print_pg_logs = lambda do
51
- logs, = run_cmd 'docker-compose logs pg'
52
- puts "docker-compose logs for pg:"
53
- puts
54
- puts logs
55
- end
34
+ def database_name
35
+ # This is used locally too, so make the name nice and unique.
36
+ @database_name ||= "appland-rails-test-#{Random.bytes(8).unpack1('h*')}"
37
+ end
56
38
 
57
- Dir.chdir fixture_dir do
58
- run_cmd 'docker-compose down -v'
59
- cmd = 'docker-compose up -d pg'
60
- run_cmd cmd
61
- wait_for_container 'pg'
39
+ def bundle
40
+ return if @bundled
62
41
 
63
- cmd = 'docker-compose run --rm app ./create_app'
64
- run_cmd cmd, &print_pg_logs
65
- end
42
+ run_cmd 'bundle'
43
+ @bundled = true
66
44
  end
67
45
 
68
- after(:all) do
69
- if ENV['NOKILL'] != 'true'
70
- cmd = 'docker-compose down -v'
71
- run_cmd cmd, chdir: fixture_dir
72
- end
46
+ def prepare_db
47
+ return if @db_prepared
48
+
49
+ bundle
50
+ run_cmd './bin/rake db:create db:schema:load'
51
+ @db_prepared = true
52
+ at_exit { drop_db }
53
+ end
54
+
55
+ def drop_db
56
+ return unless @db_prepared
57
+
58
+ run_cmd './bin/rake db:drop'
59
+ @db_prepared = false
73
60
  end
74
- end
75
61
 
76
- shared_context 'rails integration test setup' do
77
62
  def tmpdir
78
- 'tmp/spec/AbstractControllerBase'
63
+ @tmpdir ||= File.join(fixture_dir, 'tmp')
64
+ end
65
+
66
+ def run_specs
67
+ return if @specs_ran or use_existing_data?
68
+
69
+ prepare_db
70
+ FileUtils.rm_rf tmpdir
71
+ run_cmd \
72
+ './bin/rspec spec/controllers/users_controller_spec.rb spec/controllers/users_controller_api_spec.rb',
73
+ 'APPMAP' => 'true'
74
+ @specs_ran = true
75
+ end
76
+
77
+ def self.for_fixture(fixture_dir)
78
+ @apps ||= {}
79
+ @apps[fixture_dir] ||= TestRailsApp.new fixture_dir
79
80
  end
80
81
 
81
- unless use_existing_data?
82
- before(:all) do
83
- FileUtils.rm_rf tmpdir
84
- FileUtils.mkdir_p tmpdir
85
- run_spec 'spec/controllers/users_controller_spec.rb'
86
- run_spec 'spec/controllers/users_controller_api_spec.rb'
82
+ protected
83
+
84
+ def run_process(method, cmd, env, options = {})
85
+ Bundler.with_clean_env do
86
+ method.call \
87
+ env.merge('TEST_DATABASE' => database_name),
88
+ cmd,
89
+ options.merge(chdir: fixture_dir)
87
90
  end
88
91
  end
92
+ end
93
+
94
+ shared_context 'Rails app pg database' do |dir|
95
+ before(:all) { @app = TestRailsApp.for_fixture dir }
96
+ let(:app) { @app }
97
+ end
98
+
99
+ shared_context 'rails integration test setup' do
100
+ let(:tmpdir) { app.tmpdir }
101
+
102
+ before(:all) { @app.run_specs } unless use_existing_data?
89
103
 
90
- let(:appmap) { JSON.parse File.read File.join tmpdir, 'appmap/rspec', appmap_json_file }
91
104
  let(:appmap_json_path) { File.join(tmpdir, 'appmap/rspec', appmap_json_file) }
92
105
  let(:appmap) { JSON.parse File.read(appmap_json_path) }
93
106
  let(:events) { appmap['events'] }
@@ -3,7 +3,7 @@ require 'rails_spec_helper'
3
3
  # Rails5 doesn't work with Ruby 3.x, Rails 7 doesn't work with Ruby < 2.7.
4
4
  def default_rails_versions
5
5
  if testing_ruby_2?
6
- if Gem::Requirement.create('>= 2.7') =~ Gem::Version.new(ENV['RUBY_VERSION'])
6
+ if Gem::Requirement.create('>= 2.7') =~ Gem::Version.new(RUBY_VERSION)
7
7
  [ 5, 6, 7 ]
8
8
  else
9
9
  [ 5, 6 ]
@@ -21,24 +21,14 @@ describe 'Rails' do
21
21
  rails_versions.each do |rails_major_version| # rubocop:disable Metrics/BlockLength
22
22
  context "#{rails_major_version}" do
23
23
  include_context 'Rails app pg database', "spec/fixtures/rails#{rails_major_version}_users_app" unless use_existing_data?
24
- def tmpdir
25
- 'tmp/spec/rails_test_spec'
26
- end
27
- before(:all) do
28
- FileUtils.rm_rf tmpdir
29
- FileUtils.mkdir_p tmpdir
30
- end
31
-
32
- def run_tests
33
- cmd = <<~CMD.gsub "\n", ' '
34
- docker-compose run --rm -e RAILS_ENV=test -e APPMAP=true -e TEST_OPTS=--verbose
35
- -v #{File.absolute_path tmpdir}:/app/tmp app bundle exec rake
36
- CMD
37
- run_cmd cmd, chdir: fixture_dir
38
- end
39
24
 
40
25
  it 'runs tests with APPMAP=true' do
41
- run_tests
26
+ app.prepare_db
27
+ app.run_cmd \
28
+ 'bundle exec rake',
29
+ 'RAILS_ENV' => 'test',
30
+ 'APPMAP' => 'true',
31
+ 'TEST_OPTS' => '--verbose'
42
32
  end
43
33
  end
44
34
  end
data/spec/railtie_spec.rb CHANGED
@@ -1,27 +1,13 @@
1
1
  require 'rails_spec_helper'
2
2
 
3
3
  describe 'AppMap tracer via Railtie' do
4
- include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
4
+ include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
5
5
  let(:env) { {} }
6
6
 
7
- let(:cmd) { %(docker-compose run --rm -e RAILS_ENV=development -e APPMAP app ./bin/rails r "puts AppMap.instance_variable_get('@configuration').nil?") }
8
- let(:command_capture2) do
9
- require 'open3'
10
- Open3.capture3(env, cmd, chdir: fixture_dir).tap do |result|
11
- unless result[2] == 0
12
- warn <<~STDERR
13
- Failed to run rails6_users_app container
14
- <<< Output:
15
- #{result[0]}
16
- #{result[1]}
17
- >>> End of output
18
- STDERR
19
- raise 'Failed to run rails6_users_app container'
20
- end
21
- end
7
+ let(:command_output) do
8
+ app.prepare_db
9
+ app.capture_cmd(%{./bin/rails r "puts AppMap.instance_variable_get('@configuration').nil?"}, env).strip
22
10
  end
23
- let(:command_output) { command_capture2[0].strip }
24
- let(:command_result) { command_capture2[2] }
25
11
 
26
12
  describe 'with APPMAP=false' do
27
13
  let(:env) { { 'APPMAP' => 'false' } }
@@ -2,89 +2,58 @@ require 'rails_spec_helper'
2
2
 
3
3
  describe 'SQL events' do
4
4
  include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
5
- around(:each) do |example|
6
- FileUtils.rm_rf tmpdir
7
- FileUtils.mkdir_p tmpdir
8
- cmd = "docker-compose run --rm -e ORM_MODULE=#{orm_module} -e RAILS_ENV=test -e APPMAP=true -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec spec/controllers/users_controller_api_spec.rb:#{test_line_number}"
9
- run_cmd cmd, chdir: fixture_dir
10
-
11
- example.run
12
- end
13
-
14
- let(:tmpdir) { "tmp/spec/record_sql_rails_pg_spec" }
15
-
16
- describe 'fields' do
17
- let(:test_line_number) { 8 }
18
- let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
19
- let(:orm_module) { 'sequel' }
20
- let(:appmap) { JSON.parse(File.read(appmap_json)) }
21
- describe 'on a call event' do
22
- let(:event) do
23
- appmap['events'].find do |event|
24
- event['event'] == 'call' &&
25
- event.keys.include?('sql_query')
5
+ def self.check_queries(cases)
6
+ cases.each do |test_case, query|
7
+ context "in #{test_case}" do
8
+ let(:test_case) { test_case }
9
+ it "captures #{query}" do
10
+ expect(sql_events).to include sql_query query
26
11
  end
27
12
  end
28
- it 'do not include function-only fields' do
29
- expect(event.keys).to_not include('defined_class')
30
- expect(event.keys).to_not include('method_id')
31
- expect(event.keys).to_not include('path')
32
- expect(event.keys).to_not include('lineno')
33
- end
34
13
  end
35
14
  end
36
15
 
37
- describe 'in a Rails app' do
38
- let(:appmap) { JSON.parse(File.read(appmap_json)).to_yaml }
39
- context 'while creating a new record' do
40
- let(:test_line_number) { 8 }
41
- let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_POST_api_users_with_required_parameters_creates_a_user.appmap.json') }
16
+ context 'with Sequel' do
17
+ before(:context) { run_specs 'sequel' }
42
18
 
43
- context 'using Sequel ORM' do
44
- let(:orm_module) { 'sequel' }
45
- it 'detects the sql INSERT' do
46
- expect(appmap).to include(<<-SQL_QUERY.strip)
47
- sql_query:
48
- sql: INSERT INTO "users" ("login") VALUES ('alice') RETURNING *
49
- SQL_QUERY
50
- end
51
- end
52
- context 'using ActiveRecord ORM' do
53
- let(:orm_module) { 'activerecord' }
54
- it 'detects the sql INSERT' do
55
- expect(appmap).to include(<<-SQL_QUERY.strip)
56
- sql_query:
57
- sql: INSERT INTO "users" ("login") VALUES ($1) RETURNING "id"
58
- SQL_QUERY
59
- end
60
- end
61
- end
19
+ check_queries(
20
+ 'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user' =>
21
+ %(INSERT INTO "users" ("login") VALUES ('alice') RETURNING *),
22
+ 'Api_UsersController_GET_api_users_lists_the_users' => %(SELECT * FROM "users")
23
+ )
24
+ end
62
25
 
63
- context 'while listing records' do
64
- let(:test_line_number) { 29 }
65
- let(:appmap_json) { File.join(tmpdir, 'appmap/rspec/Api_UsersController_GET_api_users_lists_the_users.appmap.json') }
26
+ context 'with ActiveRecord' do
27
+ before(:context) { run_specs 'activerecord' }
66
28
 
67
- context 'using Sequel ORM' do
68
- let(:orm_module) { 'sequel' }
69
- it 'detects the sql SELECT' do
70
- expect(appmap).to include(<<-SQL_QUERY.strip)
71
- sql_query:
72
- sql: SELECT * FROM "users"
73
- SQL_QUERY
74
-
75
- expect(appmap).to include('sql:')
76
- end
77
- end
78
- context 'using ActiveRecord ORM' do
79
- let(:orm_module) { 'activerecord' }
80
- it 'detects the sql SELECT' do
81
- expect(appmap).to include(<<-SQL_QUERY.strip)
82
- sql_query:
83
- sql: SELECT "users".* FROM "users"
84
- SQL_QUERY
85
- end
86
- end
87
- end
29
+ check_queries(
30
+ 'Api_UsersController_POST_api_users_with_required_parameters_creates_a_user' =>
31
+ %(INSERT INTO "users" ("login") VALUES ($1) RETURNING "id"),
32
+ 'Api_UsersController_GET_api_users_lists_the_users' => %(SELECT "users".* FROM "users")
33
+ )
34
+ end
35
+
36
+ def run_specs(orm_module)
37
+ @app.prepare_db
38
+ @app.run_cmd \
39
+ './bin/rspec spec/controllers/users_controller_api_spec.rb:8 spec/controllers/users_controller_api_spec.rb:29',
40
+ 'ORM_MODULE' => orm_module,
41
+ 'RAILS_ENV' => 'test',
42
+ 'APPMAP' => 'true'
43
+ end
44
+
45
+ let(:appmap_json) { File.join tmpdir, "appmap/rspec/#{test_case}.appmap.json" }
46
+ let(:appmap) { JSON.parse(File.read(appmap_json)) }
47
+ let(:tmpdir) { app.tmpdir }
48
+ let(:sql_events) { appmap['events'].select { |ev| ev.include? 'sql_query' } }
49
+
50
+ RSpec::Matchers.define_negated_matcher :not_include, :include
51
+ def sql_query(query)
52
+ (include('sql_query' => (include 'sql' => query)))
53
+ .and(not_include('defined_class'))
54
+ .and(not_include('method_id'))
55
+ .and(not_include('path'))
56
+ .and(not_include('lineno'))
88
57
  end
89
58
  end
90
59
  end
@@ -1,41 +1,27 @@
1
1
  require 'rails_spec_helper'
2
+
3
+ require 'random-port'
4
+
2
5
  require 'net/http'
3
6
  require 'socket'
4
7
 
5
8
  describe 'remote recording', :order => :defined do
6
9
  include_context 'Rails app pg database', 'spec/fixtures/rails6_users_app' do
7
10
  before(:all) do
8
- fixture_dir = 'spec/fixtures/rails6_users_app'
9
- start_cmd = 'docker-compose up -d app'
10
- run_cmd({ 'ORM_MODULE' => 'sequel', 'APPMAP' => 'true' }, start_cmd, chdir: fixture_dir)
11
- Dir.chdir fixture_dir do
12
- wait_for_container 'app'
13
- end
11
+ @service_port = RandomPort::Pool::SINGLETON.acquire
12
+ @app.prepare_db
13
+ @server = @app.spawn_cmd \
14
+ "./bin/rails server -p #{@service_port}",
15
+ 'ORM_MODULE' => 'sequel',
16
+ 'APPMAP' => 'true'
14
17
 
15
- port_cmd = 'docker-compose port app 3000'
16
- port_out, = run_cmd port_cmd, chdir: fixture_dir
17
- @service_port = port_out.strip.split(':')[1]
18
-
19
- service_running = false
20
- retry_count = 0
21
18
  uri = URI("http://localhost:#{@service_port}/health")
22
19
 
23
- until service_running
24
- sleep(0.25)
25
- begin
26
- res = Net::HTTP.start(uri.hostname, uri.port) do |http|
27
- http.request(Net::HTTP::Get.new(uri))
28
- end
29
-
30
- status = res.response.code.to_i
31
- service_running = true if status >= 200 && status < 300
32
-
33
- # give up after a certain error threshold is met
34
- # we don't want to wait forever if there's an unrecoverable issue
35
- raise 'gave up waiting on fixture service' if (retry_count += 1) == 10
36
- rescue Errno::ETIMEDOUT, Errno::ECONNRESET, EOFError
37
- $stderr.print('.')
38
- end
20
+ 100.times do
21
+ Net::HTTP.get(uri)
22
+ break
23
+ rescue Errno::ECONNREFUSED
24
+ sleep 0.1
39
25
  end
40
26
  end
41
27
 
@@ -44,8 +30,10 @@ describe 'remote recording', :order => :defined do
44
30
  end
45
31
 
46
32
  after(:all) do
47
- fixture_dir = 'spec/fixtures/rails6_users_app'
48
- run_cmd 'docker-compose rm -fs app', chdir: fixture_dir
33
+ if @server
34
+ Process.kill 'INT', @server
35
+ Process.wait @server
36
+ end
49
37
  end
50
38
 
51
39
  let(:service_address) { URI("http://localhost:#{@service_port}") }
data/spec/spec_helper.rb CHANGED
@@ -13,6 +13,7 @@ require 'appmap'
13
13
 
14
14
  RSpec.configure do |config|
15
15
  config.example_status_persistence_file_path = "tmp/rspec_failed_examples.txt"
16
+ config.profile_examples = true
16
17
  end
17
18
 
18
19
  # Re-run the Rails specs without re-generating the data. This is useful for efficiently enhancing and
@@ -4,24 +4,9 @@ describe 'rake appmap:swagger' do
4
4
  include_context 'Rails app pg database', "spec/fixtures/rails6_users_app" unless use_existing_data?
5
5
  include_context 'rails integration test setup'
6
6
 
7
- def run_spec(spec_name)
8
- cmd = <<~CMD.gsub "\n", ' '
9
- docker-compose run --rm -e RAILS_ENV=test -e APPMAP=true
10
- -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rspec #{spec_name}
11
- CMD
12
- run_cmd cmd, chdir: fixture_dir
13
- end
14
-
15
- def generate_swagger
16
- cmd = <<~CMD.gsub "\n", ' '
17
- docker-compose run --rm -v #{File.absolute_path tmpdir}:/app/tmp app ./bin/rake appmap:swagger
18
- CMD
19
- run_cmd cmd, chdir: fixture_dir
20
- end
21
-
22
7
  unless use_existing_data?
23
8
  before(:all) do
24
- generate_swagger
9
+ @app.run_cmd './bin/rake appmap:swagger'
25
10
  end
26
11
  end
27
12
 
data/spec/util_spec.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
  require 'appmap/util'
5
5
 
6
- describe AppMap::Util, docker: false do
6
+ describe AppMap::Util do
7
7
  describe 'scenario_filename' do
8
8
  let(:subject) { AppMap::Util.method(:scenario_filename) }
9
9
  it 'leaves short names alone' do
@@ -26,7 +26,8 @@
26
26
  "name": "arg",
27
27
  "class": "Array",
28
28
  "value": "[e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855, the document]",
29
- "kind": "rest"
29
+ "kind": "rest",
30
+ "size": 2
30
31
  }
31
32
  ],
32
33
  "receiver": {