require File.dirname(__FILE__) + '/helper' PORT = 27118 class ErnieServerTest < Test::Unit::TestCase # global setup def setup @servers ||= [] Dir.chdir(ERNIE_ROOT) `erlc -o test/sample #{ERNIE_ROOT}/test/sample/intTest.erl` Signal.trap("INT") do puts "Shutting Down" shutdown_servers teardown exit end end def teardown `rm test/sample/intTest.beam` end context "An Ernie Server" do setup do start_server end context "call" do should "handle zeronary" do assert_equal :foo, svc.call.ext.zeronary assert_equal :foo, svc.call.intTest.zeronary end should "handle unary" do assert_equal 5, svc.call.ext.unary(5) assert_equal 5, svc.call.intTest.unary(5) end should "handle binary" do assert_equal 7, svc.call.ext.binary(5, 2) assert_equal 7, svc.call.intTest.binary(5, 2) end should "handle ternary" do assert_equal 10, svc.call.ext.ternary(5, 2, 3) assert_equal 10, svc.call.intTest.ternary(5, 2, 3) end should "handle massive binaries" do assert_equal 8 * 1024 * 1024, svc.call.ext.big(8 * 1024 * 1024).size assert_equal 8 * 1024 * 1024, svc.call.intTest.big(8 * 1024 * 1024).size end should "not block on internal modules" do time = Time.now svc.call.intTest.sleep(1000) assert(Time.now >= time + 1) time = Time.now svc.cast.intTest.sleep(1000) svc.cast.intTest.sleep(1000) svc.cast.intTest.sleep(1000) svc.call.intTest.zeronary assert(Time.now < time + 1) end should "get an error on missing module" do begin svc.call.failboat.mcfail(:fail) fail "Expected a BERTRPC::ServerError" rescue BERTRPC::ServerError => e assert_equal "No such module 'failboat'", e.message else assert false, 'failed to raise on missing module' end end should "get an error on missing function" do begin svc.call.ext.mcfail(:fail) fail "Expected a BERTRPC::ServerError" rescue BERTRPC::ServerError => e assert_equal "No such function 'ext:mcfail'", e.message else assert false, 'failed to raise on missing function' end begin svc.call.intTest.mcfail(:fail) fail "Expected a BERTRPC::ServerError" rescue BERTRPC::ServerError => e assert_equal "No such function 'intTest:mcfail'", e.message else assert false, 'failed to raise on missing function' end end end context "cast" do should "be received and return immediately" do t0 = Time.now assert_equal nil, svc.cast.ext.set_state(7) assert Time.now - t0 < 1 assert_equal 7, svc.call.ext.get_state t0 = Time.now assert_equal nil, svc.cast.intTest.set_state(7) assert Time.now - t0 < 1 sleep 0.25 assert_equal 7, svc.call.intTest.get_state end end teardown do shutdown_server end end context "Two Ernie Servers" do setup do start_servers(2) @servers.each do |svc| svc.cast.intTest.connect_nodes end end context "call" do should "handle zeronary" do @servers.each do |svc| assert_equal :foo, svc.call.ext.zeronary assert_equal :foo, svc.call.intTest.zeronary end end should "handle unary" do @servers.each do |svc| assert_equal 5, svc.call.ext.unary(5) assert_equal 5, svc.call.intTest.unary(5) end end should "handle binary" do @servers.each do |svc| assert_equal 7, svc.call.ext.binary(5, 2) assert_equal 7, svc.call.intTest.binary(5, 2) end end should "handle ternary" do @servers.each do |svc| assert_equal 10, svc.call.ext.ternary(5, 2, 3) assert_equal 10, svc.call.intTest.ternary(5, 2, 3) end end should "handle massive binaries" do @servers.each do |svc| assert_equal 8 * 1024 * 1024, svc.call.ext.big(8 * 1024 * 1024).size assert_equal 8 * 1024 * 1024, svc.call.intTest.big(8 * 1024 * 1024).size end end should "make joined erlang nodes possible" do assert_equal nil, @servers.first.cast.intTest.set_state(7) sleep 0.25 assert_equal 7, @servers.last.call.intTest.get_state end end teardown do shutdown_servers(2) end end protected def svc @servers[rand(@servers.size-1)] end def start_server start_servers(1) end def shutdown_server shutdown_servers(1) end def start_servers(n = 1) n.times do `#{ERNIE_ROOT}/bin/ernie -c #{ERNIE_ROOT}/test/sample/sample.cfg \ -P /tmp/ernie#{@servers.size}.pid \ -p #{PORT + @servers.size} \ --name ernie#{@servers.size}@127.0.0.1 \ -d` @servers << BERTRPC::Service.new('localhost', PORT + @servers.size) loop do begin @servers.last.call.ext.zeronary break rescue Object => e sleep 0.1 end end end end def shutdown_servers(n = nil) start = @servers.size - 1 last = start - (n || start) (start).downto(last >= 0 ? last : 0) do |i| pid = File.read("/tmp/ernie#{i}.pid") `kill -9 #{pid}` end end end