I need to perform some actions periodically on my GTK Ruby program and i am looking for the working example of using gobject.timeout_add() function.
here is a short example showing a timeout each second that prints the message foo. The true at the end of the timeout block means that you don't want to remove the timeout. Return false when you want the timeout to stop firing.
require 'glib2'
GLib::Timeout.add(1000) do
puts "foo"
true
end
mainloop = GLib::MainLoop.new
mainloop.run
I have found this solution, but I am not sure:
class MainWin
def initialize()
#window = Gtk::Window::new
....
periodic
end
def periodic
do_something
Glib::Timeout.add(100) { periodic }
end
end
Related
I am having difficulty writing integration (no stubbing) tests for the following scenario: a process (rake task) that runs in a loop, emitting some values. Below is an approximation of the use case.
The test will succeed if I control-C it, but I would like it to catch the success condition and stop.
Anyone has some good suggestions? (stubbing/mocking are not good suggestions). I guess may be there is a way to instruct RSpec to stop a process after a matcher returns success?
describe 'rake reactor' do
it 'eventually returns 0.3' do
expect { Rake::Task['reactor'].execute }.to output(/^0\.3.*/).to_stdout
end
end
class Reactor
def initialize
#stop = false
end
def call
loop do
break if stop?
sleep random_interval
yield random_interval
end
end
def stop
#stop = true
end
def stop?
#stop == true
end
def random_interval
rand(0.1..0.4)
end
end
desc 'Start reactor'
task reactor: :environment do
reactor = Reactor.new
trap(:INT) do
reactor.stop
end
reactor.call { |m| p m }
end
A naïve way to handle it is to start a new thread and send INT from there after some predefined timeout:
before do
Thread.new do
sleep 0.5
Process.kill('INT', Process.pid)
end
end
Is there a way to keep track of variables that are created when using let?
I have a series of tests, some of which use let(:server) { #blah blah }. Part of the blah is to wait for the server to start up so that it is in a decent state before it is used.
The issue comes when I'm done with that test. I want to kill the server using server.kill(). This would be almost perfect if I could say something to the effect of
after(:each) { server.kill }
But this would create the server and waste all the resources/time to create it when it is referenced, only to kill it immediately if the server hadn't been used in the preceding test. Is there a way to keep track of and only clean up the server if it has been used?
I've come across a similar problem. A simple way to solve this is to set a instance variable in the let method to track if the object was created:
describe MyTest do
before(:each) { #created_server = false }
let(:server) {
#created_server = true
Server.new
}
after(:each) { server.kill if #created_server }
end
What I would do is something like this:
describe MyTest do
let(:server) { Server.new }
context "without server" do
## dont kill the server in here.
end
context "with server" do
before do
server
end
after(:each) { server.kill }
it {}
it {}
end
end
This is definitely a hack:
describe "cleanup for let" do
let(:expensive_object) {
ExpensiveObject.new
}
after(:context) {
v = __memoized[:expensive_object]
v.close if v
}
end
I figured that rspec had to be storing these lazy values somewhere the instance could access them, and __memoized is that place.
With a helper, it becomes a bit tidier:
def cleanup(name, &block)
after(:context) do
v = __memoized[name]
instance_exec(v, &block) if v
end
end
describe "cleanup for let" do
let(:expensive_object) {
ExpensiveObject.new
}
cleanup(:expensive_object) { |v|
v.close
}
end
There's still room for improvement, though. I think I would rather not have to type the object's name twice, so something like this would be nicer:
describe "cleanup for let" do
let(:expensive_object) {
ExpensiveObject.new
}.cleanup { |v|
v.close
}
end
I'm not sure I can do that without hacking rspec to pieces, but maybe if rspec themselves saw the benefit of it, something could be done in core...
Edit: Changed to using instance_exec because rspec started whining if things were called from the wrong context, and changed cleanup to be after(:context), because apparently this is the level it's memoising at.
Just write a small decorator to handle both the explicit and implicit starting of the server and which allows you to determine if the server has been started.
Imagine this to be the real server that needs to be started:
class TheActualServer
def initialize
puts 'Server starting'
end
def operation1
1
end
def operation2
2
end
def kill
puts 'Server stopped'
end
end
The reusable decorator could look like this:
class ServiceWrapper < BasicObject
def initialize(&start_procedure)
#start_procedure = start_procedure
end
def started?
!!#instance
end
def instance
#instance ||= #start_procedure.call
end
alias start instance
private
def method_missing(method_name, *arguments)
instance.public_send(method_name, *arguments)
end
def respond_to?(method_name)
super || instance.respond_to?(method_name)
end
end
Now you can apply this in your specs like the following:
describe 'something' do
let(:server) do
ServiceWrapper.new { TheActualServer.new }
end
specify { expect(server.operation1).to eql 1 }
specify { expect(server.operation2).to eql 2 }
specify { expect(123).to be_a Numeric }
context 'when server is running' do
before(:each) { server.start }
specify { expect('abc').to be_a String }
specify { expect(/abc/).to be_a Regexp }
end
after(:each) { server.kill if server.started? }
end
When a method is called on the decorator, it will run it's own implementation if one exists. For example if #started? is called, it will answer whether the actual server has been started or not. If it doesn't have an own implementation of that method, it will delegate the method call to the server object returned by that. If it doesn't have a reference to an instance of the actual server at that point, it will run the provided start_procedure to get one and memoize that for future calls.
If you put all the posted code into a file called server_spec.rb you can then run it with:
rspec server_spec.rb
The output will be like this:
something
Server starting
Server stopped
should eql 1
Server starting
Server stopped
should eql 2
should be a kind of Numeric
when server is running
Server starting
Server stopped
should be a kind of String
Server starting
Server stopped
should be a kind of Regexp
Finished in 0.00165 seconds (files took 0.07534 seconds to load)
5 examples, 0 failures
Note that in the examples 1 and 2, methods on the server are called, and therefore you see the output of the server that is implicitly started by the decorator.
In example 3 there is no interaction with the server at all, therefore you don't see the server's output in the log.
Then again in examples 4 and 5, there is not direct interaction with the server object in the example code, but the server is explicitly started through a before block, which can also be seen in the output.
I'm using RSpec to test the behavior of a simple REPL. The REPL just echoes back whatever the input was, unless the input was "exit", in which case it terminates the loop.
To avoid hanging the test runner, I'm running the REPL method inside a separate thread. To make sure that the code in the thread has executed before I write expectations about it, I've found it necessary to include a brief sleep call. If I remove it, the tests fail intermittently because the expectations are sometimes made before the code in the thread has run.
What is a good way to structure the code and spec such that I can make expectations about the REPL's behavior deterministically, without the need for the sleep hack?
Here is the REPL class and the spec:
class REPL
def initialize(stdin = $stdin, stdout = $stdout)
#stdin = stdin
#stdout = stdout
end
def run
#stdout.puts "Type exit to end the session."
loop do
#stdout.print "$ "
input = #stdin.gets.to_s.chomp.strip
break if input == "exit"
#stdout.puts(input)
end
end
end
describe REPL do
let(:stdin) { StringIO.new }
let(:stdout) { StringIO.new }
let!(:thread) { Thread.new { subject.run } }
subject { described_class.new(stdin, stdout) }
# Removing this before hook causes the examples to fail intermittently
before { sleep 0.01 }
after { thread.kill if thread.alive? }
it "prints a message on how to end the session" do
expect(stdout.string).to match(/end the session/)
end
it "prints a prompt for user input" do
expect(stdout.string).to match(/\$ /)
end
it "echoes input" do
stdin.puts("foo")
stdin.rewind
expect(stdout.string).to match(/foo/)
end
end
Instead of letting :stdout be a StringIO, you could back it by a Queue. Then when you try to read from the queue, your tests will just wait until the REPL pushes something into the queue (aka. writes to stdout).
require 'thread'
class QueueIO
def initialize
#queue = Queue.new
end
def write(str)
#queue.push(str)
end
def puts(str)
write(str + "\n")
end
def read
#queue.pop
end
end
let(:stdout) { QueueIO.new }
I just wrote this up without trying it out, and it may not be robust enough for your needs, but it gets the point across. If you use a data structure to synchronize the two threads like this, then you don't need to sleep at all. Since this removes the non-determinism, you shouldn't see the intermittent failures.
I've used a running? guard for situations like this. You probably can't avoid the sleep entirely, but you can avoid unnecessary sleeps.
First, add a running? method to your REPL class.
class REPL
...
def running?
!!#running
end
def run
#running=true
loop do
...
if input == 'exit
#running = false
break
end
...
end
end
end
Then, in your specs, sleep until the REPL is running:
describe REPL do
...
before { sleep 0.01 until REPL.running? }
...
end
I wonder if this is possible, because if it is, it would help me implement what I need for a program I am making:
Is there a way to attach some kind of listener to STDOUT from within a Ruby program, so that if nothing is written (via puts) to STDOUT for a certain time interval, an error is raised?
Writing to STDOUT should otherwise work as expected.
Perhaps something like this:
def new_puts(what)
#time_th.kill if(#time_th)
puts what
#time_th = Thread.new() {
sleep(2)
raise "here"
}
#time_th.abort_on_exception = true
end
new_puts("test")
new_puts("test2")
sleep(10)
new_puts("test3") #too late
or with callback methods:
def callback
puts "Timeout!"
end
def new_puts(what)
#time_th.kill if(#time_th)
puts what
#time_th = Thread.new() {
sleep(2)
self.method(:callback).call
}
end
new_puts("test")
new_puts("test2")
sleep(10)
new_puts("test3") #too late
I'm writing a delayed_job clone for DataMapper. I've got what I think is working and tested code except for the thread in the worker process. I looked to delayed_job for how to test this but there are now tests for that portion of the code. Below is the code I need to test. ideas? (I'm using rspec BTW)
def start
say "*** Starting job worker #{#name}"
t = Thread.new do
loop do
delay = Update.work_off(self) #this method well tested
break if $exit
sleep delay
break if $exit
end
clear_locks
end
trap('TERM') { terminate_with t }
trap('INT') { terminate_with t }
trap('USR1') do
say "Wakeup Signal Caught"
t.run
end
see also this thread
The best approach, I believe, is to stub the Thread.new method, and make sure that any "complicated" stuff is in it's own method which can be tested individually. Thus you would have something like this:
class Foo
def start
Thread.new do
do_something
end
end
def do_something
loop do
foo.bar(bar.foo)
end
end
end
Then you would test like this:
describe Foo
it "starts thread running do_something" do
f = Foo.new
expect(Thread).to receive(:new).and_yield
expect(f).to receive(:do_something)
f.start
end
it "do_something loops with and calls foo.bar with bar.foo" do
f = Foo.new
expect(f).to receive(:loop).and_yield #for multiple yields: receive(:loop).and_yield.and_yield.and_yield...
expect(foo).to receive(:bar).with(bar.foo)
f.do_something
end
end
This way you don't have to hax around so much to get the desired result.
You could start the worker as a subprocess when testing, waiting for it to fully start, and then check the output / send signals to it.
I suspect you can pick up quite a few concrete testing ideas in this area from the Unicorn project.
Its impossible to test threads completely. Best you can do is to use mocks.
(something like)
object.should_recieve(:trap).with('TERM').and yield
object.start
How about just having the thread yield right in your test.
Thread.stub(:new).and_yield
start
# assertions...