Skip to content

Commit

Permalink
Use overlayfs (when possible) to speed up specs
Browse files Browse the repository at this point in the history
  • Loading branch information
Resonious committed Dec 19, 2019
1 parent 3dd5586 commit 1b41c62
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 8 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ jobs:
uses: actions/setup-ruby@v1
with:
ruby-version: 2.5.x
- name: Install sqlite3
run: sudo apt-get install -y libsqlite3-dev
- name: Install sqlite3 and overlayfs
run: sudo apt-get install -y libsqlite3-dev fuse-overlayfs
- name: Install nodejs dependencies
run: |
cd spec/dummy
Expand Down
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

0 comments on commit 1b41c62

Please sign in to comment.