mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 02:15:38 +01:00 
			
		
		
		
	Testes reformulados.
This commit is contained in:
		| @@ -1,467 +1,484 @@ | ||||
| ----------------------------------------------------------------------------- | ||||
| -- LuaSocket automated test module | ||||
| -- testclnt.lua | ||||
| -- This is the client module. It connects with the server module and executes | ||||
| -- all tests. | ||||
| ----------------------------------------------------------------------------- | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Read command definitions | ||||
| ----------------------------------------------------------------------------- | ||||
| HOST = HOST or "localhost" | ||||
| assert(dofile("testcmd.lua")) | ||||
| test_debug_mode() | ||||
| PORT = PORT or "8080" | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Start control connection | ||||
| ----------------------------------------------------------------------------- | ||||
| new_test("initializing...") | ||||
| while control == nil do | ||||
| 	print("client: trying control connection...") | ||||
| 	control, err = connect(HOST, PORT) | ||||
| 	if control then | ||||
| 		print("client: control connection stablished!")  | ||||
| 	else | ||||
| 		_sleep(2) | ||||
| 	end | ||||
| function pass(...) | ||||
|     local s = call(format, arg) | ||||
|     write(s, "\n") | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Make sure server is ready for data transmission | ||||
| ----------------------------------------------------------------------------- | ||||
| function sync() | ||||
| 	send_command(SYNC) | ||||
| 	get_command() | ||||
| function fail(...) | ||||
|     local s = call(format, arg) | ||||
|     write("ERROR: ", s, "!\n") | ||||
|     exit() | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Close and reopen data connection, to get rid of any unread blocks | ||||
| ----------------------------------------------------------------------------- | ||||
| function reconnect() | ||||
| 	if data then  | ||||
| 		data:close()  | ||||
| 		send_command(CLOSE) | ||||
| 		data = nil | ||||
| 	end | ||||
| 	while data == nil do | ||||
| 		send_command(CONNECT) | ||||
| 		data = connect(HOST, PORT) | ||||
| 		if not data then  | ||||
| 			print("client: waiting for data connection.")  | ||||
| 			_sleep(1) | ||||
| 		end | ||||
| 	end | ||||
| 	sync() | ||||
| function warn(...) | ||||
|     local s = call(format, arg) | ||||
|     write("WARNING: ", s, "\n") | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests the command connection | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_command(cmd, par) | ||||
| 	local cmd_back, par_back | ||||
| 	reconnect() | ||||
| 	send_command(COMMAND) | ||||
| 	write("testing command ") | ||||
| 	print_command(cmd, par) | ||||
| 	send_command(cmd, par) | ||||
| 	cmd_back, par_back = get_command() | ||||
| 	if cmd_back ~= cmd or par_back ~= par then | ||||
| 		fail(cmd) | ||||
| 	else | ||||
| 		pass() | ||||
| 	end | ||||
| function remote(...) | ||||
|     local s = call(format, arg) | ||||
|     s = gsub(s, "\n", ";") | ||||
|     s = gsub(s, "%s+", " ") | ||||
|     s = gsub(s, "^%s*", "") | ||||
|     control:send(s, "\n") | ||||
|     control:receive() | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests ASCII line transmission | ||||
| -- Input | ||||
| --   len: length of line to be tested | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_asciiline(len) | ||||
| 	local str, str10, back, err | ||||
| 	reconnect() | ||||
| 	send_command(ECHO_LINE) | ||||
| 	str = strrep("x", mod(len, 10)) | ||||
| 	str10 = strrep("aZb.c#dAe?", floor(len/10)) | ||||
| 	str = str .. str10 | ||||
| 	write("testing ", len, " byte(s) line\n") | ||||
| 	err = data:send(str, "\n") | ||||
| 	if err then fail(err) end | ||||
| 	back, err = data:receive() | ||||
| 	if err then fail(err) end | ||||
| 	if back == str then pass("lines match") | ||||
| 	else fail("lines don't match") end | ||||
| function test(test) | ||||
|     write("----------------------------------------------\n", | ||||
|         "testing: ", test, "\n", | ||||
|         "----------------------------------------------\n") | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests multiple pattern transmission | ||||
| -- Input | ||||
| --   len: length of line to be tested | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_multiple() | ||||
| 	local p1 = "unix line\n" | ||||
| 	local p2 = "dos line\r\n" | ||||
| 	local p3 = "raw bytes" | ||||
| 	local bp1, bp2, bp3 | ||||
| 	reconnect() | ||||
| 	send_command(ECHO_BLOCK, strlen(p1)+strlen(p2)+strlen(p3)) | ||||
| 	err = data:send(p1, p2, p3) | ||||
| 	if err then fail(err) end | ||||
| 	bp1, bp2, bp3, err = data:receive("*lu", "*l", strlen(p3)) | ||||
| 	if err then fail(err) end | ||||
| 	if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 then  | ||||
| 		pass("patterns match") | ||||
| 	else fail("patterns don't match") end | ||||
| function check_timeout(tm, sl, elapsed, err, opp, mode, alldone) | ||||
|     if tm < sl then | ||||
|         if opp == "send" then | ||||
|             if not err then warn("must be buffered") | ||||
|             elseif err == "timeout" then pass("proper timeout") | ||||
|             else fail("unexpected error '%s'", err) end | ||||
|         else  | ||||
|             if err ~= "timeout" then fail("should have timed out")  | ||||
|             else pass("proper timeout") end | ||||
|         end | ||||
|     else | ||||
|         if mode == "return" then | ||||
|             if elapsed > tm then  | ||||
|                 if err ~= "timeout" then fail("should have timed out") | ||||
|                 else pass("proper timeout") end | ||||
|             elseif elapsed < tm then | ||||
|                 if err then fail(err)  | ||||
|                 else pass("ok") end | ||||
|             else  | ||||
|                 if alldone then  | ||||
|                     if err then fail("unexpected error '%s'", err)  | ||||
|                     else pass("ok") end | ||||
|                 else | ||||
|                     if err ~= "timeout" then fail(err)  | ||||
|                     else pass("proper timeoutk") end | ||||
|                 end | ||||
|             end | ||||
|         else  | ||||
|             if err then fail(err)  | ||||
|             else pass("ok") end  | ||||
|         end | ||||
|     end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests closed connection detection | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_closed() | ||||
| 	local str = "This is our little test line" | ||||
| 	local len = strlen(str) | ||||
| 	local back, err, total | ||||
| 	reconnect() | ||||
| 	print("testing close while reading line") | ||||
| 	send_command(ECHO_BLOCK, len) | ||||
| 	data:send(str) | ||||
| 	send_command(CLOSE) | ||||
| 	-- try to get a line  | ||||
| 	back, err = data:receive() | ||||
| 	if not err then fail("shold have gotten 'closed'.") | ||||
| 	elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.") | ||||
| 	elseif str ~= back then fail("didn't receive what i should 'closed'.") | ||||
| 	else pass("rightfull 'closed' received") end | ||||
| 	reconnect() | ||||
| 	print("testing close while reading block") | ||||
| 	send_command(ECHO_BLOCK, len) | ||||
| 	data:send(str) | ||||
| 	send_command(CLOSE) | ||||
| 	-- try to get a line  | ||||
| 	back, err = data:receive(2*len) | ||||
| 	if not err then fail("shold have gotten 'closed'.") | ||||
| 	elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.") | ||||
| 	elseif str ~= back then fail("didn't receive what I should.") | ||||
| 	else pass("rightfull 'closed' received") end | ||||
| end | ||||
| write("----------------------------------------------\n", | ||||
| "LuaSocket Test Procedures\n", | ||||
| "----------------------------------------------\n") | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests binary line transmission | ||||
| -- Input | ||||
| --   len: length of line to be tested | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_rawline(len) | ||||
| 	local str, str10, back, err | ||||
| 	reconnect() | ||||
| 	send_command(ECHO_LINE) | ||||
| 	str = strrep(strchar(47), mod(len, 10)) | ||||
| 	str10 = strrep(strchar(120,21,77,4,5,0,7,36,44,100), floor(len/10)) | ||||
| 	str = str .. str10 | ||||
| 	write("testing ", len, " byte(s) line\n") | ||||
| 	err = data:send(str, "\n") | ||||
| 	if err then fail(err) end | ||||
| 	back, err = data:receive() | ||||
| 	if err then fail(err) end | ||||
| 	if back == str then pass("lines match") | ||||
| 	else fail("lines don't match") end | ||||
| end | ||||
| if not _time or not _sleep then fail("not compiled with _DEBUG") end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests block transmission | ||||
| -- Input | ||||
| --   len: length of block to be tested | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_block(len) | ||||
| 	local half = floor(len/2) | ||||
| 	local s1, s2, back, err | ||||
| 	reconnect() | ||||
| 	send_command(ECHO_BLOCK, len) | ||||
| 	write("testing ", len, " byte(s) block\n") | ||||
| 	s1 = strrep("x", half) | ||||
| 	err = data:send(s1) | ||||
| 	if err then fail(err) end | ||||
| 	s2 = strrep("y", len-half) | ||||
| 	err = data:send(s2) | ||||
| 	if err then fail(err) end | ||||
| 	back, err = data:receive(len) | ||||
| 	if err then fail(err) end | ||||
| 	if back == s1..s2 then pass("blocks match") | ||||
| 	else fail("blocks don't match") end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests if return-timeout was respected  | ||||
| --   delta: time elapsed during transfer | ||||
| --   t: timeout value | ||||
| --   s: time server slept | ||||
| --   err: error code returned by I/O operation | ||||
| --   o: operation being executed | ||||
| ----------------------------------------------------------------------------- | ||||
| function blockedtimed_out(t, s, err, o) | ||||
| 	if err == "timeout" then | ||||
| 		if s >= t then | ||||
| 			pass("got rightfull forced timeout") | ||||
| 			return 1 | ||||
| 		else | ||||
| 			pass("got natural cause timeout") | ||||
| 			return 1 | ||||
| 		end | ||||
| 	elseif s > t then | ||||
| 		if o == "send" then | ||||
| 			pass("must have been buffered (may be wrong)") | ||||
| 		else | ||||
| 			fail("should have gotten timeout") | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests blocked-timeout conformance | ||||
| -- Input | ||||
| --   len: length of block to be tested | ||||
| --   t: timeout value | ||||
| --   s: server sleep between transfers | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_blockedtimeout(len, t, s) | ||||
| 	local str, err, back, total | ||||
| 	reconnect() | ||||
| 	send_command(RECEIVE_BLOCK, len) | ||||
| 	send_command(SLEEP, s) | ||||
| 	send_command(RECEIVE_BLOCK, len) | ||||
| 	write("testing ", len, " bytes, ", t,  | ||||
| 		"s block timeout, ", s, "s sleep\n") | ||||
| 	data:timeout(t) | ||||
| 	str = strrep("a", 2*len) | ||||
| 	err, total = data:send(str) | ||||
| 	if blockedtimed_out(t, s, err, "send") then return end | ||||
| 	if err then fail(err) end | ||||
| 	send_command(SEND_BLOCK) | ||||
| 	send_command(SLEEP, s) | ||||
| 	send_command(SEND_BLOCK) | ||||
| 	back, err = data:receive(2*len) | ||||
| 	if blockedtimed_out(t, s, err, "receive") then return end | ||||
| 	if err then fail(err) end | ||||
| 	if back == str then pass("blocks match") | ||||
| 	else fail("blocks don't match") end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests if return-timeout was respected  | ||||
| --   delta: time elapsed during transfer | ||||
| --   t: timeout value | ||||
| --   err: error code returned by I/O operation | ||||
| ----------------------------------------------------------------------------- | ||||
| function returntimed_out(delta, t, err) | ||||
| 	if err == "timeout" then | ||||
| 		if delta >= t then | ||||
| 			pass("got rightfull timeout") | ||||
| 			return 1 | ||||
| 		else | ||||
| 			fail("shouldn't have gotten timeout") | ||||
| 		end | ||||
| 	elseif delta > t then | ||||
| 		pass(format("but took %fs longer than should have", delta - t)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests return-timeout conformance | ||||
| -- Input | ||||
| --   len: length of block to be tested | ||||
| --   t: timeout value | ||||
| --   s: server sleep between transfers | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_returntimeout(len, t, s) | ||||
| 	local str, err, back, delta, total | ||||
| 	reconnect() | ||||
| 	send_command(RECEIVE_BLOCK, len) | ||||
| 	send_command(SLEEP, s) | ||||
| 	send_command(RECEIVE_BLOCK, len) | ||||
| 	write("testing ", len, " bytes, ", t,  | ||||
| 		"s return timeout, ", s, "s sleep\n") | ||||
| 	data:timeout(t, "return") | ||||
| 	str = strrep("a", 2*len) | ||||
| 	err, total, delta = data:send(str) | ||||
| 	print("sent in " .. delta .. "s") | ||||
| 	if returntimed_out(delta, t, err) then return end | ||||
| 	if err then fail("unexpected error: " .. err) end | ||||
| 	send_command(SEND_BLOCK) | ||||
| 	send_command(SLEEP, s) | ||||
| 	send_command(SEND_BLOCK) | ||||
| 	back, err, delta = data:receive(2*len) | ||||
| 	print("received in " .. delta .. "s") | ||||
| 	if returntimed_out(delta, t, err) then return end | ||||
| 	if err then fail("unexpected error: " .. err) end | ||||
| 	if back == str then pass("blocks match") | ||||
| 	else fail("blocks don't match") end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Tests read patterns | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_word() | ||||
|     local b1 = "  \t one two    three  \n this_is_a_very" | ||||
|     local b2 = "_big_word " | ||||
|     send_command(ECHO_BLOCK, strlen(b1)+strlen(b2)) | ||||
|     err = data:send(b1, b2) | ||||
|     local a1, a2, a3, a4 | ||||
|     a1, a2, a3, a4, err = data:receive("*w", "*w", "*w", "*w") | ||||
| 	if err then fail(err) end | ||||
|     _, err = data:receive(1) -- get last space | ||||
| 	if err then fail(err) end | ||||
|     if a1 ~= "one" or a2 ~= "two" or a3 ~= "three" or | ||||
|        a4 ~= "this_is_a_very_big_word" then fail("'*w' failed") end | ||||
|     pass("'*w' is ok") | ||||
| end | ||||
|  | ||||
| function test_patterns() | ||||
| 	local dos_line1 = "this the first dos line" | ||||
| 	local dos_line2 = "this is another dos line" | ||||
| 	local unix_line1 = "this the first unix line" | ||||
| 	local unix_line2 = "this is another unix line" | ||||
| 	local block = dos_line1 .. "\r\n" ..  dos_line2 .. "\r\n" | ||||
| 	reconnect() | ||||
|     block = block .. unix_line1 .. "\n" .. unix_line2 .. "\n" | ||||
| 	block = block .. block | ||||
| 	send_command(ECHO_BLOCK, strlen(block)) | ||||
| 	err = data:send(block) | ||||
| 	if err then fail(err) end | ||||
| 	local back = data:receive("*l") | ||||
| 	if back ~= dos_line1 then fail("'*l' failed") end | ||||
| 	back = data:receive("*l") | ||||
| 	if back ~= dos_line2 then fail("'*l' failed") end | ||||
| 	back = data:receive("*lu") | ||||
| 	if back ~= unix_line1 then fail("'*lu' failed") end | ||||
| 	back = data:receive("*lu") | ||||
| 	if back ~= unix_line2 then fail("'*lu' failed") end | ||||
| 	back = data:receive() | ||||
| 	if back ~= dos_line1 then fail("default failed") end | ||||
| 	back = data:receive() | ||||
| 	if back ~= dos_line2 then fail("default failed") end | ||||
| 	back = data:receive("*lu") | ||||
| 	if back ~= unix_line1 then fail("'*lu' failed") end | ||||
| 	back = data:receive("*lu") | ||||
| 	if back ~= unix_line2 then fail("'*lu' failed") end | ||||
| 	pass("line patterns are ok") | ||||
| 	send_command(ECHO_BLOCK, strlen(block)) | ||||
| 	err = data:send(block) | ||||
| 	if err then fail(err) end | ||||
| 	back = data:receive(strlen(block)) | ||||
| 	if back ~= block then fail("number failed") end | ||||
| 	pass("number is ok") | ||||
| 	test_word() | ||||
| 	send_command(ECHO_BLOCK, strlen(block)) | ||||
| 	send_command(SLEEP, 1) | ||||
| 	send_command(CLOSE) | ||||
| 	err = data:send(block) | ||||
| 	if err then fail(err) end | ||||
| 	back = data:receive("*a") | ||||
| 	if back ~= block then fail("'*a' failed") end | ||||
| 	pass("'*a' is ok") | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Test for select bugs | ||||
| ----------------------------------------------------------------------------- | ||||
| function test_select() | ||||
| 	local r, s, e = select(nil, nil, 0.1) | ||||
| 	assert(type(r) == "table" and type(s) == "table" and e == "timeout") | ||||
| 	pass("both nil") | ||||
| 	data:close() | ||||
| 	r, s, e = select({ data }, { data }, 0.1) | ||||
| 	assert(type(r) == "table" and type(s) == "table" and e == "timeout") | ||||
| 	pass("closed sockets") | ||||
| 	e = call(select, {"wrong", 1, 0.1}, "x", nil) | ||||
| 	assert(e == nil) | ||||
| 	pass("invalid input") | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Execute all tests | ||||
| ----------------------------------------------------------------------------- | ||||
| start = _time() | ||||
|  | ||||
| new_test("control connection test") | ||||
| test_command(EXIT) | ||||
| test_command(CONNECT) | ||||
| test_command(CLOSE) | ||||
| test_command(ECHO_BLOCK, 12234) | ||||
| test_command(SLEEP, 1111) | ||||
| test_command(ECHO_LINE) | ||||
| function tcpreconnect() | ||||
|     write("attempting data connection... ") | ||||
|     if data then data:close() end | ||||
|     remote [[ | ||||
|         if data then data:close() data = nil end | ||||
|         data = server:accept() | ||||
|     ]] | ||||
|     data, error = connect(HOST, PORT) | ||||
|     if not data then fail(error)  | ||||
|     else pass("connected!") end | ||||
| end | ||||
| reconnect = tcpreconnect | ||||
|  | ||||
| new_test("testing for select bugs") | ||||
| test_select() | ||||
| pass("attempting control connection...") | ||||
| control, error = connect(HOST, PORT) | ||||
| if error then fail(error) | ||||
| else pass("connected!") end | ||||
|  | ||||
| new_test("connection close test") | ||||
| test_closed() | ||||
| ------------------------------------------------------------------------ | ||||
| test("bugs") | ||||
|  | ||||
| new_test("read pattern test") | ||||
| test_patterns() | ||||
| write("empty host connect: ") | ||||
| function empty_connect() | ||||
|     if data then data:close() data = nil end | ||||
|     remote [[ | ||||
|         if data then data:close() data = nil end | ||||
|         data = server:accept() | ||||
|     ]] | ||||
|     data, err = connect("", PORT) | ||||
|     if not data then  | ||||
|         pass("ok") | ||||
|         data = connect(HOST, PORT) | ||||
|     else fail("should not have connected!") end | ||||
| end | ||||
|  | ||||
| new_test("multiple pattern test") | ||||
| test_multiple() | ||||
| empty_connect() | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("method registration") | ||||
|  | ||||
| function test_methods(sock, methods) | ||||
|     for _, v in methods do | ||||
|         if type(sock[v]) ~= "function" then  | ||||
|             fail(type(sock) .. " method " .. v .. "not registered")  | ||||
|         end | ||||
|     end | ||||
|     pass(type(sock) .. " methods are ok") | ||||
| end | ||||
|  | ||||
| test_methods(control, { | ||||
|     "close",  | ||||
|     "timeout",  | ||||
|     "send",  | ||||
|     "receive",  | ||||
|     "getpeername", | ||||
|     "getsockname" | ||||
| }) | ||||
|  | ||||
| if udpsocket then | ||||
|     test_methods(udpsocket(), { | ||||
|         "close",  | ||||
|         "timeout",  | ||||
|         "send",  | ||||
|         "sendto",  | ||||
|         "receive",  | ||||
|         "receivefrom",  | ||||
|         "getpeername", | ||||
|         "getsockname", | ||||
|         "setsockname", | ||||
|         "setpeername" | ||||
|     }) | ||||
| end | ||||
|  | ||||
| test_methods(bind("*", 0), { | ||||
|     "close",  | ||||
|     "timeout",  | ||||
|     "accept"  | ||||
| }) | ||||
|  | ||||
| if pipe then | ||||
|     local p1, p2 = pipe() | ||||
|     test_methods(p1, { | ||||
|         "close",  | ||||
|         "timeout",  | ||||
|         "send", | ||||
|         "receive"  | ||||
|     }) | ||||
|     test_methods(p2, { | ||||
|         "close",  | ||||
|         "timeout",  | ||||
|         "send", | ||||
|         "receive"  | ||||
|     }) | ||||
| end | ||||
|  | ||||
| if filesocket then | ||||
|     test_methods(filesocket(0), { | ||||
|         "close",  | ||||
|         "timeout",  | ||||
|         "send", | ||||
|         "receive"  | ||||
|     }) | ||||
| end | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("select function") | ||||
| function test_selectbugs() | ||||
|     local r, s, e = select(nil, nil, 0.1) | ||||
|     assert(type(r) == "table" and type(s) == "table" and e == "timeout") | ||||
|     pass("both nil: ok") | ||||
|     local udp = udpsocket() | ||||
|     udp:close() | ||||
|     r, s, e = select({ data }, { data }, 0.1) | ||||
|     assert(type(r) == "table" and type(s) == "table" and e == "timeout") | ||||
|     pass("closed sockets: ok") | ||||
|     e = call(select, {"wrong", 1, 0.1}, "x", nil) | ||||
|     assert(e == nil) | ||||
|     pass("invalid input: ok") | ||||
| end | ||||
|  | ||||
| test_selectbugs() | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("character line") | ||||
| reconnect() | ||||
|  | ||||
| function test_asciiline(len) | ||||
|     local str, str10, back, err | ||||
|     str = strrep("x", mod(len, 10)) | ||||
|     str10 = strrep("aZb.c#dAe?", floor(len/10)) | ||||
|     str = str .. str10 | ||||
|     pass(len .. " byte(s) line") | ||||
| remote "str = data:receive()" | ||||
|     err = data:send(str, "\n") | ||||
|     if err then fail(err) end | ||||
| remote "data:send(str, '\\n')" | ||||
|     back, err = data:receive() | ||||
|     if err then fail(err) end | ||||
|     if back == str then pass("lines match") | ||||
|     else fail("lines don't match") end | ||||
| end | ||||
|  | ||||
| new_test("character string test") | ||||
| test_asciiline(1) | ||||
| test_asciiline(17) | ||||
| test_asciiline(200) | ||||
| test_asciiline(3000) | ||||
| test_asciiline(80000) | ||||
| test_asciiline(4091) | ||||
| test_asciiline(80199) | ||||
| test_asciiline(800000) | ||||
|  | ||||
| new_test("binary string test") | ||||
| ------------------------------------------------------------------------ | ||||
| test("binary line") | ||||
| reconnect() | ||||
|  | ||||
| function test_rawline(len) | ||||
|     local str, str10, back, err | ||||
|     str = strrep(strchar(47), mod(len, 10)) | ||||
|     str10 = strrep(strchar(120,21,77,4,5,0,7,36,44,100), floor(len/10)) | ||||
|     str = str .. str10 | ||||
|     pass(len .. " byte(s) line") | ||||
| remote "str = data:receive()" | ||||
|     err = data:send(str, "\n") | ||||
|     if err then fail(err) end | ||||
| remote "data:send(str, '\\n')" | ||||
|     back, err = data:receive() | ||||
|     if err then fail(err) end | ||||
|     if back == str then pass("lines match") | ||||
|     else fail("lines don't match") end | ||||
| end | ||||
|  | ||||
| test_rawline(1) | ||||
| test_rawline(17) | ||||
| test_rawline(200) | ||||
| test_rawline(3000) | ||||
| test_rawline(8000) | ||||
| test_rawline(80000) | ||||
| test_rawline(4091) | ||||
| test_rawline(80199) | ||||
| test_rawline(800000) | ||||
| test_rawline(80199) | ||||
| test_rawline(4091) | ||||
| test_rawline(200) | ||||
| test_rawline(17) | ||||
| test_rawline(1) | ||||
|  | ||||
| new_test("blocking transfer test") | ||||
| test_block(1) | ||||
| test_block(17) | ||||
| test_block(200) | ||||
| test_block(3000) | ||||
| test_block(80000) | ||||
| test_block(800000) | ||||
| ------------------------------------------------------------------------ | ||||
| test("raw transfer") | ||||
| reconnect() | ||||
|  | ||||
| function test_raw(len) | ||||
|     local half = floor(len/2) | ||||
|     local s1, s2, back, err | ||||
|     s1 = strrep("x", half) | ||||
|     s2 = strrep("y", len-half) | ||||
|     pass(len .. " byte(s) block") | ||||
| remote (format("str = data:receive(%d)", len)) | ||||
|     err = data:send(s1) | ||||
|     if err then fail(err) end | ||||
|     err = data:send(s2) | ||||
|     if err then fail(err) end | ||||
| remote "data:send(str)" | ||||
|     back, err = data:receive(len) | ||||
|     if err then fail(err) end | ||||
|     if back == s1..s2 then pass("blocks match") | ||||
|     else fail("blocks don't match") end | ||||
| end | ||||
|  | ||||
| test_raw(1) | ||||
| test_raw(17) | ||||
| test_raw(200) | ||||
| test_raw(4091) | ||||
| test_raw(80199) | ||||
| test_raw(800000) | ||||
| test_raw(80199) | ||||
| test_raw(4091) | ||||
| test_raw(200) | ||||
| test_raw(17) | ||||
| test_raw(1) | ||||
| ------------------------------------------------------------------------ | ||||
| test("non-blocking transfer") | ||||
| reconnect() | ||||
|  | ||||
| new_test("non-blocking transfer test") | ||||
| -- the value is not important, we only want  | ||||
| -- to test non-blockin I/O anyways | ||||
| data:timeout(200) | ||||
| test_block(1) | ||||
| test_block(17) | ||||
| test_block(200) | ||||
| test_block(3000) | ||||
| test_block(80000) | ||||
| test_block(800000) | ||||
| test_raw(1) | ||||
| test_raw(17) | ||||
| test_raw(200) | ||||
| test_raw(4091) | ||||
| test_raw(80199) | ||||
| test_raw(800000) | ||||
| test_raw(80199) | ||||
| test_raw(4091) | ||||
| test_raw(200) | ||||
| test_raw(17) | ||||
| test_raw(1) | ||||
|  | ||||
| new_test("blocked timeout test") | ||||
| test_blockedtimeout(80, 1, 2) | ||||
| test_blockedtimeout(80, 2, 2) | ||||
| test_blockedtimeout(80, 3, 2) | ||||
| test_blockedtimeout(800, 1, 0) | ||||
| test_blockedtimeout(8000, 2, 3) | ||||
| test_blockedtimeout(80000, 2, 1) | ||||
| test_blockedtimeout(800000, 0.01, 0) | ||||
| ------------------------------------------------------------------------ | ||||
| test("mixed patterns") | ||||
| reconnect() | ||||
|  | ||||
| new_test("return timeout test") | ||||
| test_returntimeout(80, 2, 1) | ||||
| test_returntimeout(80, 1, 2) | ||||
| test_returntimeout(8000, 1, 2) | ||||
| test_returntimeout(80000, 2, 1) | ||||
| test_returntimeout(800000, 0.1, 0) | ||||
| test_returntimeout(800000, 2, 1) | ||||
| function test_mixed(len) | ||||
|     local inter = floor(len/3) | ||||
|     local p1 = "unix " .. strrep("x", inter) .. "line\n" | ||||
|     local p2 = "dos " .. strrep("y", inter) .. "line\r\n" | ||||
|     local p3 = "raw " .. strrep("z", inter) .. "bytes" | ||||
|     local bp1, bp2, bp3 | ||||
|     pass(len .. " byte(s) patterns") | ||||
| remote (format("str = data:receive(%d)", strlen(p1)+strlen(p2)+strlen(p3))) | ||||
|     err = data:send(p1, p2, p3) | ||||
|     if err then fail(err) end | ||||
| remote "data:send(str)" | ||||
|     bp1, bp2, bp3, err = data:receive("*lu", "*l", strlen(p3)) | ||||
|     if err then fail(err) end | ||||
|     if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 then | ||||
|         pass("patterns match") | ||||
|     else fail("patterns don't match") end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Close connection and exit server. We are done. | ||||
| ----------------------------------------------------------------------------- | ||||
| new_test("the library has passed all tests") | ||||
| print("client: closing connection with server") | ||||
| send_command(CLOSE) | ||||
| send_command(EXIT) | ||||
| control:close() | ||||
| print(format("time elapsed: %6.2fs", _time() - start)) | ||||
| print("client: exiting...") | ||||
| exit() | ||||
| test_mixed(1) | ||||
| test_mixed(17) | ||||
| test_mixed(200) | ||||
| test_mixed(4091) | ||||
| test_mixed(80199) | ||||
| test_mixed(800000) | ||||
| test_mixed(80199) | ||||
| test_mixed(4091) | ||||
| test_mixed(200) | ||||
| test_mixed(17) | ||||
| test_mixed(1) | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("closed connection detection") | ||||
|  | ||||
| function test_closed() | ||||
|     local back, err | ||||
|     local str = 'little string' | ||||
|     reconnect() | ||||
|     pass("trying read detection") | ||||
|     remote (format ([[ | ||||
|         data:send('%s') | ||||
|         data:close() | ||||
|         data = nil | ||||
|     ]], str)) | ||||
|     -- try to get a line  | ||||
|     back, err = data:receive() | ||||
|     if not err then fail("shold have gotten 'closed'.") | ||||
|     elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.") | ||||
|     elseif str ~= back then fail("didn't receive partial result.") | ||||
|     else pass("graceful 'closed' received") end | ||||
|     reconnect() | ||||
|     pass("trying write detection") | ||||
|     remote [[ | ||||
|         data:close() | ||||
|         data = nil | ||||
|     ]] | ||||
|     err, total = data:send(strrep("ugauga", 100000)) | ||||
|     if not err then  | ||||
| pass("failed: output buffer is at least %d bytes long!", total) | ||||
|     elseif err ~= "closed" then  | ||||
| fail("got '"..err.."' instead of 'closed'.") | ||||
|     else  | ||||
| pass("graceful 'closed' received after %d bytes were sent", total)  | ||||
|     end | ||||
| end | ||||
|  | ||||
| test_closed() | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("return timeout on receive") | ||||
| function test_blockingtimeoutreceive(len, tm, sl) | ||||
|     local str, err, total | ||||
|     reconnect() | ||||
|     pass("%d bytes, %ds return timeout, %ds pause", len, tm, sl) | ||||
|     remote (format ([[ | ||||
|         data:timeout(%d) | ||||
|         str = strrep('a', %d) | ||||
|         data:send(str) | ||||
|         print('server: sleeping for %ds') | ||||
|         _sleep(%d) | ||||
|         print('server: woke up') | ||||
|         data:send(str) | ||||
|     ]], 2*tm, len, sl, sl)) | ||||
|     data:timeout(tm, "return") | ||||
|     str, err, elapsed = data:receive(2*len) | ||||
|     check_timeout(tm, sl, elapsed, err, "receive", "return",  | ||||
|         strlen(str) == 2*len) | ||||
| end | ||||
| test_blockingtimeoutreceive(800091, 1, 3) | ||||
| test_blockingtimeoutreceive(800091, 2, 3) | ||||
| test_blockingtimeoutreceive(800091, 3, 2) | ||||
| test_blockingtimeoutreceive(800091, 3, 1) | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("return timeout on send") | ||||
| function test_returntimeoutsend(len, tm, sl) | ||||
|     local str, err, total | ||||
|     reconnect() | ||||
|     pass("%d bytes, %ds return timeout, %ds pause", len, tm, sl) | ||||
|     remote (format ([[ | ||||
|         data:timeout(%d) | ||||
|         str = data:receive(%d) | ||||
|         print('server: sleeping for %ds') | ||||
|         _sleep(%d) | ||||
|         print('server: woke up') | ||||
|         str = data:receive(%d) | ||||
|     ]], 2*tm, len, sl, sl, len)) | ||||
|     data:timeout(tm, "return") | ||||
|     str = strrep("a", 2*len) | ||||
|     err, total, elapsed = data:send(str) | ||||
|     check_timeout(tm, sl, elapsed, err, "send", "return",  | ||||
|         total == 2*len) | ||||
| end | ||||
| test_returntimeoutsend(800091, 1, 3) | ||||
| test_returntimeoutsend(800091, 2, 3) | ||||
| test_returntimeoutsend(800091, 3, 2) | ||||
| test_returntimeoutsend(800091, 3, 1) | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("blocking timeout on receive") | ||||
| function test_blockingtimeoutreceive(len, tm, sl) | ||||
|     local str, err, total | ||||
|     reconnect() | ||||
|     pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) | ||||
|     remote (format ([[ | ||||
|         data:timeout(%d) | ||||
|         str = strrep('a', %d) | ||||
|         data:send(str) | ||||
|         print('server: sleeping for %ds') | ||||
|         _sleep(%d) | ||||
|         print('server: woke up') | ||||
|         data:send(str) | ||||
|     ]], 2*tm, len, sl, sl)) | ||||
|     data:timeout(tm) | ||||
|     str, err, elapsed = data:receive(2*len) | ||||
|     check_timeout(tm, sl, elapsed, err, "receive", "blocking",  | ||||
|         strlen(str) == 2*len) | ||||
| end | ||||
| test_blockingtimeoutreceive(800091, 1, 3) | ||||
| test_blockingtimeoutreceive(800091, 2, 3) | ||||
| test_blockingtimeoutreceive(800091, 3, 2) | ||||
| test_blockingtimeoutreceive(800091, 3, 1) | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test("blocking timeout on send") | ||||
| function test_blockingtimeoutsend(len, tm, sl) | ||||
|     local str, err, total | ||||
|     reconnect() | ||||
|     pass("%d bytes, %ds blocking timeout, %ds pause", len, tm, sl) | ||||
|     remote (format ([[ | ||||
|         data:timeout(%d) | ||||
|         str = data:receive(%d) | ||||
|         print('server: sleeping for %ds') | ||||
|         _sleep(%d) | ||||
|         print('server: woke up') | ||||
|         str = data:receive(%d) | ||||
|     ]], 2*tm, len, sl, sl, len)) | ||||
|     data:timeout(tm) | ||||
|     str = strrep("a", 2*len) | ||||
|     err, total, elapsed = data:send(str) | ||||
|     check_timeout(tm, sl, elapsed, err, "send", "blocking", | ||||
|         total == 2*len) | ||||
| end | ||||
| test_blockingtimeoutsend(800091, 1, 3) | ||||
| test_blockingtimeoutsend(800091, 2, 3) | ||||
| test_blockingtimeoutsend(800091, 3, 2) | ||||
| test_blockingtimeoutsend(800091, 3, 1) | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test(format("done in %.2fs", _time() - start)) | ||||
|   | ||||
| @@ -1,96 +1,24 @@ | ||||
| ----------------------------------------------------------------------------- | ||||
| -- LuaSocket automated test module | ||||
| -- testsrvr.lua | ||||
| -- This is the server module. It's completely controled by the client module | ||||
| -- by the use of a control connection. | ||||
| ----------------------------------------------------------------------------- | ||||
| HOST = HOST or "localhost" | ||||
| PORT = PORT or "8080" | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Read command definitions | ||||
| ----------------------------------------------------------------------------- | ||||
| HOST = HOST or "*" | ||||
| assert(dofile("testcmd.lua")) | ||||
| test_debug_mode() | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Start control connection | ||||
| ----------------------------------------------------------------------------- | ||||
| server, err = bind(HOST, PORT) | ||||
| if not server then | ||||
| 	fail(err) | ||||
| 	exit(1) | ||||
| end | ||||
| print("server: waiting for control connection...") | ||||
| control = server:accept() | ||||
| print("server: control connection stablished!") | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Executes a command, detecting any possible failures | ||||
| -- Input | ||||
| --   cmd: command to be executed | ||||
| --   par: command parameters, if needed | ||||
| ----------------------------------------------------------------------------- | ||||
| function execute_command(cmd, par) | ||||
| 	if cmd == CONNECT then | ||||
| 		print("server: waiting for data connection...") | ||||
| 		data = server:accept() | ||||
| 		data:timeout(10) | ||||
| 		if not data then | ||||
| 			fail("server: unable to start data connection!") | ||||
| 		else | ||||
| 			print("server: data connection stablished!") | ||||
| 		end | ||||
| 	elseif cmd == CLOSE then | ||||
| 		print("server: closing connection with client...") | ||||
| 		if data then  | ||||
| 			data:close() | ||||
| 			data = nil | ||||
| 		end | ||||
| 	elseif cmd == ECHO_LINE then | ||||
| 		str, err = data:receive() | ||||
| 		if err then fail("server: " .. err) end | ||||
| 		err = data:send(str, "\n") | ||||
| 		if err then fail("server: " .. err) end | ||||
| 	elseif cmd == ECHO_BLOCK then | ||||
| 		str, err = data:receive(par) | ||||
| 		print(format("server: received %d bytes", strlen(str))) | ||||
| 		if err then fail("server: " .. err) end | ||||
| 		print(format("server: sending %d bytes", strlen(str))) | ||||
| 		err = data:send(str) | ||||
| 		if err then fail("server: " .. err) end | ||||
| 	elseif cmd == RECEIVE_BLOCK then | ||||
| 		str, err = data:receive(par) | ||||
| 		print(format("server: received %d bytes", strlen(str))) | ||||
| 	elseif cmd == SEND_BLOCK then | ||||
| 		print(format("server: sending %d bytes", strlen(str))) | ||||
| 		err = data:send(str) | ||||
| 	elseif cmd == ECHO_TIMEOUT then | ||||
| 		str, err = data:receive(par) | ||||
| 		if err then fail("server: " .. err) end | ||||
| 		err = data:send(str) | ||||
| 		if err then fail("server: " .. err) end | ||||
| 	elseif cmd == COMMAND then | ||||
| 		cmd, par = get_command() | ||||
| 		send_command(cmd, par) | ||||
| 	elseif cmd == EXIT then | ||||
| 		print("server: exiting...") | ||||
| 		exit(0) | ||||
| 	elseif cmd == SYNC then | ||||
| 		print("server: synchronizing...") | ||||
| 		send_command(SYNC) | ||||
| 	elseif cmd == SLEEP then | ||||
| 		print("server: sleeping for " .. par .. " seconds...") | ||||
| 		_sleep(par) | ||||
| 		print("server: woke up!") | ||||
| 	end | ||||
| end | ||||
|  | ||||
| ----------------------------------------------------------------------------- | ||||
| -- Loop forever, accepting and executing commands | ||||
| ----------------------------------------------------------------------------- | ||||
| server, error = bind(HOST, PORT) | ||||
| if not server then print("server: " .. tostring(error)) exit() end | ||||
| while 1 do | ||||
| 	cmd, par = get_command() | ||||
| 	if not cmd then fail("server: " .. par) end | ||||
| 	print_command(cmd, par) | ||||
| 	execute_command(cmd, par) | ||||
|     print("server: waiting for client connection..."); | ||||
|     control = server:accept() | ||||
|     while 1 do  | ||||
|         command, error = control:receive() | ||||
|         if error then | ||||
|             control:close() | ||||
|             print("server: closing connection...") | ||||
|             break | ||||
|         end | ||||
|         error = control:send("\n") | ||||
|         if error then | ||||
|             control:close() | ||||
|             print("server: closing connection...") | ||||
|             break | ||||
|         end | ||||
|         dostring(command) | ||||
|     end | ||||
| end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user