logstash-core 5.5.3-java → 5.6.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core/logstash-core.jar +0 -0
  3. data/lib/logstash-core/version.rb +1 -1
  4. data/lib/logstash/api/commands/node.rb +2 -2
  5. data/lib/logstash/api/commands/stats.rb +2 -2
  6. data/lib/logstash/config/config_ast.rb +24 -1
  7. data/lib/logstash/config/modules_common.rb +47 -15
  8. data/lib/logstash/config/source/modules.rb +55 -0
  9. data/lib/logstash/config/string_escape.rb +27 -0
  10. data/lib/logstash/elasticsearch_client.rb +24 -2
  11. data/lib/logstash/environment.rb +2 -0
  12. data/lib/logstash/filter_delegator.rb +9 -6
  13. data/lib/logstash/instrument/collector.rb +7 -5
  14. data/lib/logstash/instrument/metric_store.rb +11 -11
  15. data/lib/logstash/instrument/namespaced_metric.rb +4 -0
  16. data/lib/logstash/instrument/namespaced_null_metric.rb +4 -0
  17. data/lib/logstash/instrument/null_metric.rb +10 -0
  18. data/lib/logstash/instrument/periodic_poller/dlq.rb +19 -0
  19. data/lib/logstash/instrument/periodic_pollers.rb +3 -1
  20. data/lib/logstash/instrument/wrapped_write_client.rb +33 -24
  21. data/lib/logstash/logging/logger.rb +26 -19
  22. data/lib/logstash/modules/{importer.rb → elasticsearch_importer.rb} +3 -3
  23. data/lib/logstash/modules/kibana_base.rb +24 -0
  24. data/lib/logstash/modules/kibana_client.rb +124 -0
  25. data/lib/logstash/modules/kibana_config.rb +29 -28
  26. data/lib/logstash/modules/kibana_dashboards.rb +36 -0
  27. data/lib/logstash/modules/kibana_importer.rb +17 -0
  28. data/lib/logstash/modules/kibana_settings.rb +40 -0
  29. data/lib/logstash/modules/logstash_config.rb +89 -17
  30. data/lib/logstash/modules/resource_base.rb +6 -5
  31. data/lib/logstash/modules/scaffold.rb +11 -3
  32. data/lib/logstash/modules/settings_merger.rb +23 -0
  33. data/lib/logstash/modules/util.rb +17 -0
  34. data/lib/logstash/output_delegator.rb +7 -5
  35. data/lib/logstash/pipeline.rb +34 -2
  36. data/lib/logstash/runner.rb +8 -13
  37. data/lib/logstash/settings.rb +20 -1
  38. data/lib/logstash/util/wrapped_acked_queue.rb +5 -24
  39. data/lib/logstash/util/wrapped_synchronous_queue.rb +14 -24
  40. data/lib/logstash/version.rb +1 -1
  41. data/locales/en.yml +11 -4
  42. data/spec/logstash/agent_spec.rb +19 -6
  43. data/spec/logstash/api/modules/node_spec.rb +2 -1
  44. data/spec/logstash/config/config_ast_spec.rb +47 -8
  45. data/spec/logstash/config/string_escape_spec.rb +24 -0
  46. data/spec/logstash/event_spec.rb +9 -0
  47. data/spec/logstash/filter_delegator_spec.rb +21 -7
  48. data/spec/logstash/instrument/periodic_poller/dlq_spec.rb +17 -0
  49. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +1 -1
  50. data/spec/logstash/legacy_ruby_event_spec.rb +4 -4
  51. data/spec/logstash/modules/logstash_config_spec.rb +56 -0
  52. data/spec/logstash/modules/scaffold_spec.rb +234 -0
  53. data/spec/logstash/output_delegator_spec.rb +15 -5
  54. data/spec/logstash/pipeline_spec.rb +76 -26
  55. data/spec/logstash/runner_spec.rb +46 -25
  56. data/spec/logstash/settings/splittable_string_array_spec.rb +51 -0
  57. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +0 -22
  58. metadata +22 -4
  59. data/lib/logstash/modules/kibana_base_resource.rb +0 -10
  60. data/lib/logstash/program.rb +0 -14
@@ -21,20 +21,10 @@ require "logstash/patches/clamp"
21
21
  require "logstash/settings"
22
22
  require "logstash/version"
23
23
  require "logstash/plugins/registry"
24
+ require "logstash/modules/util"
24
25
 
25
26
  java_import 'org.logstash.FileLockFactory'
26
27
 
27
- def register_local_modules(path)
28
- modules_path = File.join(path, File::Separator, "modules")
29
- Dir.foreach(modules_path) do |item|
30
- # Ignore unix relative path ids
31
- next if item == '.' or item == '..'
32
- # Ignore non-directories
33
- next if !File.directory?(File.join(modules_path, File::Separator, item))
34
- LogStash::PLUGIN_REGISTRY.add(:modules, item, LogStash::Modules::Scaffold.new(item, File.join(modules_path, File::Separator, item, File::Separator, "configuration")))
35
- end
36
- end
37
-
38
28
  class LogStash::Runner < Clamp::StrictCommand
39
29
  include LogStash::Util::Loggable
40
30
  # The `path.settings` and `path.logs` need to be defined in the runner instead of the `logstash-core/lib/logstash/environment.rb`
@@ -73,6 +63,11 @@ class LogStash::Runner < Clamp::StrictCommand
73
63
  :multivalued => true,
74
64
  :attribute_name => "modules_variable_list"
75
65
 
66
+ option ["--setup"], :flag,
67
+ I18n.t("logstash.runner.flag.modules_setup"),
68
+ :default => LogStash::SETTINGS.get_default("modules_setup"),
69
+ :attribute_name => "modules_setup"
70
+
76
71
  # Pipeline settings
77
72
  option ["-w", "--pipeline.workers"], "COUNT",
78
73
  I18n.t("logstash.runner.flag.pipeline-workers"),
@@ -226,7 +221,7 @@ class LogStash::Runner < Clamp::StrictCommand
226
221
  java.lang.System.setProperty("ls.log.level", setting("log.level"))
227
222
  unless java.lang.System.getProperty("log4j.configurationFile")
228
223
  log4j_config_location = ::File.join(setting("path.settings"), "log4j2.properties")
229
- LogStash::Logging::Logger::initialize("file:///" + log4j_config_location)
224
+ LogStash::Logging::Logger::reconfigure("file:///" + log4j_config_location)
230
225
  end
231
226
  # override log level that may have been introduced from a custom log4j config file
232
227
  LogStash::Logging::Logger::configure_logging(setting("log.level"))
@@ -236,7 +231,7 @@ class LogStash::Runner < Clamp::StrictCommand
236
231
  end
237
232
 
238
233
  # Add local modules to the registry before everything else
239
- register_local_modules(LogStash::Environment::LOGSTASH_HOME)
234
+ LogStash::Modules::Util.register_local_modules(LogStash::Environment::LOGSTASH_HOME)
240
235
 
241
236
  # We configure the registry and load any plugin that can register hooks
242
237
  # with logstash, this need to be done before any operation.
@@ -534,8 +534,27 @@ module LogStash
534
534
  end
535
535
  end
536
536
  end
537
- end
538
537
 
538
+ class SplittableStringArray < ArrayCoercible
539
+ DEFAULT_TOKEN = ","
540
+
541
+ def initialize(name, klass, default, strict=true, tokenizer = DEFAULT_TOKEN, &validator_proc)
542
+ @element_class = klass
543
+ @token = tokenizer
544
+ super(name, klass, default, strict, &validator_proc)
545
+ end
546
+
547
+ def coerce(value)
548
+ if value.is_a?(Array)
549
+ value
550
+ elsif value.nil?
551
+ []
552
+ else
553
+ value.split(@token).map(&:strip)
554
+ end
555
+ end
556
+ end
557
+ end
539
558
 
540
559
  SETTINGS = Settings.new
541
560
  end
@@ -57,24 +57,6 @@ module LogStash; module Util
57
57
  end
58
58
  alias_method(:<<, :push)
59
59
 
60
- # TODO - fix doc for this noop method
61
- # Offer an object to the queue, wait for the specified amount of time.
62
- # If adding to the queue was successful it will return true, false otherwise.
63
- #
64
- # @param [Object] Object to add to the queue
65
- # @param [Integer] Time in milliseconds to wait before giving up
66
- # @return [Boolean] True if adding was successful if not it return false
67
- def offer(obj, timeout_ms)
68
- raise NotImplementedError.new("The offer method is not implemented. There is no non blocking write operation yet.")
69
- end
70
-
71
- # Blocking
72
- def take
73
- check_closed("read a batch")
74
- # TODO - determine better arbitrary timeout millis
75
- @queue.read_batch(1, 200).get_elements.first
76
- end
77
-
78
60
  # Block for X millis
79
61
  def poll(millis)
80
62
  check_closed("read")
@@ -223,19 +205,18 @@ module LogStash; module Util
223
205
  end
224
206
 
225
207
  def start_clock
226
- @inflight_clocks[Thread.current] = [
227
- @event_metric.time(:duration_in_millis),
228
- @pipeline_metric.time(:duration_in_millis)
229
- ]
208
+ @inflight_clocks[Thread.current] = java.lang.System.current_time_millis
230
209
  end
231
210
 
232
211
  def stop_clock(batch)
233
212
  unless @inflight_clocks[Thread.current].nil?
234
213
  if batch.size > 0
235
- # onl/y stop (which also records) the metrics if the batch is non-empty.
214
+ # only stop (which also records) the metrics if the batch is non-empty.
236
215
  # start_clock is now called at empty batch creation and an empty batch could
237
216
  # stay empty all the way down to the close_batch call.
238
- @inflight_clocks[Thread.current].each(&:stop)
217
+ time_taken = java.lang.System.current_time_millis - @inflight_clocks[Thread.current]
218
+ @event_metric.report_time(:duration_in_millis, time_taken)
219
+ @pipeline_metric.report_time(:duration_in_millis, time_taken)
239
220
  end
240
221
  @inflight_clocks.delete(Thread.current)
241
222
  end
@@ -18,21 +18,6 @@ module LogStash; module Util
18
18
  end
19
19
  alias_method(:<<, :push)
20
20
 
21
- # Offer an object to the queue, wait for the specified amount of time.
22
- # If adding to the queue was successful it wil return true, false otherwise.
23
- #
24
- # @param [Object] Object to add to the queue
25
- # @param [Integer] Time in milliseconds to wait before giving up
26
- # @return [Boolean] True if adding was successful if not it return false
27
- def offer(obj, timeout_ms)
28
- @queue.offer(obj, timeout_ms, TimeUnit::MILLISECONDS)
29
- end
30
-
31
- # Blocking
32
- def take
33
- @queue.take
34
- end
35
-
36
21
  # Block for X millis
37
22
  def poll(millis)
38
23
  @queue.poll(millis, TimeUnit::MILLISECONDS)
@@ -83,11 +68,17 @@ module LogStash; module Util
83
68
 
84
69
  def set_events_metric(metric)
85
70
  @event_metric = metric
71
+ @event_metric_out = @event_metric.counter(:out)
72
+ @event_metric_filtered = @event_metric.counter(:filtered)
73
+ @event_metric_time = @event_metric.counter(:duration_in_millis)
86
74
  define_initial_metrics_values(@event_metric)
87
75
  end
88
76
 
89
77
  def set_pipeline_metric(metric)
90
78
  @pipeline_metric = metric
79
+ @pipeline_metric_out = @pipeline_metric.counter(:out)
80
+ @pipeline_metric_filtered = @pipeline_metric.counter(:filtered)
81
+ @pipeline_metric_time = @pipeline_metric.counter(:duration_in_millis)
91
82
  define_initial_metrics_values(@pipeline_metric)
92
83
  end
93
84
 
@@ -155,10 +146,7 @@ module LogStash; module Util
155
146
  end
156
147
 
157
148
  def start_clock
158
- @inflight_clocks[Thread.current] = [
159
- @event_metric.time(:duration_in_millis),
160
- @pipeline_metric.time(:duration_in_millis)
161
- ]
149
+ @inflight_clocks[Thread.current] = java.lang.System.current_time_millis
162
150
  end
163
151
 
164
152
  def stop_clock(batch)
@@ -167,20 +155,22 @@ module LogStash; module Util
167
155
  # only stop (which also records) the metrics if the batch is non-empty.
168
156
  # start_clock is now called at empty batch creation and an empty batch could
169
157
  # stay empty all the way down to the close_batch call.
170
- @inflight_clocks[Thread.current].each(&:stop)
158
+ time_taken = java.lang.System.current_time_millis - @inflight_clocks[Thread.current]
159
+ @event_metric_time.increment(time_taken)
160
+ @pipeline_metric_time.increment(time_taken)
171
161
  end
172
162
  @inflight_clocks.delete(Thread.current)
173
163
  end
174
164
  end
175
165
 
176
166
  def add_filtered_metrics(batch)
177
- @event_metric.increment(:filtered, batch.filtered_size)
178
- @pipeline_metric.increment(:filtered, batch.filtered_size)
167
+ @event_metric_filtered.increment(batch.filtered_size)
168
+ @pipeline_metric_filtered.increment(batch.filtered_size)
179
169
  end
180
170
 
181
171
  def add_output_metrics(batch)
182
- @event_metric.increment(:out, batch.filtered_size)
183
- @pipeline_metric.increment(:out, batch.filtered_size)
172
+ @event_metric_out.increment(batch.filtered_size)
173
+ @pipeline_metric_out.increment(batch.filtered_size)
184
174
  end
185
175
  end
186
176
 
@@ -11,4 +11,4 @@
11
11
  # eventually this file should be in the root logstash lib fir and dependencies in logstash-core should be
12
12
  # fixed.
13
13
 
14
- LOGSTASH_VERSION = "5.5.3"
14
+ LOGSTASH_VERSION = "5.6.0"
@@ -100,8 +100,10 @@ en:
100
100
  Specified modules: %{specified_modules}
101
101
  Available modules: %{available_modules}
102
102
  elasticsearch_connection_failed: >-
103
- Failed to import module configurations to Elasticsearch.
104
- Module: %{module_name} has hosts: %{hosts}
103
+ Failed to import module configurations to Elasticsearch and/or Kibana.
104
+ Module: %{module_name} has Elasticsearch hosts: %{elasticsearch_hosts} and Kibana hosts: %{kibana_hosts}
105
+ modules-too-many-specified: >-
106
+ Too many modules specified. Maximum allowed: %{max}, specified: %{specified_modules}
105
107
 
106
108
  runner:
107
109
  short-help: |-
@@ -120,10 +122,11 @@ en:
120
122
  config-module-exclusive: >-
121
123
  Settings 'path.config' (-f) or 'config.string' (-e) can't be used in conjunction with
122
124
  (--modules) or the "modules:" block in the logstash.yml file.
125
+ reload-with-modules: >-
126
+ Configuration reloading can't be used with command-line or logstash.yml specified modules.
123
127
  cli-module-override: >-
124
128
  Both command-line and logstash.yml modules configurations detected.
125
- Using command-line module configuration and ignoring logstash.yml module
126
- configuration.
129
+ Using command-line module configuration to override logstash.yml module configuration.
127
130
  reload-without-config-path: >-
128
131
  Configuration reloading also requires passing a configuration path with '-f yourlogstash.conf'
129
132
  locked-data-path: >-
@@ -227,6 +230,10 @@ en:
227
230
  '-M "MODULE_NAME.var.PLUGIN_TYPE.PLUGIN_NAME.VARIABLE_NAME=VALUE"'
228
231
  as in
229
232
  '-M "example.var.filter.mutate.fieldname=fieldvalue"'
233
+ modules_setup: |+
234
+ Load index template into Elasticsearch, and saved searches,
235
+ index-pattern, visualizations, and dashboards into Kibana when
236
+ running modules.
230
237
  configtest: |+
231
238
  Check configuration for valid syntax and then exit.
232
239
  http_host: Web API binding host
@@ -5,6 +5,7 @@ require "logstash/inputs/generator"
5
5
  require_relative "../support/mocks_classes"
6
6
  require "fileutils"
7
7
  require_relative "../support/helpers"
8
+ require 'timeout'
8
9
 
9
10
  describe LogStash::Agent do
10
11
 
@@ -16,6 +17,7 @@ describe LogStash::Agent do
16
17
  let(:config_file) { Stud::Temporary.pathname }
17
18
  let(:config_file_txt) { "input { generator { count => 100000 } } output { }" }
18
19
  let(:logger) { double("logger") }
20
+ let(:timeout) {120} #seconds
19
21
 
20
22
  subject { LogStash::Agent.new(agent_settings) }
21
23
 
@@ -151,7 +153,9 @@ describe LogStash::Agent do
151
153
 
152
154
  it "does not try to reload the pipeline" do
153
155
  t = Thread.new { subject.execute }
154
- sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
156
+ Timeout.timeout(timeout) do
157
+ sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
158
+ end
155
159
  expect(subject).to_not receive(:reload_pipeline!)
156
160
  File.open(config_file, "w") { |f| f.puts second_pipeline_config }
157
161
  subject.reload_state!
@@ -183,7 +187,9 @@ describe LogStash::Agent do
183
187
 
184
188
  it "tries to reload the pipeline" do
185
189
  t = Thread.new { subject.execute }
186
- sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
190
+ Timeout.timeout(timeout) do
191
+ sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
192
+ end
187
193
  expect(subject).to receive(:reload_pipeline!).once.and_call_original
188
194
  File.open(config_file, "w") { |f| f.puts second_pipeline_config }
189
195
  subject.reload_state!
@@ -213,8 +219,9 @@ describe LogStash::Agent do
213
219
  it "should periodically reload_state" do
214
220
  allow(subject).to receive(:clean_state?).and_return(false)
215
221
  t = Thread.new { subject.execute }
216
- sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
217
-
222
+ Timeout.timeout(timeout) do
223
+ sleep(0.01) until subject.running_pipelines? && subject.pipelines.values.first.running?
224
+ end
218
225
  expect(subject).to receive(:reload_state!).at_least(2).times
219
226
 
220
227
  sleep 1
@@ -451,7 +458,9 @@ describe LogStash::Agent do
451
458
  pipeline_thread
452
459
 
453
460
  # wait for some events to reach the dummy_output
454
- sleep(0.1) until dummy_output.events_received > initial_generator_threshold
461
+ Timeout.timeout(timeout) do
462
+ sleep(0.1) until dummy_output.events_received > initial_generator_threshold
463
+ end
455
464
  end
456
465
 
457
466
  after :each do
@@ -459,6 +468,8 @@ describe LogStash::Agent do
459
468
  subject.shutdown
460
469
  Stud.stop!(pipeline_thread)
461
470
  pipeline_thread.join
471
+ rescue
472
+ #don't care about errors here.
462
473
  ensure
463
474
  Thread.abort_on_exception = @abort_on_exception
464
475
  end
@@ -477,7 +488,9 @@ describe LogStash::Agent do
477
488
  subject.send(:"reload_pipeline!", "main")
478
489
 
479
490
  # wait until pipeline restarts
480
- sleep(0.01) until dummy_output2.events_received > 0
491
+ Timeout.timeout(timeout) do
492
+ sleep(0.01) until dummy_output2.events_received > 0
493
+ end
481
494
  end
482
495
 
483
496
  it "resets the pipeline metric collector" do
@@ -114,7 +114,8 @@ describe LogStash::Api::Modules::Node do
114
114
  "batch_size" => Numeric,
115
115
  "batch_delay" => Numeric,
116
116
  "config_reload_automatic" => Boolean,
117
- "config_reload_interval" => Numeric
117
+ "config_reload_interval" => Numeric,
118
+ "dead_letter_queue_enabled" => Boolean
118
119
  },
119
120
  "os" => {
120
121
  "name" => String,
@@ -6,6 +6,8 @@ require "logstash/config/grammar"
6
6
  require "logstash/config/config_ast"
7
7
 
8
8
  describe LogStashConfigParser do
9
+ let(:settings) { mock_settings({}) }
10
+
9
11
  context '#parse' do
10
12
  context "valid configuration" do
11
13
  it "should permit single-quoted attribute names" do
@@ -77,7 +79,7 @@ describe LogStashConfigParser do
77
79
  }
78
80
  CONFIG
79
81
  subject { LogStashConfigParser.new }
80
-
82
+
81
83
  it "should compile successfully" do
82
84
  result = subject.parse(config)
83
85
  expect(result).not_to(be_nil)
@@ -142,12 +144,50 @@ describe LogStashConfigParser do
142
144
  expect(config).to be_nil
143
145
  end
144
146
  end
147
+
148
+ context "when config.support_escapes" do
149
+ let(:parser) { LogStashConfigParser.new }
150
+
151
+ let(:processed_value) { 'The computer says, "No"' }
152
+
153
+ let(:config) {
154
+ parser.parse(%q(
155
+ input {
156
+ foo {
157
+ bar => "The computer says, \"No\""
158
+ }
159
+ }
160
+ ))
161
+ }
162
+
163
+ let(:compiled_string) { eval(config.recursive_select(LogStash::Config::AST::String).first.compile) }
164
+
165
+ before do
166
+ config.process_escape_sequences = escapes
167
+ end
168
+
169
+ context "is enabled" do
170
+ let(:escapes) { true }
171
+
172
+ it "should process escape sequences" do
173
+ expect(compiled_string).to be == processed_value
174
+ end
175
+ end
176
+
177
+ context "is false" do
178
+ let(:escapes) { false }
179
+
180
+ it "should not process escape sequences" do
181
+ expect(compiled_string).not_to be == processed_value
182
+ end
183
+ end
184
+ end
145
185
  end
146
186
 
147
187
  context "when using two plugin sections of the same type" do
148
188
  let(:pipeline_klass) do
149
189
  Class.new do
150
- def initialize(config)
190
+ def initialize(config, settings)
151
191
  grammar = LogStashConfigParser.new
152
192
  @config = grammar.parse(config)
153
193
  @code = @config.compile
@@ -166,7 +206,7 @@ describe LogStashConfigParser do
166
206
 
167
207
 
168
208
  it "should create a pipeline with both sections" do
169
- generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
209
+ generated_objects = pipeline_klass.new(config_string, settings).instance_variable_get("@generated_objects")
170
210
  filters = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^filter.+?_\d+$/) }
171
211
  expect(filters.size).to eq(2)
172
212
  end
@@ -181,14 +221,13 @@ describe LogStashConfigParser do
181
221
 
182
222
 
183
223
  it "should create a pipeline with both sections" do
184
- generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
224
+ generated_objects = pipeline_klass.new(config_string, settings).instance_variable_get("@generated_objects")
185
225
  outputs = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^output.+?_\d+$/) }
186
226
  expect(outputs.size).to eq(2)
187
227
  end
188
228
  end
189
229
  end
190
230
  context "when creating two instances of the same configuration" do
191
-
192
231
  let(:config_string) {
193
232
  "input { generator { } }
194
233
  filter {
@@ -201,7 +240,7 @@ describe LogStashConfigParser do
201
240
 
202
241
  let(:pipeline_klass) do
203
242
  Class.new do
204
- def initialize(config)
243
+ def initialize(config, settings)
205
244
  grammar = LogStashConfigParser.new
206
245
  @config = grammar.parse(config)
207
246
  @code = @config.compile
@@ -213,8 +252,8 @@ describe LogStashConfigParser do
213
252
 
214
253
  describe "generated conditional functionals" do
215
254
  it "should be created per instance" do
216
- instance_1 = pipeline_klass.new(config_string)
217
- instance_2 = pipeline_klass.new(config_string)
255
+ instance_1 = pipeline_klass.new(config_string, settings)
256
+ instance_2 = pipeline_klass.new(config_string, settings)
218
257
  generated_method_1 = instance_1.instance_variable_get("@generated_objects")[:cond_func_1]
219
258
  generated_method_2 = instance_2.instance_variable_get("@generated_objects")[:cond_func_1]
220
259
  expect(generated_method_1).to_not be(generated_method_2)