cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob 6f547e764bcad67a20f1018be2bac45ecfbd9be4 2851 bytes (raw)
$ git show HEAD:test/http_idle_expire.rb	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
 
#!/usr/bin/env ruby
# -*- encoding: binary -*-
# Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
require 'test/test_helper'
require 'io/wait'
require 'io/nonblock'

class TestHTTPIdleExpire < Test::Unit::TestCase
  def setup
    @to_close = []
    @host = TEST_HOST

    # skip tests under libkqueue, different versions may use more or less
    # descriptors in the background.  The functionality tested in this
    # file only works in Linux, and anybody running this under Linux
    # will want to use epoll directly instead of libkqueue.
    cmd_path = %x{which cmogstored}.chomp
    @kq = %x{ldd #{cmd_path}}.chomp.split(/\n/).grep(/libkqueue/)[0]
    return if @kq

    @tmpdir = Dir.mktmpdir('cmogstored-http-test')

    srv = TCPServer.new(@host, 0)
    @http_port = srv.addr[1]
    srv.close

    srv = TCPServer.new(@host, 0)
    @mgmt_port = srv.addr[1]
    srv.close

    cmd = [ "cmogstored", "--docroot=#@tmpdir",
            "--httplisten=#@host:#@http_port",
            "--mgmtlisten=#@host:#@mgmt_port",
            "--maxconns=500" ]
    @err = Tempfile.new("stderr")
    nofile = 20

    @pid = fork {
      Process.setrlimit(Process::RLIMIT_NOFILE, nofile)
      $stderr.reopen(@err)
      @err.close
      exec(*cmd)
    }
    @idle_timeout = 5
  end

  def test_idle_expire
    return if @kq

    # keep connecting until we don't get a response
    clients = []
    loop do
      c = get_client(300, @http_port)
      c.nonblock = true
      c.write "GET / HTTP/1.1\r\nHost: #@host:#@http_port\r\n\r\n"
      if c.wait(1)
        clients << c
      else # not accepted
        c.close
        break
      end
    end

    # drain the sockets
    clients.each do |c|
      while line = c.gets
        break if line == "\r\n"
      end
      c.write("G") # start the next request
    end

    # wait for timeouts to be valid
    sleep(@idle_timeout + 1)

    # start new clients to trigger keepalive expiry
    new_clients = clients.map do
      c = get_client(1, @http_port)
      c.nonblock = true
      assert_kind_of TCPSocket, c
      c
    end

    clients.each do |c|
      assert_equal [[c],[],[]], IO.select([c], nil, nil, 1)
      assert_nil c.gets, "expect nil (EOF)"
      c.close
    end
    new_clients.each do |c|
      c.write("GET / HTTP/1.0\r\n\r\n")
      assert c.wait(5)
      buf = c.read
      assert_match(%r{\AHTTP/1\.1 }, buf)
      assert_match(%r{\r\n\r\n\z}, buf)
      c.close
    end
  end

  def teardown
    return if @kq

    Process.kill(:QUIT, @pid) rescue nil
    _, status = Process.waitpid2(@pid)
    @to_close.each { |io| io.close unless io.closed? }
    FileUtils.rm_rf(@tmpdir)
    @err.rewind
    $stderr.write(@err.read)
    assert status.success?, status.inspect
  end
end if RUBY_PLATFORM =~ /linux/

git clone https://yhbt.net/cmogstored.git