<commit_before>#!/usr/bin/env ruby

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'riemann'))
require 'riemann/client'
require 'bacon'
require 'set'

Bacon.summary_on_exit

include Riemann

describe Riemann::Client do
  before do
    @client = Client.new
#    clear
  end

  should 'send a state' do
    res = @client << {
      :state => 'ok',
      :service => 'test',
      :description => 'desc',
      :metric_f => 1.0
    }

    res.should == nil
  end

  def roundtrip_metric(m)
    @client.tcp << {
      :service => 'metric-test',
      :metric => m
    }
    @client["service = \"metric-test\" and metric = #{m}"].
      first.metric.should.equal m
  end

  should 'send longs' do
    roundtrip_metric 0
    roundtrip_metric -3
    roundtrip_metric 5
    roundtrip_metric -(2**63)
    roundtrip_metric(2**63 - 1)
  end

  should 'send doubles' do
    roundtrip_metric 0.0
    roundtrip_metric 12.0
    roundtrip_metric 1.2300000190734863
  end

  should 'send custom attributes' do
    event = Event.new(
      :service => 'custom',
      :state => 'ok',
      :cats => 'meow',
      :env => 'prod'
    )
    event[:sneak] = 'attack'
    @client.tcp << event
    event2 = @client['service = "custom"'].first
    event2.service.should == 'custom'
    event2.state.should == 'ok'
    event2[:cats].should == 'meow'
    event2[:env].should == 'prod'
    event2[:sneak].should == 'attack'
  end

  should 'send a state with a time' do
    t = Time.now.to_i - 10
    @client.tcp << {
      :state => 'ok',
      :service => 'test',
      :time => t
    }
    @client.query('service = "test"').events.first.time.should == t
  end

  should 'send a state without time' do
    @client.tcp << {
      :state => 'ok',
      :service => 'timeless test'
    }
    @client.query('service = "timeless test"').events.first.time.should == Time.now.to_i
  end

  should "query states" do
    @client << { :state => 'critical', :service => '1' }
    @client << { :state => 'warning', :service => '2' }
    @client << { :state => 'critical', :service => '3' }
    @client.query.events.
      map(&:service).to_set.should.superset ['1', '2', '3'].to_set
    @client.query('state = "critical" and (service = "1" or service = "2" or service = "3")').events.
      map(&:service).to_set.should == ['1', '3'].to_set
  end

  it '[]' do
#    @client['state = "critical"'].should == []
    @client << {:state => 'critical'}
    @client['state = "critical"'].first.state.should == 'critical'
  end

  should 'query quickly' do
    t1 = Time.now
    total = 1000
    total.times do |i|
      @client.query('state = "critical"')
    end
    t2 = Time.now

    rate = total / (t2 - t1)
    puts
    puts "#{rate} queries/sec"
    rate.should > 100
  end

  should 'be threadsafe' do
    concurrency = 10
    per_thread = 200
    total = concurrency * per_thread

    t1 = Time.now
    (0...concurrency).map do |i|
      Thread.new do
        per_thread.times do
          @client.tcp.<<({
            :state => 'ok',
            :service => 'test',
            :description => 'desc',
            :metric_f => 1.0
          })
        end
      end
    end.each do |t|
      t.join
    end
    t2 = Time.now

    rate = total / (t2 - t1)
    puts
    puts "#{rate} inserts/sec"
    rate.should > 100
  end

  should 'survive inactivity' do
    @client.tcp.<<({
      :state => 'warning',
      :service => 'test',
    })

    sleep 5

    @client.tcp.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true
  end

  should 'survive local close' do
    @client.tcp.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true

    @client.tcp.socket.close

    @client.tcp.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true
  end
end<commit_msg>spec/client.rb refactor: add UDP support<commit_after>#!/usr/bin/env ruby

require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'riemann'))
require 'riemann/client'
require 'bacon'
require 'set'

Bacon.summary_on_exit

include Riemann


def roundtrip_metric(m)
  @client_with_transport << {
    :service => 'metric-test',
    :metric => m
  }
  @client["service = \"metric-test\" and metric = #{m}"].
    first.metric.should.equal m
end


shared "a riemann client" do

  should 'be connected after sending' do
    @client_with_transport.connected?.should.be.false
    @client.connected?.should.be.false
    @client_with_transport << {:state => 'ok', :service => 'connected check' }
    @client_with_transport.connected?.should.be.true
    # NOTE: only single transport connected at this point, @client.connected? is still false until all transports used
  end

  should 'send longs' do
    roundtrip_metric 0
    roundtrip_metric -3
    roundtrip_metric 5
    roundtrip_metric -(2**63)
    roundtrip_metric(2**63 - 1)
  end

  should 'send doubles' do
    roundtrip_metric 0.0
    roundtrip_metric 12.0
    roundtrip_metric 1.2300000190734863
  end

  should 'send custom attributes' do
    event = Event.new(
      :service => 'custom',
      :state => 'ok',
      :cats => 'meow',
      :env => 'prod'
    )
    event[:sneak] = 'attack'
    @client_with_transport << event
    event2 = @client['service = "custom"'].first
    event2.service.should.equal 'custom'
    event2.state.should.equal 'ok'
    event2[:cats].should.equal 'meow'
    event2[:env].should.equal 'prod'
    event2[:sneak].should.equal 'attack'
  end

  should 'send a state with a time' do
    t = Time.now.to_i - 10
    @client_with_transport << {
      :state => 'ok',
      :service => 'test',
      :time => t
    }
    @client.query('service = "test"').events.first.time.should.equal t
  end

  should 'send a state without time' do
    @client_with_transport << {
      :state => 'ok',
      :service => 'timeless test'
    }
    @client.query('service = "timeless test"').events.first.time.should.equal Time.now.to_i
  end

  should "query states" do
    @client_with_transport << { :state => 'critical', :service => '1' }
    @client_with_transport << { :state => 'warning', :service => '2' }
    @client_with_transport << { :state => 'critical', :service => '3' }
    @client.query.events.
      map(&:service).to_set.should.superset ['1', '2', '3'].to_set
    @client.query('state = "critical" and (service = "1" or service = "2" or service = "3")').events.
      map(&:service).to_set.should.equal ['1', '3'].to_set
  end

  it '[]' do
#    @client['state = "critical"'].should == []
    @client_with_transport << {:state => 'critical'}
    @client['state = "critical"'].first.state.should.equal 'critical'
  end

  should 'query quickly' do
    t1 = Time.now
    total = 1000
    total.times do |i|
      @client.query('state = "critical"')
    end
    t2 = Time.now

    rate = total / (t2 - t1)
    puts "\n     #{"%.2f" % rate} queries/sec (#{"%.2f" % (1000/rate)}ms per query)"
    rate.should > 100
  end

  should 'be threadsafe' do
    concurrency = 10
    per_thread = 200
    total = concurrency * per_thread

    t1 = Time.now
    (0...concurrency).map do |i|
      Thread.new do
        per_thread.times do
          @client_with_transport.<<({
            :state => 'ok',
            :service => 'test',
            :description => 'desc',
            :metric_f => 1.0
          })
        end
      end
    end.each do |t|
      t.join
    end
    t2 = Time.now

    rate = total / (t2 - t1)
    puts "\n     #{"%.2f" % rate} inserts/sec (#{"%.2f" % (1000/rate)}ms per insert)"
    rate.should > @expected_rate
  end

end


describe "Riemann::Client (TCP transport)" do
  before do
    @client = Client.new
    @client_with_transport = @client.tcp
    @expected_rate = 100
  end
  behaves_like "a riemann client"

  should 'send a state' do
    res = @client_with_transport << {
      :state => 'ok',
      :service => 'test',
      :description => 'desc',
      :metric_f => 1.0
    }

    res.ok.should.be.true
    @client['service = "test"'].first.state.should.equal 'ok'
  end

  should 'survive inactivity' do
    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    })

    sleep 5

    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true
  end

  should 'survive local close' do
    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true

    @client.close

    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    }).ok.should.be.true
  end
end

describe "Riemann::Client (UDP transport)" do
  before do
    @client = Client.new
    @client_with_transport = @client.udp
    @expected_rate = 1000
  end
  behaves_like "a riemann client"

  should 'send a state' do
    res = @client_with_transport << {
      :state => 'ok',
      :service => 'test',
      :description => 'desc',
      :metric_f => 1.0
    }

    res.should.be.nil
    @client['service = "test"'].first.state.should.equal 'ok'
  end

  should 'survive inactivity' do
    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    })
    @client['service = "test"'].first.state.should.equal 'warning'

    sleep 5

    @client_with_transport.<<({
      :state => 'ok',
      :service => 'test',
    })
    @client['service = "test"'].first.state.should.equal 'ok'
  end

  should 'survive local close' do
    @client_with_transport.<<({
      :state => 'warning',
      :service => 'test',
    })
    @client['service = "test"'].first.state.should.equal 'warning'

    @client.close

    @client_with_transport.<<({
      :state => 'ok',
      :service => 'test',
    })
    @client['service = "test"'].first.state.should.equal 'ok'
  end

  should "raise Riemann::Client::Unsupported exception on query" do
    should.raise(Riemann::Client::Unsupported) { @client_with_transport['service = "test"'] }
    should.raise(Riemann::Client::Unsupported) { @client_with_transport.query('service = "test"') }
  end

end
{'fraction_non_alphanumeric': 0.16344236138811327, 'fraction_numerical': 0.017850019944156362, 'mean_word_length': 2.5201825201825203, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, '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': '2679751', 'n_tokens_mistral': 3605, 'n_tokens_neox': 3389, 'n_words': 801}