From 78f70634ed92a9d27391873c21b0a09f98b0119d Mon Sep 17 00:00:00 2001 From: Andrew Cholakian Date: Wed, 17 May 2017 16:36:06 -0500 Subject: [PATCH] Refactor API specs to play well with others This is a big chang, it: 1. Moves API specs out of their special hierarchy 2. Removes the API spec spec_helper 3. Reactivates that stats command spec (that was accidentally not being run before due to it not having _spec as a suffix This was required to fix the preceeding commit, where we added a before(:each) hook to the spec_helper that wasn't being picked up in some cases due to the existence of two spec helpers and a $LOAD_PATH that could change. Fixes #7132 --- logstash-core/spec/api/spec_helper.rb | 106 ------------------ .../api/commands/stats_spec.rb} | 9 +- .../{api/lib => logstash/api}/errors_spec.rb | 2 +- .../api/modules}/logging_spec.rb | 11 +- .../api/modules}/node_plugins_spec.rb | 3 +- .../api => logstash/api/modules}/node_spec.rb | 3 +- .../api/modules}/node_stats_spec.rb | 4 +- .../api/modules}/plugins_spec.rb | 7 +- .../api => logstash/api/modules}/root_spec.rb | 4 +- .../lib => logstash/api}/rack_app_spec.rb | 0 logstash-core/spec/support/helpers.rb | 12 +- logstash-core/spec/support/shared_contexts.rb | 21 ++++ spec/spec_helper.rb | 14 +++ .../support/resource_dsl_methods.rb | 7 +- 14 files changed, 68 insertions(+), 135 deletions(-) delete mode 100644 logstash-core/spec/api/spec_helper.rb rename logstash-core/spec/{api/lib/commands/stats.rb => logstash/api/commands/stats_spec.rb} (82%) rename logstash-core/spec/{api/lib => logstash/api}/errors_spec.rb (94%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/logging_spec.rb (84%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/node_plugins_spec.rb (88%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/node_spec.rb (97%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/node_stats_spec.rb (96%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/plugins_spec.rb (90%) rename logstash-core/spec/{api/lib/api => logstash/api/modules}/root_spec.rb (77%) rename logstash-core/spec/{api/lib => logstash/api}/rack_app_spec.rb (100%) rename {logstash-core/spec/api/lib/api => spec}/support/resource_dsl_methods.rb (88%) diff --git a/logstash-core/spec/api/spec_helper.rb b/logstash-core/spec/api/spec_helper.rb deleted file mode 100644 index 0f0ef192c95..00000000000 --- a/logstash-core/spec/api/spec_helper.rb +++ /dev/null @@ -1,106 +0,0 @@ -# encoding: utf-8 -API_ROOT = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "logstash", "api")) - -require "stud/task" -require "logstash/devutils/rspec/spec_helper" -$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) -require "lib/api/support/resource_dsl_methods" -require_relative "../support/mocks_classes" -require_relative "../support/helpers" -require 'rspec/expectations' -require "logstash/settings" -require 'rack/test' -require 'rspec' -require "json" - -def read_fixture(name) - path = File.join(File.dirname(__FILE__), "fixtures", name) - File.read(path) -end - -module LogStash - class DummyAgent < Agent - def start_webserver - http_address = "#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORTS.first}" - @webserver = Struct.new(:address).new(http_address) - self.metric.gauge([], :http_address, http_address) - end - - def stop_webserver; end - end -end - -## -# Class used to wrap and manage the execution of an agent for test, -# this helps a lot in order to have a more integrated test for the -# web api, could be also used for other use cases if generalized enough -## -class LogStashRunner - - attr_reader :config_str, :agent, :pipeline_settings - - def initialize - - require "securerandom" - id = SecureRandom.uuid - - @config_str = "input { generator {id => 'api-generator-pipeline-#{id}' count => 100 } } output { dummyoutput {} }" - - args = { - "config.reload.automatic" => false, - "metric.collect" => true, - "log.level" => "debug", - "node.name" => "test_agent", - "http.port" => rand(9600..9700), - "http.environment" => "test", - "config.string" => @config_str, - "pipeline.batch.size" => 1, - "pipeline.workers" => 1 - } - - @settings = ::LogStash::SETTINGS.clone.merge(args) - source_loader = LogStash::Config::SourceLoader.new - source_loader.configure_sources(LogStash::Config::Source::Local.new(@settings)) - @agent = LogStash::DummyAgent.new(@settings, source_loader) - end - - def start - # We start a pipeline that will generate a finite number of events - # before starting the expectations - @agent_task = Stud::Task.new { agent.execute } - @agent_task.wait - end - - def stop - agent.shutdown - end -end - -RSpec::Matchers.define :be_available? do - match do |plugin| - begin - Gem::Specification.find_by_name(plugin["name"]) - true - rescue - false - end - end -end - -shared_context "api setup" do - before :all do - clear_data_dir - @runner = LogStashRunner.new - @runner.start - end - - after :all do - @runner.stop - end - - include Rack::Test::Methods - - def app() - described_class.new(nil, @runner.agent) - end -end diff --git a/logstash-core/spec/api/lib/commands/stats.rb b/logstash-core/spec/logstash/api/commands/stats_spec.rb similarity index 82% rename from logstash-core/spec/api/lib/commands/stats.rb rename to logstash-core/spec/logstash/api/commands/stats_spec.rb index 2efdb6c4241..62335fb1e14 100644 --- a/logstash-core/spec/api/lib/commands/stats.rb +++ b/logstash-core/spec/logstash/api/commands/stats_spec.rb @@ -1,10 +1,15 @@ # encoding: utf-8 -require_relative "../../spec_helper" +require "spec_helper" describe LogStash::Api::Commands::Stats do + include_context "api setup" let(:report_method) { :run } - subject(:report) { report_class.new.send(report_method) } + subject(:report) do + factory = ::LogStash::Api::CommandFactory.new(LogStash::Api::Service.new(@agent)) + + factory.build(:stats).send(report_method) + end let(:report_class) { described_class } diff --git a/logstash-core/spec/api/lib/errors_spec.rb b/logstash-core/spec/logstash/api/errors_spec.rb similarity index 94% rename from logstash-core/spec/api/lib/errors_spec.rb rename to logstash-core/spec/logstash/api/errors_spec.rb index 430671402d0..49e6e1462c2 100644 --- a/logstash-core/spec/api/lib/errors_spec.rb +++ b/logstash-core/spec/logstash/api/errors_spec.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require_relative "../spec_helper" +require "spec_helper" require "logstash/api/errors" describe LogStash::Api::ApiError do diff --git a/logstash-core/spec/api/lib/api/logging_spec.rb b/logstash-core/spec/logstash/api/modules/logging_spec.rb similarity index 84% rename from logstash-core/spec/api/lib/api/logging_spec.rb rename to logstash-core/spec/logstash/api/modules/logging_spec.rb index 214a2ad69f2..952cdf872a6 100644 --- a/logstash-core/spec/api/lib/api/logging_spec.rb +++ b/logstash-core/spec/logstash/api/modules/logging_spec.rb @@ -1,5 +1,5 @@ # encoding: utf-8 -require_relative "../../spec_helper" +require "spec_helper" require "sinatra" require "logstash/api/modules/logging" require "logstash/json" @@ -10,15 +10,6 @@ describe "#logging" do context "when setting a logger's log level" do - before(:all) do - @runner = LogStashRunner.new - @runner.start - end - - after(:all) do - @runner.stop - end - it "should return a positive acknowledgement on success" do put '/', '{"logger.logstash": "ERROR"}' payload = LogStash::Json.load(last_response.body) diff --git a/logstash-core/spec/api/lib/api/node_plugins_spec.rb b/logstash-core/spec/logstash/api/modules/node_plugins_spec.rb similarity index 88% rename from logstash-core/spec/api/lib/api/node_plugins_spec.rb rename to logstash-core/spec/logstash/api/modules/node_plugins_spec.rb index 79094ed4707..4cfb30e5eb5 100644 --- a/logstash-core/spec/api/lib/api/node_plugins_spec.rb +++ b/logstash-core/spec/logstash/api/modules/node_plugins_spec.rb @@ -1,6 +1,5 @@ # encoding: utf-8 -require_relative "../../../support/shared_examples" -require_relative "../../spec_helper" +require "spec_helper" require "sinatra" require "logstash/api/modules/plugins" require "logstash/json" diff --git a/logstash-core/spec/api/lib/api/node_spec.rb b/logstash-core/spec/logstash/api/modules/node_spec.rb similarity index 97% rename from logstash-core/spec/api/lib/api/node_spec.rb rename to logstash-core/spec/logstash/api/modules/node_spec.rb index e818e0f42f8..9d2daa2c9ef 100644 --- a/logstash-core/spec/api/lib/api/node_spec.rb +++ b/logstash-core/spec/logstash/api/modules/node_spec.rb @@ -1,6 +1,5 @@ # encoding: utf-8 -require_relative "../../spec_helper" -require_relative "../../../support/shared_examples" +require "spec_helper" require "sinatra" require "logstash/api/modules/node" require "logstash/json" diff --git a/logstash-core/spec/api/lib/api/node_stats_spec.rb b/logstash-core/spec/logstash/api/modules/node_stats_spec.rb similarity index 96% rename from logstash-core/spec/api/lib/api/node_stats_spec.rb rename to logstash-core/spec/logstash/api/modules/node_stats_spec.rb index a4eae4d5aa3..2250e885e1a 100644 --- a/logstash-core/spec/api/lib/api/node_stats_spec.rb +++ b/logstash-core/spec/logstash/api/modules/node_stats_spec.rb @@ -1,6 +1,6 @@ # encoding: utf-8 -require_relative "../../spec_helper" -require_relative "../../../support/shared_examples" +require "spec_helper" + require "sinatra" require "logstash/api/modules/node_stats" require "logstash/json" diff --git a/logstash-core/spec/api/lib/api/plugins_spec.rb b/logstash-core/spec/logstash/api/modules/plugins_spec.rb similarity index 90% rename from logstash-core/spec/api/lib/api/plugins_spec.rb rename to logstash-core/spec/logstash/api/modules/plugins_spec.rb index ee554dae22f..506633a1455 100644 --- a/logstash-core/spec/api/lib/api/plugins_spec.rb +++ b/logstash-core/spec/logstash/api/modules/plugins_spec.rb @@ -1,6 +1,5 @@ # encoding: utf-8 -require_relative "../../spec_helper" -require_relative "../../../support/shared_examples" +require "spec_helper" require "sinatra" require "logstash/api/modules/plugins" require "logstash/json" @@ -40,7 +39,9 @@ it "return a list of available plugins" do payload["plugins"].each do |plugin| - expect(plugin).to be_available? + expect do + Gem::Specification.find_by_name(plugin["name"]) + end.not_to raise_error end end diff --git a/logstash-core/spec/api/lib/api/root_spec.rb b/logstash-core/spec/logstash/api/modules/root_spec.rb similarity index 77% rename from logstash-core/spec/api/lib/api/root_spec.rb rename to logstash-core/spec/logstash/api/modules/root_spec.rb index 696ce6dc693..88cac6d4026 100644 --- a/logstash-core/spec/api/lib/api/root_spec.rb +++ b/logstash-core/spec/logstash/api/modules/root_spec.rb @@ -1,6 +1,6 @@ # encoding: utf-8 -require_relative "../../spec_helper" -require_relative "../../../support/shared_examples" +require "spec_helper" + require "sinatra" require "logstash/api/modules/root" require "logstash/json" diff --git a/logstash-core/spec/api/lib/rack_app_spec.rb b/logstash-core/spec/logstash/api/rack_app_spec.rb similarity index 100% rename from logstash-core/spec/api/lib/rack_app_spec.rb rename to logstash-core/spec/logstash/api/rack_app_spec.rb diff --git a/logstash-core/spec/support/helpers.rb b/logstash-core/spec/support/helpers.rb index 4426b97256a..589a1299c1b 100644 --- a/logstash-core/spec/support/helpers.rb +++ b/logstash-core/spec/support/helpers.rb @@ -22,7 +22,7 @@ def clear_data_dir end end -def mock_settings(settings_values) +def mock_settings(settings_values={}) settings = LogStash::SETTINGS.clone settings_values.each do |key, value| @@ -32,6 +32,14 @@ def mock_settings(settings_values) settings end +def make_test_agent(settings=mock_settings) + sl = LogStash::Config::SourceLoader.new + sl.add_source(LogStash::Config::Source::Local.new(settings)) + sl + + ::LogStash::Agent.new(settings, sl) +end + def mock_pipeline(pipeline_id, reloadable = true, config_hash = nil) config_string = "input { stdin { id => '#{pipeline_id}' }}" settings = mock_settings("pipeline.id" => pipeline_id.to_s, @@ -90,4 +98,4 @@ def temporary_file(content, file_name = Time.now.to_i.to_s, directory = Stud::Te end end -SUPPORT_DIR = Pathname.new(::File.join(::File.dirname(__FILE__), "support")) +SUPPORT_DIR = Pathname.new(::File.join(::File.dirname(__FILE__), "support")) \ No newline at end of file diff --git a/logstash-core/spec/support/shared_contexts.rb b/logstash-core/spec/support/shared_contexts.rb index 2fd922005a7..85e985eb5a8 100644 --- a/logstash-core/spec/support/shared_contexts.rb +++ b/logstash-core/spec/support/shared_contexts.rb @@ -14,3 +14,24 @@ allow(pipeline).to receive(:agent).and_return(agent) end end + +shared_context "api setup" do + before :all do + clear_data_dir + settings = mock_settings + config_string = "input { generator {id => 'api-generator-pipeline' count => 100 } } output { dummyoutput {} }" + settings.set("config.string", config_string) + @agent = make_test_agent(settings) + @agent.execute + end + + after :all do + @agent.shutdown + end + + include Rack::Test::Methods + + def app() + described_class.new(nil, @agent) + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 122ba5367cd..0feef2287b1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -9,6 +9,19 @@ require "flores/rspec" require "flores/random" require "pathname" +require "stud/task" +require "logstash/devutils/rspec/spec_helper" +require "support/resource_dsl_methods" +require "support/mocks_classes" +require "support/helpers" +require "support/shared_contexts" +require "support/shared_examples" +require 'rspec/expectations' +require "logstash/settings" +require 'rack/test' +require 'rspec' +require "json" + class JSONIOThingy < IO def initialize; end @@ -53,3 +66,4 @@ def puts(payload) def installed_plugins Gem::Specification.find_all.select { |spec| spec.metadata["logstash_plugin"] }.map { |plugin| plugin.name } end + diff --git a/logstash-core/spec/api/lib/api/support/resource_dsl_methods.rb b/spec/support/resource_dsl_methods.rb similarity index 88% rename from logstash-core/spec/api/lib/api/support/resource_dsl_methods.rb rename to spec/support/resource_dsl_methods.rb index c5ec25d5aa0..9d9b7275576 100644 --- a/logstash-core/spec/api/lib/api/support/resource_dsl_methods.rb +++ b/spec/support/resource_dsl_methods.rb @@ -45,15 +45,15 @@ def test_api(expected, path) end it "should include the http address" do - expect(payload["http_address"]).to eql("#{Socket.gethostname}:#{::LogStash::WebServer::DEFAULT_PORTS.first}") + expect(payload["http_address"]).to eql("127.0.0.1:#{::LogStash::WebServer::DEFAULT_PORTS.first}") end it "should include the node name" do - expect(payload["name"]).to eql(@runner.agent.name) + expect(payload["name"]).to eql(@agent.name) end it "should include the node id" do - expect(payload["id"]).to eql(@runner.agent.id) + expect(payload["id"]).to eql(@agent.id) end end @@ -63,6 +63,7 @@ def test_api(expected, path) it "should set '#{dotted}' at '#{path}' to be a '#{klass}'" do expect(last_response).to be_ok # fail early if need be resource_path_value = resource_path.reduce(payload) do |acc,v| + expect(acc).to be_a(Hash), "Got a nil looking for #{resource_path} in #{payload}" expect(acc.has_key?(v)).to eql(true), "Expected to find value '#{v}' in structure '#{acc}', but could not. Payload was '#{payload}'" acc[v] end