Created
June 24, 2015 09:32
-
-
Save hatyuki/f79bad568526a10f2c16 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Test | |
class RedisServer | |
# Create a new redis-server instance, and start it if block given. | |
# | |
# @param timeout [Fixnum] | |
# @param config [Hash] | |
def initialize (timeout: 3, config: { }, &block) | |
@owner_pid = $$ | |
@pid = nil | |
@timeout = timeout | |
@config = config | |
if @config[:loglevel].to_s == 'warning' | |
$stderr.puts 'Test::RedisServer does not support "loglevel warning", using "notice" instead.' | |
@config[:loglevel] = 'notice' | |
end | |
start(&block) if block | |
end | |
# Start redis-server instance. | |
# | |
# @yield [connect_info] | |
# @yieldparam connect_info [Hash] | |
def start | |
return if @pid | |
Dir.mktmpdir do |tmpdir| | |
yield start_redis_server(tmpdir) | |
stop | |
end | |
end | |
private | |
def start_redis_server (tmpdir) | |
logfile = "#{tmpdir}/redis-server.log" | |
config_file = prepare_config_file(tmpdir) | |
File.open(logfile, 'w') do |redirect| | |
@pid = Process.fork do | |
stderr = $stderr.dup | |
begin | |
exec 'redis-server', config_file, out: redirect, err: redirect | |
rescue => error | |
stderr.puts "exec failed: #{error}" | |
exit error.errno | |
end | |
end | |
end | |
(@timeout * 10).times do | |
if !Process.waitpid(@pid, Process::WNOHANG).nil? | |
@pid = nil | |
break | |
else | |
if File.read(logfile) =~ /The server is now ready to accept connections/ | |
return connect_info | |
end | |
end | |
sleep 0.1 | |
end | |
stop if @pid | |
raise RuntimeError, "failed to launch redis-server\n#{File.read(logfile)}" | |
end | |
def prepare_config_file (directory) | |
if @config[:unixsocket].nil? && @config[:port].nil? | |
@config[:unixsocket] = "#{directory}/redis.sock" | |
@config[:port] = 0 | |
end | |
if @config[:dir].nil? | |
@config[:dir] = "#{directory}/" | |
end | |
"#{directory}/redis.conf".tap do |config_file| | |
File.write(config_file, config) | |
end | |
end | |
def config | |
@config.inject('') do |memo, (key, value)| | |
next if value.to_s.empty? | |
memo += "#{key} #{value}\n" | |
end | |
end | |
def connect_info | |
host = @config[:bind].nil? ? '0.0.0.0' : @config[:bind] | |
port = @config[:port] | |
if port.is_a?(Fixnum) && port > 0 | |
{ url: "redis://#{host}:#{port}/" } | |
else | |
{ path: @config[:unixsocket] } | |
end | |
end | |
def stop (signal = :TERM) | |
return if @pid.nil? | |
Process.kill(signal, @pid) | |
while Process.waitpid(@pid, Process::WNOHANG); end | |
@pid = nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment