Skip to content

Commit

Permalink
Enhance container synchronization custom matchers to check sync withi…
Browse files Browse the repository at this point in the history
…n a time lapse without waiting for the full time ✨
  • Loading branch information
michaelbaudino committed Jul 5, 2017
1 parent cc9337a commit 33b2068
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 23 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ gemspec
group :test do
gem 'rspec'
gem 'rspec-bash'
gem 'activesupport'
gem 'os'
end
12 changes: 12 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activesupport (5.1.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
backticks (1.0.0)
coderay (1.1.1)
concurrent-ruby (1.0.5)
daemons (1.2.4)
diff-lcs (1.3)
docker-compose (1.1.5)
backticks (~> 1.0)
dotenv (2.2.1)
gem_update_checker (0.2.0)
i18n (0.8.4)
method_source (0.8.2)
minitest (5.10.2)
os (1.0.0)
pry (0.10.4)
coderay (~> 1.1.0)
Expand All @@ -44,11 +52,15 @@ GEM
slop (3.6.0)
terminal-notifier (1.6.3)
thor (0.19.4)
thread_safe (0.3.6)
tzinfo (1.2.3)
thread_safe (~> 0.1)

PLATFORMS
ruby

DEPENDENCIES
activesupport
docker-sync!
os
pry
Expand Down
6 changes: 6 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,11 @@ require 'docker-sync'
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.

# ActiveSupport stuff for readability (specially `1.second` and stuff like that)
require 'active_support'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/integer/time'
require 'active_support/core_ext/object/blank'

require 'pry'
Pry.start
46 changes: 35 additions & 11 deletions spec/helpers/synchronization_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
RSpec::Matchers.define :be_in_sync_with do |container_dir|
attr_reader :actual, :expected, :container_name, :container_dir, :host_dir
attr_reader :actual, :expected, :container_dir, :host_dir

attr_accessor :container_name_missing_error
container_name_missing_error = 'Container name is missing. Please chain `.in_container(container_name)` to define it.'.freeze

match do |host_dir|
@container_dir = container_dir
@host_dir = host_dir
raise container_name_missing_error if container_name.nil? || container_name.empty?
def container_dir_matches_host_dir?
@actual, host_stderr, _status = env.execute_inline("cd #{host_dir}; find . -type f -print0 | sort -z | xargs -0 shasum -a 256")
@expected, container_stderr, _status = env.execute_inline("docker exec #{container_name} bash -c 'cd #{container_dir}; find . -type f -print0 | sort -z | xargs -0 sha256sum'")
raise host_stderr unless host_stderr.empty?
raise container_stderr unless container_stderr.empty?
expected == actual
end

match do |host_dir|
@container_dir = container_dir
@host_dir = host_dir
@start_time = Time.now

while Time.now < @start_time + delay
if container_dir_matches_host_dir?
# puts "Yay: #{diff_target} matches #{diff_source} in #{(Time.now - @start_time).round(3).seconds.inspect} instead of #{delay.inspect}."
break true
end
sleep 0.25.second
end
end

chain :in_container do |container_name|
@container_name = container_name
end

chain :within do |delay|
@delay = delay
end

chain :immediately do
@delay = 0.second
end

def container_name
@container_name.presence || raise('Container name is missing. Please chain `.in_container(container_name)` to define it.'.freeze)
end

def delay
@delay ||= 1.second
end

diffable
description { "synchronize #{diff_target} with #{diff_source}." }
failure_message { "Expected #{diff_target} to match #{diff_source}." }
failure_message_when_negated { "Expected #{diff_target} to be different than #{diff_source}." }
description { "synchronize #{diff_target} with #{diff_source} within #{delay.inspect}." }
failure_message { "Expected #{diff_target} to match #{diff_source} within #{delay.inspect}." }
failure_message_when_negated { "Expected #{diff_target} to be different than #{diff_source} within #{delay.inspect}." }

def diff_source
"`#{host_dir}` filetree on host"
Expand Down
14 changes: 10 additions & 4 deletions spec/integration/native-osx_strategy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,34 @@
let(:host_app_path) { File.join(env.dir, File.basename(host_app_template)) }
let(:test_env_vars) { { 'DOCKER_SYNC_SKIP_UPGRADE' => 'true', 'DOCKER_SYNC_SKIP_UPDATE' => 'true', 'DOCKER_SYNC_SKIP_DEPENDENCIES_CHECK' => 'true' } }

before :all do
# Cleanup potentially leftover container from previously killed test suite
system('docker rm -f -v docker_sync_specs-sync &> /dev/null')
end

describe 'start' do
around(:each) do |example|
FileUtils.cp_r([host_app_template, config_file_template], env.dir)
FileUtils.chdir(env.dir) do
replace_in_file(config_file_path, '{{HOST_APP_PATH}}', "'#{host_app_path}'")
env.execute_inline("#{bin} start", test_env_vars)
sleep 1 # because, you know ¯\_(ツ)_/¯
_stdout, stderr, status = env.execute_inline("#{bin} start", test_env_vars)
raise stderr unless status.success?
example.run
env.execute_inline("#{bin} clean", test_env_vars)
end
end

it 'creates a PID file' do
sleep 1 # because, you know ¯\_(ツ)_/¯
expect(File.file?('.docker-sync/daemon.pid')).to be true
end

it 'creates a log file' do
expect(File.file?('.docker-sync/daemon.log')).to be true
end

it_behaves_like 'a synchronized directory', '/host_sync'
it_behaves_like 'a synchronized directory', '/app_sync'
it_behaves_like 'a synchronized directory', '/host_sync', within: 2.second
it_behaves_like 'a synchronized directory', '/app_sync', within: 4.seconds

xit "is a manual debugging test" do
# Welcome to a state where you can debug DockerSync synchronization. In another terminal, you can:
Expand Down
13 changes: 5 additions & 8 deletions spec/shared_examples/synchronization_shared_examples.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
require 'spec_helper'
RSpec.shared_examples 'a synchronized directory' do |container_dir, options = {}|
options[:within] ||= 1.second

RSpec.shared_examples 'a synchronized directory' do |container_dir|
it 'synchronizes on startup' do
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync')
end

it 'synchronizes files additions' do
File.write(File.join(host_app_path, 'new_file.txt'), 'Hi, I am a new file')
sleep 1
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync')
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync').within(options[:within])
end

it 'synchronizes files changes' do
File.write(File.join(host_app_path, 'README.md'), 'Some new content', mode: 'a+')
sleep 1
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync')
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync').within(options[:within])
end

it 'synchronizes files deletions' do
File.delete(File.join(host_app_path, 'README.md'))
sleep 1
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync')
expect(host_app_path).to be_in_sync_with(container_dir).in_container('docker_sync_specs-sync').within(options[:within])
end
end
6 changes: 6 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
require 'rspec/bash'
require 'pry'

# ActiveSupport stuff for readability (specially `1.second` and stuff like that)
require 'active_support'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/integer/time'
require 'active_support/core_ext/object/blank'

# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause
Expand Down

0 comments on commit 33b2068

Please sign in to comment.