File: servetests.lua

package info (click to toggle)
lua-ljsyscall 0.12-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,732 kB
  • sloc: ansic: 434; sh: 59; makefile: 3
file content (156 lines) | stat: -rw-r--r-- 3,194 bytes parent folder | download | duplicates (3)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
-- serve test results, in case operating in an environemnt with no console

local S = require "syscall"

-- exit will cause issues, override
os.exit = function() end

-- open output file
local outname = "output"
local fd = S.creat(outname, "rwxu")

-- set stdio to file, keep handle so not garbage collected
local stdin = S.dup2(fd, 0)
local stdout = S.dup2(fd, 1)
local stderr = S.dup2(fd, 2)

-- run tests
require "test.test"

local st = fd:stat()

-- close file
fd:close()

local results = S.util.readfile(outname, nil, st.size)

-- serve file - this code is borrowed from examples/epoll.lua
local t, c = S.t, S.c

local function assert(cond, s, ...)
  if cond == nil then error(tostring(s)) end -- annoyingly, assert does not call tostring!
  return cond, s, ...
end

local maxevents = 1024

local poll

-- this is somewhat working toward a common API but needs a lot more work, but has resulted in some improvements
if S.epoll_create then
  poll = {
    init = function(this)
      return setmetatable({fd = assert(S.epoll_create())}, {__index = this})
    end,
    event = t.epoll_event(),
    add = function(this, s)
      local event = this.event
      event.events = c.EPOLL.IN
      event.data.fd = s:getfd()
      assert(this.fd:epoll_ctl("add", s, event))
    end,
    events = t.epoll_events(maxevents),
    get = function(this)
      return this.fd:epoll_wait(this.events)
    end,
    eof = function(ev) return ev.HUP or ev.ERR or ev.RDHUP end,
  }
elseif S.kqueue then
  poll = {
    init = function(this)
      return setmetatable({fd = assert(S.kqueue())}, {__index = this})
    end,
    event = t.kevents(1),
    add = function(this, s)
      local event = this.event[1]
      event.fd = s
      event.setfilter = "read"
      event.setflags = "add"
      assert(this.fd:kevent(this.event, nil, 0))
    end,
    events = t.kevents(maxevents),
    get = function(this)
      return this.fd:kevent(nil, this.events)
    end,
    eof = function(ev) return ev.EOF or ev.ERROR end,
  }
else
  error("no epoll or kqueue support")
end

local s = assert(S.socket("inet", "stream, nonblock"))

s:setsockopt("socket", "reuseaddr", true)

local sa = assert(t.sockaddr_in(80, "0.0.0.0"))

assert(s:bind(sa))

assert(s:listen(128))

ep = poll:init()

ep:add(s)

local w = {}

local msg = [[
<html>
<head>
<title>performance test</title>
</head>
<body>
]] .. results .. [[
</body>
</html>
]]

local reply = table.concat({
"HTTP/1.0 200 OK",
"Content-type: text/html",
"Connection: close",
"Content-Length: " .. #msg,
"",
"",
}, "\r\n") .. msg


local bufsize = 4096
local buffer = t.buffer(bufsize)

local ss = t.sockaddr_storage()
local addrlen = t.socklen1(#ss)

local function loop()

for i, ev in ep:get() do

  if ep.eof(ev) then
    fd:close()
    w[ev.fileno] = nil
  end

  if ev.fd == s.filenum then -- server socket, accept
    repeat
      local a, err = s:accept("nonblock", ss, addrlen)
      if a then
        ep:add(a.fd)
        w[a.fd:getfd()] = a.fd
      end
    until not a
  else
    local fd = w[ev.fd]
    fd:read(buffer, bufsize)
    local n = fd:write(reply)
    assert(n == #reply)
    assert(fd:close())
    w[ev.fd] = nil
  end
end

return loop()

end

loop()