<commit_before>require 'test_helper'
require 'test_rails_helper'

class TestController < ActionController::Base

  include Curbit::Controller

  def index
    render :text => 'index action'
  end

  rate_limit :index, :max_calls => 2,
                     :time_limit => 30.seconds,
                     :wait_time => 1.minute

  def show
    render :text => 'show action'
  end

  rate_limit :show, :max_calls => 2,
                    :time_limit => 30.seconds,
                    :wait_time => 1.minute,
                    :status => 200
end


class CurbiControllerTest < ActionController::TestCase
  tests TestController

  context "A controller including Curbit" do
    should "have a rate_limit class method" do
      assert_equal true, TestController.respond_to?(:rate_limit)
    end
  end

  context "When declaring a rate_limit method, there " do
      should "be a new rate_limit_method method added to the instance" do
          assert_equal true, @controller.respond_to?(:rate_limit_index)
      end
  end

  context "When calling a rate_limited method" do
    setup {
      Rails.cache = mock()
    }

    context "without a designated key argument" do
      context "and the remote client address is forwarded from a proxy, it" do
        setup {
          @env = {'HTTP_X_FORWARDED_FOR' => '192.168.1.123'}
          @request.stubs(:env).returns(@env)
          @cache_key = nil
          Rails.cache.expects(:write).with() {|key, val, duration|
            @cache_key = key
            true
          }
          Rails.cache.expects(:read).returns(nil)
        }

        should "use a default key that is derived from request.env['HTTP_X_FORWARDED_FOR']" do
          get :index
          ip = @env['HTTP_X_FORWARDED_FOR']
          pfx = Curbit::Controller::CacheKeyPrefix
          assert_equal "#{pfx}_#{TestController.name}_index_#{ip}", @cache_key
        end
      end #context: and the remote client address is...


      context "and the remote client address is a localhost address, it" do
        setup {
          @request.stubs(:remote_addr).returns("0.0.0.0")
          Rails.cache.expects(:read).never()
        }
        should "ignore rate limiting" do
          get :index
          assert_equal "index action", @response.body
        end
      end

    end #context: without a designated key argument...

    context "from a remote client" do
      setup {
        @env = {'HTTP_X_FORWARDED_FOR' => '192.168.1.123'}
        @request.stubs(:env).returns(@env)
      }
      context "and max calls has been exceeded for the current time limit" do
        setup {
          cache_value = {:started => Time.now.to_i - 15.seconds,
                         :count => 1
                         }
          Rails.cache.stubs(:read).returns(cache_value)
          Rails.cache.stubs(:write)
        }
        context ", the call" do
          should "be blocked" do
            get :index
            assert_equal "index action", @response.body
            get :index
            assert_equal true, @response.body.include?("wait")
            # default status on a limit
            assert_equal "503 Service Unavailable", @response.status
          end

          should "be blocked and render a custom status when specified" do
            get :show
            assert_equal "show action", @response.body<commit_msg>fixed expectations and incremented count for in mocked cache data<commit_after>require 'test_helper'
require 'test_rails_helper'

class TestController < ActionController::Base

  include Curbit::Controller

  def index
    render :text => 'index action'
  end

  rate_limit :index, :max_calls => 2,
                     :time_limit => 30.seconds,
                     :wait_time => 1.minute

  def show
    render :text => 'show action'
  end

  rate_limit :show, :max_calls => 2,
                    :time_limit => 30.seconds,
                    :wait_time => 1.minute,
                    :status => 200
end


class CurbiControllerTest < ActionController::TestCase
  tests TestController

  context "A controller including Curbit" do
    should "have a rate_limit class method" do
      assert_equal true, TestController.respond_to?(:rate_limit)
    end
  end

  context "When declaring a rate_limit method, there " do
      should "be a new rate_limit_method method added to the instance" do
          assert_equal true, @controller.respond_to?(:rate_limit_index)
      end
  end

  context "When calling a rate_limited method" do
    setup {
      Rails.cache = mock()
    }

    context "without a designated key argument" do
      context "and the remote client address is forwarded from a proxy, it" do
        setup {
          @env = {'HTTP_X_FORWARDED_FOR' => '192.168.1.123'}
          @request.stubs(:env).returns(@env)
          @cache_key = nil
          Rails.cache.expects(:write).with() {|key, val, duration|
            @cache_key = key
            true
          }
          Rails.cache.expects(:read).returns(nil)
        }

        should "use a default key that is derived from request.env['HTTP_X_FORWARDED_FOR']" do
          get :index
          ip = @env['HTTP_X_FORWARDED_FOR']
          pfx = Curbit::Controller::CacheKeyPrefix
          assert_equal "#{pfx}_#{TestController.name}_index_#{ip}", @cache_key
        end
      end #context: and the remote client address is...


      context "and the remote client address is a localhost address, it" do
        setup {
          @request.stubs(:remote_addr).returns("0.0.0.0")
          Rails.cache.expects(:read).never()
        }
        should "ignore rate limiting" do
          get :index
          assert_equal "index action", @response.body
        end
      end

    end #context: without a designated key argument...

    context "from a remote client" do
      setup {
        @env = {'HTTP_X_FORWARDED_FOR' => '192.168.1.123'}
        @request.stubs(:env).returns(@env)
      }
      context "and max calls has been exceeded for the current time limit" do
        setup {
          # emulate the state needed to indicate that we've started
          # waiting on calls
          cache_value = {:started => Time.now.to_i - 15.seconds,
                         :count => 1
                         }
          Rails.cache.stubs(:read).returns(cache_value)
          Rails.cache.stubs(:write).with() {|key, val, duration|
            cache_value[:count] = val[:count]
            true;
          }
        }
        context ", the call" do
          should "be blocked" do
            get :index
            assert_equal "index action", @response.body
            get :index
            assert_equal true, @response.body.include?("wait")
            # default status on a limit
            assert_equal "503 Service Unavailable", @response.status
          end

          should "be blocked and render a custom status when specified" do
            get :show
            assert_equal "show action", @response.body
{'fraction_non_alphanumeric': 0.09300316729052692, 'fraction_numerical': 0.011805355600345523, 'mean_word_length': 2.0323003055434308, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 6, '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': '6866348', 'n_tokens_mistral': 2005, 'n_tokens_neox': 1895, 'n_words': 582}