<commit_before>require 'test_helper'
require 'rack/mock'
require 'thread'
require 'connection_pool'

describe Rack::Session::Redis do
  session_key = Rack::Session::Redis::DEFAULT_OPTIONS[:key]
  session_match = /#{session_key}=([0-9a-fA-F]+);/
  incrementor = lambda do |env|
    env["rack.session"]["counter"] ||= 0
    env["rack.session"]["counter"] += 1
    Rack::Response.new(env["rack.session"].inspect).to_a
  end
  drop_session = proc do |env|
    env['rack.session.options'][:drop] = true
    incrementor.call(env)
  end
  renew_session = proc do |env|
    env['rack.session.options'][:renew] = true
    incrementor.call(env)
  end
  defer_session = proc do |env|
    env['rack.session.options'][:defer] = true
    incrementor.call(env)
  end
  skip_session = proc do |env|
    env['rack.session.options'][:skip] = true
    incrementor.call(env)
  end

  # # test Redis connection
  # Rack::Session::Redis.new(incrementor)
  #
  # it "faults on no connection" do
  #   lambda{
  #     Rack::Session::Redis.new(incrementor, :redis_server => 'nosuchserver')
  #   }.must_raise(Exception)
  # end

  it "can create it's own pool" do
    session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
    conn = session_store.instance_variable_get(:@conn)
    conn.pool.class.must_equal ::ConnectionPool
    conn.pool.instance_variable_get(:@size).must_equal 5
  end

  it "can create it's own pool using default Redis server" do
    session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
    session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/)  }
  end

  it "can create it's own pool using provided Redis server" do
    session_store = Rack::Session::Redis.new(incrementor, redis_server: 'redis://127.0.0.1:6380/1', pool_size: 5, pool_timeout: 10)
    session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/)  }
  end

  it "can use a supplied pool" do
    session_store = Rack::Session::Redis.new(incrementor, pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1")})
    conn = session_store.instance_variable_get(:@conn)
    conn.pool.class.must_equal ::ConnectionPool
    conn.pool.instance_variable_get(:@size).must_equal 1
  end

  it "uses the specified Redis store when provided" do
    store = ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1')
    pool = Rack::Session::Redis.new(incrementor, :redis_store => store)
    pool.with do |p|
      p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/)
      p.must_equal(store)
    end
  end

  it "uses the default Redis server and namespace when not provided" do
    pool = Rack::Session::Redis.new(incrementor)
    pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/) }
  end

  it "uses the specified namespace when provided" do
    pool = Rack::Session::Redis.new(incrementor, :redis_server => {:namespace => 'test:rack:session'})
    pool.with { |p| p.to_s.must_match(/namespace test:rack:session$/) }
  end

  it "uses the specified Redis server when provided" do
    pool = Rack::Session::Redis.new(incrementor, :redis_server => 'redis://127.0.0.1:6380/1')
    pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) }
  end

  it "is threadsafe by default" do
    sesion_store = Rack::Session::Redis.new(incrementor)
    sesion_store.threadsafe?.must_equal(true)
  end

  it "locks the store mutex" do
    mutex = Mutex.new
    mutex.expects(:lock).once
    sesion_store = Rack::Session::Redis.new(incrementor)
    sesion_store.instance_variable_set(:@mutex, mutex)
    was_yielded = false
    sesion_store.with_lock({'rack.multithread' => true}) { was_yielded = true}
    was_yielded.must_equal(true)
  end

  describe "threadsafe disabled" do
    it "can have the global lock disabled" do
      sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false)
      sesion_store.threadsafe?.must_equal(false)
    end

    it "does not lock the store mutex" do
      mutex = Mutex.new
      mutex.expects(:lock).never
      sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false)
      sesion_store.instance_variable_set(:@mutex, mutex)
      was_yielded = false
      sesion_store.with_lock({'rack.multithread' => true}) { was_yielded = true}
      was_yielded.must_equal(true)<commit_msg>add spec to validate blank sessions are not stored in redis<commit_after>require 'test_helper'
require 'rack/mock'
require 'thread'
require 'connection_pool'

describe Rack::Session::Redis do
  session_key = Rack::Session::Redis::DEFAULT_OPTIONS[:key]
  session_match = /#{session_key}=([0-9a-fA-F]+);/
  incrementor = lambda do |env|
    env["rack.session"]["counter"] ||= 0
    env["rack.session"]["counter"] += 1
    Rack::Response.new(env["rack.session"].inspect).to_a
  end
  drop_session = proc do |env|
    env['rack.session.options'][:drop] = true
    incrementor.call(env)
  end
  renew_session = proc do |env|
    env['rack.session.options'][:renew] = true
    incrementor.call(env)
  end
  defer_session = proc do |env|
    env['rack.session.options'][:defer] = true
    incrementor.call(env)
  end
  skip_session = proc do |env|
    env['rack.session.options'][:skip] = true
    incrementor.call(env)
  end

  # # test Redis connection
  # Rack::Session::Redis.new(incrementor)
  #
  # it "faults on no connection" do
  #   lambda{
  #     Rack::Session::Redis.new(incrementor, :redis_server => 'nosuchserver')
  #   }.must_raise(Exception)
  # end

  it "can create it's own pool" do
    session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
    conn = session_store.instance_variable_get(:@conn)
    conn.pool.class.must_equal ::ConnectionPool
    conn.pool.instance_variable_get(:@size).must_equal 5
  end

  it "can create it's own pool using default Redis server" do
    session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
    session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/)  }
  end

  it "can create it's own pool using provided Redis server" do
    session_store = Rack::Session::Redis.new(incrementor, redis_server: 'redis://127.0.0.1:6380/1', pool_size: 5, pool_timeout: 10)
    session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/)  }
  end

  it "can use a supplied pool" do
    session_store = Rack::Session::Redis.new(incrementor, pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1")})
    conn = session_store.instance_variable_get(:@conn)
    conn.pool.class.must_equal ::ConnectionPool
    conn.pool.instance_variable_get(:@size).must_equal 1
  end

  it "uses the specified Redis store when provided" do
    store = ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1')
    pool = Rack::Session::Redis.new(incrementor, :redis_store => store)
    pool.with do |p|
      p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/)
      p.must_equal(store)
    end
  end

  it "uses the default Redis server and namespace when not provided" do
    pool = Rack::Session::Redis.new(incrementor)
    pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/) }
  end

  it "uses the specified namespace when provided" do
    pool = Rack::Session::Redis.new(incrementor, :redis_server => {:namespace => 'test:rack:session'})
    pool.with { |p| p.to_s.must_match(/namespace test:rack:session$/) }
  end

  it "uses the specified Redis server when provided" do
    pool = Rack::Session::Redis.new(incrementor, :redis_server => 'redis://127.0.0.1:6380/1')
    pool.with { |p| p.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) }
  end

  it "is threadsafe by default" do
    sesion_store = Rack::Session::Redis.new(incrementor)
    sesion_store.threadsafe?.must_equal(true)
  end

  it "does not store a blank session" do
    session_store = Rack::Session::Redis.new(incrementor)
    sid = session_store.generate_unique_sid({})
    session_store.with { |c| c.get(sid).must_be_nil }
  end

  it "locks the store mutex" do
    mutex = Mutex.new
    mutex.expects(:lock).once
    sesion_store = Rack::Session::Redis.new(incrementor)
    sesion_store.instance_variable_set(:@mutex, mutex)
    was_yielded = false
    sesion_store.with_lock({'rack.multithread' => true}) { was_yielded = true}
    was_yielded.must_equal(true)
  end

  describe "threadsafe disabled" do
    it "can have the global lock disabled" do
      sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false)
      sesion_store.threadsafe?.must_equal(false)
    end

    it "does not lock the store mutex" do
      mutex = Mutex.new
      mutex.expects(:lock).never
      sesion_store = Rack::Session::Redis.new(incrementor, :threadsafe => false)
      sesion_store.instance_variable_set(:@mutex, mutex)
      was_yielded = false
      sesion_store.with_lock({'rack.multithread' => true}) { was_yielded = true}
      was_yielded.must_equal(true)
{'fraction_non_alphanumeric': 0.14119565217391306, 'fraction_numerical': 0.025217391304347827, 'mean_word_length': 3.9494351802044108, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 8, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2113395', 'n_tokens_mistral': 3440, 'n_tokens_neox': 3225, 'n_words': 681}