Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Refactoring Sandboxing to be in RSpec support #1808

Merged
merged 1 commit into from
Dec 31, 2014

Conversation

tyler-ball
Copy link
Contributor

rspec-core changes for #1798

rspec-support changes in rspec/rspec-support#137

@JonRowe
Copy link
Member

JonRowe commented Dec 16, 2014

Why, this sandboxing is only intended to be used in rspec-core....

@tyler-ball
Copy link
Contributor Author

This relates to a conversation @myronmarston and I had. We're leveraging sandboxing inside our project to use RSpec to test RSpec code.

If you think it should be moved from rspec-support into rspec-core, I am happy to do that. Rspec-support just looked like the obvious place for it.

@JonRowe
Copy link
Member

JonRowe commented Dec 16, 2014

Ah I see, this code isn't intended for external consumption (read it's far to hacky for us to want to support at the moment), we're fine with you cribbing it and maintaining it yourself in your own project but I'm not ok with extracting this as is into rspec-support.

@myronmarston
Copy link
Member

@JonRowe -- @tyler-ball and I discussed this over skype last week. We've never exposed the sandboxing logic before but given what Chef is going to be doing with RSpec (they are leveraging it as part of chef to allow "audits" of the state of nodes using RSpec's API to specify what's expected) and their need to be able to to test their audit runner (in the same way rspec-core tests itself), they need the same sandboxing thing. We already need to maintain the sandboxing logic anyway so that we can use it, so providing a stable RSpec::Core::Sandbox.sandboxed(&block) API isn't really any additional work for us, and it's going to make things much better on Chef if they don't have to maintain hacky sandboxing logic of their own that uses private APIs.

@tyler-ball -- I'd prefer to see the sandboxing logic be placed directly here in rspec-core, given that it's specifically deals with sandboxing rspec-core's world/config state. rspec-support is intended primarily to contain common support code that we'd like to be available to any of rspec-core/expectations/mocks when they are used individually w/o the others. The sandboxing stuff isn't needed by expectations or mocks and really belongs here. I've got some more feedback on it but figure I'll wait until you've ported it back over to here so we can keep the review all in this one PR :).

@tyler-ball
Copy link
Contributor Author

Okay @myronmarston I moved sandboxing back into rspec-core. Now I'm seeing the same error in Travis that I am seeing locally. I'm guessing this has to do with no longer setting RSpec.current_example = nil in the run method, like you mentioned 😄

I'll see if I can figure it out.

attr_writer :configuration, :world
end
end
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we are exposing the sandboxing as a public API, I think we can add these writers to the definition of RSpec in lib/rspec/core.rb. (Just be sure to label them @api private). We had them in the spec stuff because they weren't needed by any public APIs but now that they are they belong in lib/rspec/core.rb, I think.

@myronmarston
Copy link
Member

I think it's going to be useful to distinguish between what's essential to the sandbox and what's incidentally needed by rspec-core's specs and was mixed into the sandboxing logic at some point in the past. The incidental stuff probably doesn't belong in lib/rspec/core/sandboxing.rb. I think we'll probably still have a spec/support/sandbox.rb file that leverages lib/rspec/core/sandboxing.rb plus adds some additional things rspec-core needs.

I'll comment on the specific things I think don't belong. I don't have time to do that right now (I have to go do something), unfortunately, but will try to do it a few hours from now.

class << self

def sandboxed(&block)
orig_load_path = $LOAD_PATH.dup
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The load path isolation is orthogonal to rspec-core sandboxing. It got added because some of rspec-core's specs do load path manipulation, it's useful to keep those mutations in a sandbox and it was simple to add it to the existing sandboxing logic, but I don't think it belongs in the publicly supported rspec-core sandbox.

@myronmarston
Copy link
Member

I'm guessing this has to do with no longer setting RSpec.current_example = nil in the run method, like you mentioned 😄

I'll see if I can figure it out.

Let me know if you want to take a stab at that, as it deals with stuff that's pretty orthogonal to what you're working on. Or if you run into trouble with any of the other suggestions I made, let me know and I'm happy to try to help out.

@tyler-ball
Copy link
Contributor Author

@myronmarston Okay, I updated for all your comments - I still need to fix that example but I don't have time just this second. I'll either do it or ping you with questions - thanks for all the help and great feedback!

@@ -43,6 +43,11 @@ module RSpec

extend RSpec::Core::Warnings

class << self
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you don't usually open up the singleton class, but I was getting a private method called error when trying to use self.attr_writer - any idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For macros that you normally use at the class level to define instance methods, but instead want to use to define class methods, you have to the singleton class as you have here, so that's fine. The preference I mentioned before is for normal static method definitions being done using def self.method_name, but for things that really need to run in the context of the singleton class, this is fine.

@JonRowe
Copy link
Member

JonRowe commented Dec 22, 2014

Liking the work so far!

@myronmarston
Copy link
Member

@tyler-ball -- We're hoping to release 3.2 soon and I'd like for this to be included. I completely understand the delay on this (given the holidays) but If you'd like one of us to take it across the finish line, please let us know.

@tyler-ball
Copy link
Contributor Author

@myronmarston Cleaned up per your comments so far

def self.sandboxed(&block)
raise ArgumentError.new("You must provide a block to be ran in the sandbox") unless block_given?
raise ArgumentError.new("Your sandboxed block only accepts 1 argument - the config used inside the sandbox") if block.arity > 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if I am being too eager here with my condition checking

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think I'd prefer we don't do the block checking here. Ruby's not a statically-typed language and IMO doing these sorts of checks goes against the philosophy of how ruby is designed to be used.

Also, the simple act of capturing &block, even if you yield instead, has a perf cost:

https://github.com/rspec/rspec-core/blob/master/benchmarks/capture_block_vs_yield.rb

...so I'd like to see &block removed entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@tyler-ball
Copy link
Contributor Author

Now lets just hope the specs that pass locally pass in Travis 😄

# from the running RSpec instance - it should return a sandboxed configuration.
#
# @param new_config [RSpec::Core::Configuration] A custom config to use when executing the sandboxed tests.
# Defaults to a default Configuration object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a param any more.

@myronmarston
Copy link
Member

This is looking good, @tyler-ball. I left a couple comments. Please rebase and squash into one commit when you've addressed those and I'll be glad to merge this. BTW, I expect the jruby builds to fail on travis -- they rolled out a new environment today and there are some problems there.

@tyler-ball
Copy link
Contributor Author

Updated the yarddoc, removed the &block, rebased and squashed into 1 commit

EDIT Added full yarddoc coverage - didn't realize that was failing the test, I thought it was a warning. Let me know if what I wrote does not make sense.

@tyler-ball tyler-ball force-pushed the master branch 2 times, most recently from aecf200 to 3f4fb6d Compare December 30, 2014 16:29
@tyler-ball
Copy link
Contributor Author

@myronmarston 1.8.7 and ree are now the only ones failing because the formatter tests expect a different style - can you provide some guidance?

| # ./spec/support/sandboxing.rb:2
| # ./spec/support/sandboxing.rb:18:in `block (4 levels) in <top (required)>'
| # ./spec/support/sandboxing.rb:18:in `block (3 levels) in <top (required)>'
| # ./spec/support/sandboxing.rb:9:in `block (2 levels) in <top (required)>'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On 1.8.7 (which is the context for which this fixture is used to match), these three lines don't have the :in block... bit. That's what's causing the failures on travis.

@myronmarston
Copy link
Member

@myronmarston 1.8.7 and ree are now the only ones failing because the formatter tests expect a different style - can you provide some guidance?

Backtraces look different on ruby 1.8 so there's a different test fixture defined in spec/support/formatter_support.rb. I left a comment above where the change needs to happen. If you don't have 1.8.7 installed locally and want me to take this across the finish line, let me know.

@myronmarston
Copy link
Member

Thanks, @tyler-ball. The appveyor build is a transient faliure that's unrelated to your changes here (and I'm working on a fix for it) so I'm going to merge this.

myronmarston added a commit that referenced this pull request Dec 31, 2014
Refactoring Sandboxing to be in RSpec support
@myronmarston myronmarston merged commit 57ae70d into rspec:master Dec 31, 2014
myronmarston added a commit that referenced this pull request Dec 31, 2014
@myronmarston myronmarston mentioned this pull request Dec 31, 2014
myronmarston added a commit that referenced this pull request Dec 31, 2014
@tyler-ball
Copy link
Contributor Author

Thanks for cleaning up my code issues and getting this in!

MatheusRich pushed a commit to MatheusRich/rspec-core that referenced this pull request Oct 30, 2020
Refactoring Sandboxing to be in RSpec support
MatheusRich pushed a commit to MatheusRich/rspec-core that referenced this pull request Oct 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants