[DRE-commits] [ruby-aruba] 24/98: Make sure that environment variables set by external libraries are taken into account

Hideki Yamane henrich at moszumanska.debian.org
Tue Mar 22 12:20:35 UTC 2016


This is an automated email from the git hooks/post-receive script.

henrich pushed a commit to branch debian/sid
in repository ruby-aruba.

commit bc0f98be6d68f7ef6119a5a0f6849601b58d5faa
Author: Dennis Günnewig <dev at fedux.org>
Date:   Sat Nov 28 09:18:32 2015 +0100

    Make sure that environment variables set by external libraries are taken
    into account
---
 ...feature => delete_environment_variable.feature} |   2 +-
 .../environment/set_environment_variable.feature   |  68 ++++++++++
 .../command_runtime_environment.feature            | 129 +++++++++++++++++++
 lib/aruba/api/command.rb                           |   5 +-
 lib/aruba/api/core.rb                              |   2 +
 lib/aruba/config.rb                                |   2 +-
 lib/aruba/cucumber/hooks.rb                        |   3 -
 lib/aruba/platforms/unix_environment_variables.rb  | 143 ++++++++++++++++-----
 lib/aruba/platforms/unix_platform.rb               |   2 +-
 .../platforms/windows_environment_variables.rb     |   6 +-
 lib/aruba/platforms/windows_platform.rb            |   2 +-
 lib/aruba/rspec.rb                                 |   5 +-
 lib/aruba/runtime.rb                               |   9 +-
 13 files changed, 327 insertions(+), 51 deletions(-)

diff --git a/features/api/environment/remove_environment_variable.feature b/features/api/environment/delete_environment_variable.feature
similarity index 96%
rename from features/api/environment/remove_environment_variable.feature
rename to features/api/environment/delete_environment_variable.feature
index 752a208..657c43d 100644
--- a/features/api/environment/remove_environment_variable.feature
+++ b/features/api/environment/delete_environment_variable.feature
@@ -1,4 +1,4 @@
-Feature: Remove existing environment variable via API-method
+Feature: Delete existing environment variable via API-method
 
   It is quite handy to modify the environment of a process. To make this
   possible, `aruba` provides several methods. One of these is
diff --git a/features/api/environment/set_environment_variable.feature b/features/api/environment/set_environment_variable.feature
index ca50daa..a09eff0 100644
--- a/features/api/environment/set_environment_variable.feature
+++ b/features/api/environment/set_environment_variable.feature
@@ -69,6 +69,46 @@ Feature: Set environment variable via API-method
     When I run `rspec`
     Then the specs should all pass
 
+  Scenario: Set variable via ENV
+
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { ENV['REALLY_LONG_LONG_VARIABLE'] = '2' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'REALLY_LONG_LONG_VARIABLE=2' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Existing variable set in before block in RSpec
+
+    Setting environment variables with `#set_environment_variable('VAR', 'value')` takes
+    precedence before setting variables with `ENV['VAR'] = 'value'`.
+
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { set_environment_variable 'REALLY_LONG_LONG_VARIABLE', '1' }
+      before(:each) { ENV['REALLY_LONG_LONG_VARIABLE'] = '2' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'REALLY_LONG_LONG_VARIABLE=1' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
   Scenario: Run some ruby code in code with previously set environment
 
     The `#with_environment`-block makes the change environment temporary
@@ -304,3 +344,31 @@ Feature: Set environment variable via API-method
     """
     When I run `rspec`
     Then the specs should all pass
+
+  Scenario: External ruby file / ruby gem modifying ENV
+
+    There are some Rubygems around which need to modify ENV['NODE_PATH'] like
+    [`ruby-stylus`](https://github.com/forgecrafted/ruby-stylus/blob/e7293362dc8cbf550f7c317d721ba6b9087e8833/lib/stylus.rb#L168).
+    This is supported by aruba as well.
+
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) do
+        require_relative File.expand_path('../../lib/my_library.rb', __FILE__)
+      end
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'LONG_LONG_VARIABLE=1' }
+    end
+    """
+    And a file named "lib/my_library.rb" with:
+    """
+    ENV['LONG_LONG_VARIABLE'] = '1'
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/features/configuration/command_runtime_environment.feature b/features/configuration/command_runtime_environment.feature
new file mode 100644
index 0000000..fc90abd
--- /dev/null
+++ b/features/configuration/command_runtime_environment.feature
@@ -0,0 +1,129 @@
+Feature: Define default process environment
+  Say you want to have a default set of environment variables, then use this
+  code.
+
+  ~~~ruby
+  Aruba.configure do |config|
+    config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' }
+  end
+  ~~~
+
+  This can be changed via `#set_environment_variable`,
+  `#append_environment_variable`, `#delete_environment_variable` or
+  `#prepend_environment_variable`.
+
+  Background:
+    Given I use the fixture "cli-app"
+
+  Scenario: Overwrite existing variable with new default value
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    ENV['LONG_LONG_VARIABLE'] = 'y'
+
+    Aruba.configure do |config|
+      config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' } 
+    end
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'LONG_LONG_VARIABLE=x' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Overwrite default value for variable
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    ENV['LONG_LONG_VARIABLE'] = 'y'
+
+    Aruba.configure do |config|
+      config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' } 
+    end
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { set_environment_variable 'LONG_LONG_VARIABLE', 'z' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'LONG_LONG_VARIABLE=z' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Append value to default value
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    ENV['LONG_LONG_VARIABLE'] = 'y'
+
+    Aruba.configure do |config|
+      config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' } 
+    end
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { append_environment_variable 'LONG_LONG_VARIABLE', 'z' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'LONG_LONG_VARIABLE=xz' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Prepend value
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    ENV['LONG_LONG_VARIABLE'] = 'y'
+
+    Aruba.configure do |config|
+      config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' } 
+    end
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { prepend_environment_variable 'LONG_LONG_VARIABLE', 'z' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).to include 'LONG_LONG_VARIABLE=zx' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Remove variable from default set of variables
+    Given a file named "spec/environment_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    ENV['LONG_LONG_VARIABLE'] = 'y'
+
+    Aruba.configure do |config|
+      config.command_runtime_environment = { 'LONG_LONG_VARIABLE' => 'x' } 
+    end
+
+    RSpec.describe 'Environment command', :type => :aruba do
+      before(:each) { delete_environment_variable 'LONG_LONG_VARIABLE' }
+
+      before(:each) { run('env') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started.output).not_to include 'LONG_LONG_VARIABLE' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/lib/aruba/api/command.rb b/lib/aruba/api/command.rb
index 40aaa79..9320b68 100644
--- a/lib/aruba/api/command.rb
+++ b/lib/aruba/api/command.rb
@@ -164,7 +164,7 @@ module Aruba
         @commands ||= []
         @commands << cmd
 
-        environment       = aruba.environment.to_h
+        environment       = aruba.environment
         working_directory = expand_path('.')
         event_bus         = aruba.event_bus
 
@@ -202,7 +202,7 @@ module Aruba
           :exit_timeout      => exit_timeout,
           :io_wait_timeout   => io_wait_timeout,
           :working_directory => working_directory,
-          :environment       => environment,
+          :environment       => environment.to_hash,
           :main_class        => main_class,
           :stop_signal       => stop_signal,
           :startup_wait_time => startup_wait_time,
@@ -217,6 +217,7 @@ module Aruba
         end
 
         aruba.config.before(:command, self, command)
+
         command.start
 
         aruba.announcer.announce(:stop_signal, command.pid, stop_signal) if stop_signal
diff --git a/lib/aruba/api/core.rb b/lib/aruba/api/core.rb
index da74f13..a24c60f 100644
--- a/lib/aruba/api/core.rb
+++ b/lib/aruba/api/core.rb
@@ -179,8 +179,10 @@ module Aruba
       def with_environment(env = {}, &block)
         old_aruba_env = aruba.environment.to_h
 
+        # make sure the old environment is really restored in "ENV"
         Aruba.platform.with_environment aruba.environment.update(env).to_h, &block
       ensure
+        # make sure the old environment is really restored in "aruba.environment"
         aruba.environment.clear
         aruba.environment.update old_aruba_env
       end
diff --git a/lib/aruba/config.rb b/lib/aruba/config.rb
index caef3e5..493fc07 100644
--- a/lib/aruba/config.rb
+++ b/lib/aruba/config.rb
@@ -36,7 +36,7 @@ module Aruba
     option_accessor :io_wait_timeout, :contract => { Num => Num }, :default => 0.1
     option_accessor :startup_wait_time, :contract => { Num => Num }, :default => 0
     option_accessor :fixtures_directories, :contract => { Array => ArrayOf[String] }, :default => %w(features/fixtures spec/fixtures test/fixtures fixtures)
-    option_accessor :command_runtime_environment, :contract => { Hash => Hash }, :default => ENV.to_hash.dup
+    option_accessor :command_runtime_environment, :contract => { Hash => Hash }, :default => ENV.to_hash
     # rubocop:disable Metrics/LineLength
     option_accessor(:command_search_paths, :contract => { ArrayOf[String] => ArrayOf[String] }) { |config| [File.join(config.root_directory.value, 'bin')] }
     # rubocop:enable Metrics/LineLength
diff --git a/lib/aruba/cucumber/hooks.rb b/lib/aruba/cucumber/hooks.rb
index 8be15d1..7fd739e 100644
--- a/lib/aruba/cucumber/hooks.rb
+++ b/lib/aruba/cucumber/hooks.rb
@@ -10,9 +10,6 @@ if Aruba::VERSION >= '1.0.0'
 end
 
 Before do
-  # this is ENV by default ...
-  aruba.environment.update aruba.config.command_runtime_environment
-
   # ... so every change needs to be done later
   prepend_environment_variable 'PATH', aruba.config.command_search_paths.join(':') + ':'
   set_environment_variable 'HOME', aruba.config.home_directory
diff --git a/lib/aruba/platforms/unix_environment_variables.rb b/lib/aruba/platforms/unix_environment_variables.rb
index e619af2..4d20471 100644
--- a/lib/aruba/platforms/unix_environment_variables.rb
+++ b/lib/aruba/platforms/unix_environment_variables.rb
@@ -4,17 +4,69 @@ module Aruba
   module Platforms
     # Abstract environment variables
     class UnixEnvironmentVariables
+      # Update environment
+      class UpdateAction
+        attr_reader :other_env, :block
+
+        def initialize(other_env, &block)
+          @other_env = other_env
+
+          if RUBY_VERSION <= '1.9.3'
+            # rubocop:disable Style/EachWithObject
+            @other_env = @other_env.to_hash.inject({}) { |a, (k, v)| a[k] = v.to_s; a }
+            # rubocop:enable Style/EachWithObject
+          else
+            @other_env = @other_env.to_h.each_with_object({}) { |(k, v), a| a[k] = v.to_s }
+          end
+
+          if block_given?
+            @block     = block
+          else
+            @block     = nil
+          end
+        end
+
+        def call(env)
+          if block
+            env.update(other_env, &block)
+          else
+            env.update(other_env)
+          end
+        end
+      end
+
+      # Remove variables from environment
+      class RemoveAction
+        attr_reader :variables
+
+        def initialize(variables)
+          @variables = Array(variables)
+        end
+
+        def call(env)
+          variables.each { |v| env.delete v }
+
+          env
+        end
+      end
+
       # We need to use this, because `nil` is a valid value as default
       UNDEFINED = Object.new.freeze
 
       private
 
-      attr_reader :env
+      attr_reader :actions, :env
 
       public
 
-      def initialize(env = ENV.to_hash)
-        @env = Marshal.load(Marshal.dump(env))
+      def initialize(env = ENV)
+        @actions = []
+
+        if RUBY_VERSION < '2.0'
+          @env = env.to_hash
+        else
+          @env = env.to_h
+        end
       end
 
       # Update environment with other en
@@ -24,18 +76,10 @@ module Aruba
       #
       # @yield
       #   Pass block to env
-      def update(other_env, &block)
-        if RUBY_VERSION <= '1.9.3'
-          # rubocop:disable Style/EachWithObject
-          other_env = other_env.to_hash.inject({}) { |a, (k, v)| a[k] = v.to_s; a }
-          # rubocop:enable Style/EachWithObject
-        else
-          other_env = other_env.to_h.each_with_object({}) { |(k, v), a| a[k] = v.to_s }
-        end
+      def update(other_env)
+        actions << UpdateAction.new(other_env)
 
-        env.update(other_env, &block)
-
-        self
+        UnixEnvironmentVariables.new(to_h)
       end
 
       # Fetch variable from environment
@@ -47,9 +91,9 @@ module Aruba
       #   The default value used, if the variable is not defined
       def fetch(name, default = UNDEFINED)
         if default == UNDEFINED
-          env.fetch name.to_s
+          to_h.fetch name.to_s
         else
-          env.fetch name.to_s, default
+          to_h.fetch name.to_s, default
         end
       end
 
@@ -58,7 +102,7 @@ module Aruba
       # @param [#to_s] name
       #   The name of the variable
       def key?(name)
-        env.key? name.to_s
+        to_h.key? name.to_s
       end
 
       # Get value of variable
@@ -66,7 +110,7 @@ module Aruba
       # @param [#to_s] name
       #   The name of the variable
       def [](name)
-        env[name.to_s]
+        to_h[name.to_s]
       end
 
       # Set value of variable
@@ -77,9 +121,11 @@ module Aruba
       # @param [#to_s] value
       #   The value of the variable
       def []=(name, value)
-        env[name.to_s] = value.to_s
+        value = value.to_s
+
+        actions << UpdateAction.new(name.to_s => value)
 
-        self
+        value
       end
 
       # Append value to variable
@@ -90,10 +136,12 @@ module Aruba
       # @param [#to_s] value
       #   The value of the variable
       def append(name, value)
-        name = name.to_s
-        env[name] = env[name].to_s + value.to_s
+        name  = name.to_s
+        value = self[name].to_s + value.to_s
+
+        actions << UpdateAction.new(name => value )
 
-        self
+        value
       end
 
       # Prepend value to variable
@@ -104,10 +152,12 @@ module Aruba
       # @param [#to_s] value
       #   The value of the variable
       def prepend(name, value)
-        name = name.to_s
-        env[name] = value.to_s + env[name].to_s
+        name  = name.to_s
+        value = value.to_s + self[name].to_s
 
-        self
+        actions << UpdateAction.new(name => value)
+
+        value
       end
 
       # Delete variable
@@ -115,9 +165,24 @@ module Aruba
       # @param [#to_s] name
       #   The name of the variable
       def delete(name)
-        env.delete name.to_s
+        # Rescue value, before it is deleted
+        value = to_h[name.to_s]
+
+        actions << RemoveAction.new(name.to_s)
+
+        value
+      end
+
+      # Pass on checks
+      def method_missing(name, *args, &block)
+        super unless to_h.respond_to? name
+
+        to_h.send name, *args, &block
+      end
 
-        self
+      # Check for respond_to
+      def respond_to_missing?(name, _private)
+        to_h.respond_to? name
       end
 
       # Convert to hash
@@ -126,17 +191,31 @@ module Aruba
       #   A new hash from environment
       def to_h
         if RUBY_VERSION < '2.0'
-          Marshal.load(Marshal.dump(env.to_hash))
+          Marshal.load(Marshal.dump(prepared_environment.to_hash))
         else
-          Marshal.load(Marshal.dump(env.to_h))
+          Marshal.load(Marshal.dump(prepared_environment.to_h))
         end
       end
 
       # Reset environment
       def clear
-        env.clear
+        value = to_h
 
-        self
+        actions.clear
+
+        value
+      end
+
+      private
+
+      def prepared_environment
+        if RUBY_VERSION <= '1.9.3'
+          # rubocop:disable Style/EachWithObject
+          actions.inject(ENV.to_hash.merge(env)) { |a, e| e.call(a) }
+          # rubocop:enable Style/EachWithObject
+        else
+          actions.each_with_object(ENV.to_hash.merge(env)) { |e, a| a = e.call(a) }
+        end
       end
     end
   end
diff --git a/lib/aruba/platforms/unix_platform.rb b/lib/aruba/platforms/unix_platform.rb
index 48d94fb..b199360 100644
--- a/lib/aruba/platforms/unix_platform.rb
+++ b/lib/aruba/platforms/unix_platform.rb
@@ -34,7 +34,7 @@ module Aruba
       end
 
       def environment_variables
-        UnixEnvironmentVariables.new
+        UnixEnvironmentVariables
       end
 
       def command_string
diff --git a/lib/aruba/platforms/windows_environment_variables.rb b/lib/aruba/platforms/windows_environment_variables.rb
index c2247c7..2855cf3 100644
--- a/lib/aruba/platforms/windows_environment_variables.rb
+++ b/lib/aruba/platforms/windows_environment_variables.rb
@@ -34,14 +34,14 @@ module Aruba
     # will always work.
     class WindowsEnvironmentVariables < UnixEnvironmentVariables
       def initialize(env = ENV.to_hash)
-        @env = Marshal.load(Marshal.dump(env))
+        @actions = []
 
         if RUBY_VERSION <= '1.9.3'
           # rubocop:disable Style/EachWithObject
-          @env = @env.inject({}) { |a, (k,v)| a[k.to_s.upcase] = v; a }
+          @env = env.inject({}) { |a, (k,v)| a[k.to_s.upcase] = v; a }
           # rubocop:enable Style/EachWithObject
         else
-          @env = @env.each_with_object({}) { |(k,v), a| a[k.to_s.upcase] = v }
+          @env = env.each_with_object({}) { |(k,v), a| a[k.to_s.upcase] = v }
         end
       end
 
diff --git a/lib/aruba/platforms/windows_platform.rb b/lib/aruba/platforms/windows_platform.rb
index cf8bc8c..f40fbd3 100644
--- a/lib/aruba/platforms/windows_platform.rb
+++ b/lib/aruba/platforms/windows_platform.rb
@@ -30,7 +30,7 @@ module Aruba
 
       # @see UnixPlatform#environment_variables
       def environment_variables
-        WindowsEnvironmentVariables.new
+        WindowsEnvironmentVariables
       end
 
       # @see UnixPlatform#which
diff --git a/lib/aruba/rspec.rb b/lib/aruba/rspec.rb
index 6b13352..2c24adc 100644
--- a/lib/aruba/rspec.rb
+++ b/lib/aruba/rspec.rb
@@ -91,14 +91,13 @@ RSpec.configure do |config|
   config.before :each do
     next unless self.class.include? Aruba::Api
 
-    aruba.environment.update aruba.config.command_runtime_environment
-    aruba.environment.prepend 'PATH', aruba.config.command_search_paths.join(':') + ':'
+    prepend_environment_variable 'PATH', aruba.config.command_search_paths.join(':') + ':'
   end
 
   # Use configured home directory as HOME
   config.before :each do |example|
     next unless self.class.include? Aruba::Api
 
-    aruba.environment['HOME'] =  aruba.config.home_directory
+    set_environment_variable 'HOME', aruba.config.home_directory
   end
 end
diff --git a/lib/aruba/runtime.rb b/lib/aruba/runtime.rb
index e87216c..0b0294f 100644
--- a/lib/aruba/runtime.rb
+++ b/lib/aruba/runtime.rb
@@ -40,14 +40,15 @@ module Aruba
     attr_accessor :config, :environment, :logger, :command_monitor, :announcer, :event_bus
 
     def initialize(opts = {})
-      @environment     = opts.fetch(:environment, Aruba.platform.environment_variables)
-      @event_bus     = ::Event::Bus.new(::Event::NameResolver.new(Aruba::Events))
+      @event_bus       = ::Event::Bus.new(::Event::NameResolver.new(Aruba::Events))
       @announcer       = opts.fetch(:announcer, Aruba.platform.announcer.new)
-
-      @config            = opts.fetch(:config, ConfigWrapper.new(Aruba.config.make_copy, @event_bus))
+      @config          = opts.fetch(:config, ConfigWrapper.new(Aruba.config.make_copy, @event_bus))
+      @environment     = opts.fetch(:environment, Aruba.platform.environment_variables.new)
       @current_directory = ArubaPath.new(@config.working_directory)
       @root_directory    = ArubaPath.new(@config.root_directory)
 
+      @environment.update(@config.command_runtime_environment)
+
       if Aruba::VERSION < '1'
         @command_monitor = opts.fetch(:command_monitor, Aruba.platform.command_monitor.new(:announcer => @announcer))
       else

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-aruba.git



More information about the Pkg-ruby-extras-commits mailing list