Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use overlayfs (when possible) to speed up specs #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Style/BlockComments:
Style/Documentation:
Enabled: false

Style/AndOr:
Enabled: false

Style/RescueModifier:
Exclude:
- spec/spec_helper.rb
Expand All @@ -18,6 +21,13 @@ Style/NestedParenthesizedCalls:
Exclude:
- spec/**/*

Style/MultilineIfModifier:
Exclude:
- spec/support/dummy_app_helpers.rb
Style/WhileUntilModifier:
Exclude:
- spec/support/dummy_app_helpers.rb

Metrics/BlockLength:
Exclude:
- spec/**/*
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,11 @@ sync('drivers/*').forEach((driverPath) => {
module.exports = environment
```

## Developing / Testing

This gem doesn't actually load the dummy app environment like most Rails plugins. For each spec, it copies the entire dummy app into a new folder and runs rake tasks, generators, and `rails run` inside that new folder. This makes it easier for us to test file-structure related behavior. We can freely create and move files without worrying about cleaning up.

Copying the entire dummy app on every spec is super slow. If you have [fuse-overlayfs](https://github.com/containers/fuse-overlayfs) installed, the test cases will use it to avoid the full copy on every test. Set `NO_OVERLAYFS=true` if you have it installed but don't want it to be used. If used, it speeds up tests a little bit, but running `rails run` is still pretty slow.

## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
49 changes: 43 additions & 6 deletions spec/support/dummy_app_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ def find_js_pack(html, pack_name)
def create_file(file_name, contents)
full_path = File.expand_path(File.join(dummy_app, file_name))

dir = full_path.split('/')
dir.pop
FileUtils.mkdir_p(dir.join('/'))
FileUtils.mkdir_p(File.dirname(full_path))

File.open(full_path, 'w') { |f| f.write contents }
end
Expand All @@ -84,22 +82,46 @@ def dummy_app
@dummy_app
end

def dummy_app_workdir
"#{@dummy_app}.workdir"
end

def dummy_app_upper
"#{@dummy_app}.upper"
end

def all_dummy_app_dirs
[dummy_app, dummy_app_workdir, dummy_app_upper]
end

def dummy_app_template
File.expand_path File.join(__dir__, '../dummy')
end

def setup_dummy_app
random_string = SecureRandom.hex.chars.first(4).join
@dummy_app = File.expand_path File.join(__dir__, "../dummy-#{random_string}")
FileUtils.rm_r @dummy_app if File.exist?(@dummy_app)
FileUtils.cp_r dummy_app_template, @dummy_app

all_dummy_app_dirs.each do |dir|
FileUtils.rm_rf dir
FileUtils.mkdir dir
end

try_overlayfs or copy_dummy_app
end

def teardown_dummy_app
return if @dummy_app.nil?

FileUtils.rm_r @dummy_app
until system "fusermount -u #{@dummy_app}"
sleep 1
end if @using_fuse
all_dummy_app_dirs.each do |dir|
FileUtils.rm_r dir
end

@dummy_app = nil
@using_fuse = nil
end

#
Expand All @@ -119,4 +141,19 @@ def truncate_lines(stream, limit: 200)

lines
end

def try_overlayfs
return false if ENV['NO_OVERLAYFS']
low = dummy_app_template
up = dummy_app_upper
work = dummy_app_workdir

cmd = "fuse-overlayfs -o 'lowerdir=#{low},upperdir=#{up},workdir=#{work}' #{dummy_app}"
@using_fuse = system cmd
end

def copy_dummy_app
FileUtils.rmdir dummy_app
FileUtils.cp_r dummy_app_template, dummy_app
end
end