jam-cloud/websocket-gateway/spec/jam_websockets/stress_spec.rb

304 lines
7.3 KiB
Ruby

require 'spec_helper'
require 'thread'
def time_it(cat, &blk)
start = Time.now
blk.call
time = Time.now - start
puts("TIME: #{cat}: #{time}")
end
def safety_net(&blk)
begin
blk.call
rescue => e
#Bugsnag.notify(e)
@log.error("unhandled exception in EM Timer #{e}")
puts "Error during processing: #{$!}"
puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
end
end
LoginClient = Class.new do
attr_accessor :onmsgblock, :onopenblock, :oncloseblock, :onerrorblock, :encode_json, :channel_id, :client_id, :user_id, :context, :trusted, :subscriptions
def initialize(user)
@subscriptions = Set.new
@channel_id = user.id
@encode_json = true
end
def connected?
true
end
def onopen(&block)
@onopenblock = Proc.new { |handshake| block }
end
def onmessage(&block)
@onmsgblock= Proc.new { |data| block.call data }
end
def onclose(&block)
@oncloseblock = Proc.new { || block.call }
end
def onerror(&block)
@onerrorblock = Proc.new { |err| block.call err }
end
def close()
end
def send(msg)
puts msg
end
def get_peername
return "\x00\x02\x93\v\x7F\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" # 37643, "localhost"
end
end
class TestClient
def initialize(user, router)
@user = user
@client = LoginClient.new(@user)
@router = router
end
def connect
@router.new_client(@client, false)
end
def login
login_message = login_options(@user)
@router.handle_login(@client, login_message)
end
def heartbeat(notification_id = nil, notification_seen_at = nil)
heartbeat = Jampb::Heartbeat.new
if notification_id
heartbeat.notification_seen = notification_id
else
heartbeat.notification_seen = 'junk'
end
if notification_seen_at
heartbeat.notification_seen_at = notification_seen_at.to_s
end
@router.handle_heartbeat(heartbeat, '1', @client)
end
def disconnect
@client.oncloseblock.call
end
private
def login_options(user)
options = {}
options["token"] = user.remember_token
options["client_id"] = user.id
options["client_type"] = "client"
options["client_id_int"] = 1
options
end
end
describe Router, :spec_timeout => 15 do
def database_env (env)
singleton = GenericState.new
singleton.id = 'default'
singleton.env = env
singleton.save!
end
def rails_env (env)
JamRuby::Environment.should_receive(:mode).any_number_of_times.and_return(env)
end
include EventedSpec::EMSpec
default_timeout(1000000)
em_before do
puts "EM BEFORE ROUTER NEW"
end
subject { @router }
em_after do
puts "EM AFTER"
end
def sequence_1(user, special_heartbeat)
client1 = TestClient.new(user, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 1
client1.heartbeat
update_notification_at = Time.now.utc
#client1.heartbeat(special_heartbeat.id.to_s, nil)
client1.heartbeat(nil, update_notification_at)
client1.disconnect
sleep 6
user.reload
user = User.find(user.id)
@router.client_lookup.count.should be 0
last_notification_seen_at = user.notification_seen_at
last_notification_seen_at.should_not be_nil
last_notification_seen_at.to_i.should be update_notification_at.to_i
end
def sequence_2(user)
before_count = Connection.count
client1 = TestClient.new(user, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 1
after_count = Connection.count
before_count.should be (after_count - 1)
sleep 25
@router.client_lookup.count.should be 0
disc_count = Connection.count
before_count.should be disc_count
end
def sequence_in_session(user)
before_count = Connection.count
client1 = TestClient.new(user, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 1
music_session = FactoryGirl.create(:active_music_session, :creator => user)
connection = Connection.find_by_user_id(user.id)
connection.music_session = music_session
connection.save!
client1.disconnect
@router.client_lookup.count.should be 0
disc_count = Connection.count
before_count.should be disc_count
end
def sequence_in_two_session(user1, user2)
# create friendship between the two, to increase notifications
FactoryGirl.create(:friendship, :user => user1, :friend => user2)
FactoryGirl.create(:friendship, :user => user2, :friend => user1)
before_count = Connection.count
client1 = TestClient.new(user1, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 1
client1 = TestClient.new(user2, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 2
music_session = FactoryGirl.create(:active_music_session, :creator => user)
connection = Connection.find_by_user_id(user1.id)
connection.music_session = music_session
connection.save!
connection2 = Connection.find_by_user_id(user2.id)
connection2.music_session = music_session
connection2.save!
client1.disconnect
@router.client_lookup.count.should be 1
disc_count = Connection.count
before_count.should be (disc_count - 1)
end
def delete_conn_from_under(user)
before_count = Connection.count
client1 = TestClient.new(user, @router)
client1.connect
client1.login
@router.client_lookup.count.should be 1
after_count = Connection.count
before_count.should be (after_count - 1)
Connection.first.delete
@router.periodical_check_clients
@router.client_lookup.count.should be 0
disc_count = Connection.count
before_count.should be disc_count
end
describe "stress" do
before {
database_env('production')
rails_env('production')
stub_const("ENV", {'BUILD_NUMBER' => 1})
}
let(:user1) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
let(:user3) { FactoryGirl.create(:user) }
let(:user4) { FactoryGirl.create(:user) }
let(:user5) { FactoryGirl.create(:user) }
let!(:other) { FactoryGirl.create(:user, last_jam_locidispid: 1) }
let!(:msg1) {FactoryGirl.create(:notification_text_message, source_user: other, target_user: user1) }
it "the test" do
@router = Router.new()
@router.connect_time_expire_client = 20
@router.connect_time_stale_client = 14
@router.heartbeat_interval_client = @router.connect_time_stale_client / 2
@router.connect_time_expire_browser = 20
@router.connect_time_stale_browser = 14
@router.max_connections_per_user = 10
@router.heartbeat_interval_browser = @router.connect_time_stale_browser / 2
@router.maximum_minutely_heartbeat_rate_browser = 10
@router.maximum_minutely_heartbeat_rate_client = 10
@router.amqp_connection_manager = AmqpConnectionManager.new(true, 4, host: 'localhost', port: 5672)
@router.gateway_name = 'gateway1'
@router.init
em do
EventMachine::PeriodicTimer.new(5) do
time_it('stats_dump') { safety_net { @router.periodical_stats_dump } }
end
sequence_in_session(user3)
sequence_in_two_session(user4, user5)
delete_conn_from_under(user3)
sequence_1(user1, msg1)
sequence_1(user1, msg1)
sequence_2(user2)
done
end
end
end
end